Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add default event filter #1140

Merged
merged 10 commits into from
Aug 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ else

all: build

.PHONY: vendor
vendor:
go mod tidy
go mod vendor
Expand Down
51 changes: 26 additions & 25 deletions docs/docs/20-usage/20-pipeline-syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ pipeline:

Woodpecker gives the ability to skip individual commits by adding `[CI SKIP]` to the commit message. Note this is case-insensitive.

```diff
```sh
git commit -m "updated README [CI SKIP]"
```

Expand Down Expand Up @@ -234,7 +234,7 @@ Commands of every pipeline step are executed serially as if you would enter them

There is no magic here. The above commands are converted to a simple shell script. The commands in the above example are roughly converted to the below script:

```diff
```sh
#!/bin/sh
set -e

Expand All @@ -244,7 +244,7 @@ go test

The above shell script is then executed as the container entrypoint. The below docker command is an (incomplete) example of how the script is executed:

```bash
```sh
docker run --entrypoint=build.sh golang
```

Expand Down Expand Up @@ -315,21 +315,21 @@ pipeline:

Execute a step if the branch is `master` or `develop`:

```diff
```yaml
when:
- branch: [master, develop]
```

Execute a step if the branch starts with `prefix/*`:

```diff
```yaml
when:
- branch: prefix/*
```

Execute a step using custom include and exclude logic:

```diff
```yaml
when:
- branch:
include: [ master, release/* ]
Expand All @@ -338,9 +338,17 @@ when:

#### `event`

:::info
**By default steps are filtered by following event types:**

`push`, `pull_request, `tag`, `deployment`.
:::

Available events: `push`, `pull_request`, `tag`, `deployment`

Execute a step if the build event is a `tag`:

```diff
```yaml
when:
- event: tag
```
Expand All @@ -353,26 +361,19 @@ when:
+ branch: main
```

Execute a step for all non-pull request events:
Execute a step for multiple events:

```diff
```yaml
when:
- event: [push, tag, deployment]
```

anbraten marked this conversation as resolved.
Show resolved Hide resolved
Execute a step for all build events:

```diff
when:
- event: [push, pull_request, tag, deployment]
```

#### `tag`

This filter only applies to tag events.
Use glob expression to execute a step if the tag name starts with `v`:

```diff
```yaml
when:
- event: tag
tag: v*
Expand Down Expand Up @@ -400,14 +401,14 @@ This condition should be used in conjunction with a [matrix](/docs/usage/matrix-

Execute a step for a specific platform:

```diff
```yaml
when:
- platform: linux/amd64
```

Execute a step for a specific platform using wildcards:

```diff
```yaml
when:
- platform: [ linux/*, windows/amd64 ]
```
Expand All @@ -416,7 +417,7 @@ when:

Execute a step for deployment events matching the target deployment environment:

```diff
```yaml
when:
- environment: production
- event: deployment
Expand All @@ -426,7 +427,7 @@ when:

Execute a step for a single matrix permutation:

```diff
```yaml
when:
- matrix:
GO_VERSION: 1.5
Expand All @@ -437,7 +438,7 @@ when:

Execute a step only on a certain Woodpecker instance matching the specified hostname:

```diff
```yaml
when:
- instance: stage.woodpecker.company.com
```
Expand All @@ -452,14 +453,14 @@ Gitea only support **push** at the moment ([go-gitea/gitea#18228](https://github

Execute a step only on a pipeline with certain files being changed:

```diff
```yaml
when:
- path: "src/*"
```

You can use [glob patterns](https://github.com/bmatcuk/doublestar#patterns) to match the changed files and specify if the step should run if a file matching that pattern has been changed `include` or if some files have **not** been changed `exclude`.

```diff
```yaml
when:
- path:
include: [ '.woodpecker/*.yml', '*.ini' ]
Expand Down Expand Up @@ -559,7 +560,7 @@ The base attribute defines a shared base volume available to all pipeline steps.

This would be equivalent to the following docker commands:

```bash
```sh
docker volume create my-named-volume

docker run --volume=my-named-volume:/go golang:latest
Expand Down
23 changes: 22 additions & 1 deletion pipeline/frontend/yaml/constraint/constraint.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,13 @@ func (when *When) Match(metadata frontend.Metadata) bool {
return true
}
}
return when.IsEmpty()

if when.IsEmpty() {
// test against default Constraints
empty := &Constraint{}
return empty.Match(metadata)
}
return false
}

func (when *When) IncludesStatus(status string) bool {
Expand Down Expand Up @@ -120,6 +126,16 @@ func (when *When) UnmarshalYAML(value *yaml.Node) error {
// Match returns true if all constraints match the given input. If a single
// constraint fails a false value is returned.
func (c *Constraint) Match(metadata frontend.Metadata) bool {
// if event filter is not set, set default
if c.Event.IsEmpty() {
c.Event.Include = []string{
frontend.EventPush,
frontend.EventPull,
frontend.EventTag,
frontend.EventDeploy,
}
}

match := c.Platform.Match(metadata.Sys.Platform) &&
c.Environment.Match(metadata.Curr.Target) &&
c.Event.Match(metadata.Curr.Event) &&
Expand All @@ -140,6 +156,11 @@ func (c *Constraint) Match(metadata frontend.Metadata) bool {
return match
}

// IsEmpty return true if a constraint has no conditions
func (c List) IsEmpty() bool {
return len(c.Include) == 0 && len(c.Exclude) == 0
}

// Match returns true if the string matches the include patterns and does not
// match any of the exclude patterns.
func (c *List) Match(v string) bool {
Expand Down
75 changes: 42 additions & 33 deletions pipeline/frontend/yaml/constraint/constraint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -383,89 +383,98 @@ func TestConstraintMap(t *testing.T) {

func TestConstraints(t *testing.T) {
testdata := []struct {
desc string
conf string
with frontend.Metadata
want bool
}{
// no constraints, must match
{
desc: "no constraints, must match on default events",
conf: "",
with: frontend.Metadata{},
with: frontend.Metadata{
Curr: frontend.Build{
Event: frontend.EventPush,
},
},
want: true,
},
// branch constraint
{
desc: "global branch filter",
conf: "{ branch: develop }",
with: frontend.Metadata{Curr: frontend.Build{Commit: frontend.Commit{Branch: "master"}}},
with: frontend.Metadata{Curr: frontend.Build{Event: frontend.EventPush, Commit: frontend.Commit{Branch: "master"}}},
want: false,
},
{
desc: "global branch filter",
conf: "{ branch: master }",
with: frontend.Metadata{Curr: frontend.Build{Commit: frontend.Commit{Branch: "master"}}},
with: frontend.Metadata{Curr: frontend.Build{Event: frontend.EventPush, Commit: frontend.Commit{Branch: "master"}}},
want: true,
},
// environment constraint
{
conf: "{ branch: develop }",
with: frontend.Metadata{Curr: frontend.Build{Commit: frontend.Commit{Branch: "master"}}},
want: false,
},
{
conf: "{ branch: master }",
with: frontend.Metadata{Curr: frontend.Build{Commit: frontend.Commit{Branch: "master"}}},
want: true,
},
// repo constraint
{
desc: "repo constraint",
conf: "{ repo: owner/* }",
with: frontend.Metadata{Repo: frontend.Repo{Name: "owner/repo"}},
with: frontend.Metadata{Curr: frontend.Build{Event: frontend.EventPush}, Repo: frontend.Repo{Name: "owner/repo"}},
want: true,
},
{
desc: "repo constraint",
conf: "{ repo: octocat/* }",
with: frontend.Metadata{Repo: frontend.Repo{Name: "owner/repo"}},
with: frontend.Metadata{Curr: frontend.Build{Event: frontend.EventPush}, Repo: frontend.Repo{Name: "owner/repo"}},
want: false,
},
// ref constraint
{
desc: "ref constraint",
conf: "{ ref: refs/tags/* }",
with: frontend.Metadata{Curr: frontend.Build{Commit: frontend.Commit{Ref: "refs/tags/v1.0.0"}}},
with: frontend.Metadata{Curr: frontend.Build{Commit: frontend.Commit{Ref: "refs/tags/v1.0.0"}, Event: frontend.EventPush}},
want: true,
},
{
desc: "ref constraint",
conf: "{ ref: refs/tags/* }",
with: frontend.Metadata{Curr: frontend.Build{Commit: frontend.Commit{Ref: "refs/heads/master"}}},
with: frontend.Metadata{Curr: frontend.Build{Commit: frontend.Commit{Ref: "refs/heads/master"}, Event: frontend.EventPush}},
want: false,
},
// platform constraint
{
desc: "platform constraint",
conf: "{ platform: linux/amd64 }",
with: frontend.Metadata{Sys: frontend.System{Platform: "linux/amd64"}},
with: frontend.Metadata{Curr: frontend.Build{Event: frontend.EventPush}, Sys: frontend.System{Platform: "linux/amd64"}},
want: true,
},
{
desc: "platform constraint",
conf: "{ repo: linux/amd64 }",
with: frontend.Metadata{Sys: frontend.System{Platform: "windows/amd64"}},
with: frontend.Metadata{Curr: frontend.Build{Event: frontend.EventPush}, Sys: frontend.System{Platform: "windows/amd64"}},
want: false,
},
// instance constraint
{
desc: "instance constraint",
conf: "{ instance: agent.tld }",
with: frontend.Metadata{Sys: frontend.System{Host: "agent.tld"}},
with: frontend.Metadata{Curr: frontend.Build{Event: frontend.EventPush}, Sys: frontend.System{Host: "agent.tld"}},
want: true,
},
{
desc: "instance constraint",
conf: "{ instance: agent.tld }",
with: frontend.Metadata{Sys: frontend.System{Host: "beta.agent.tld"}},
with: frontend.Metadata{Curr: frontend.Build{Event: frontend.EventPush}, Sys: frontend.System{Host: "beta.agent.tld"}},
want: false,
},
{
desc: "no constraints, and event get filtered by default default event filter",
conf: "",
with: frontend.Metadata{
Curr: frontend.Build{Event: "non-default"},
},
want: false,
},
}
for _, test := range testdata {
c := parseConstraints(t, test.conf)
got, want := c.Match(test.with), test.want
if got != want {
t.Errorf("Expect %+v matches %q is %v", test.with, test.conf, want)
}
t.Run(test.desc, func(t *testing.T) {
c := parseConstraints(t, test.conf)
got, want := c.Match(test.with), test.want
if got != want {
t.Errorf("Expect %+v matches %q is %v", test.with, test.conf, want)
}
})
}
}

Expand Down
12 changes: 7 additions & 5 deletions pipeline/schema/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,11 @@
"oneOf": [
{
"type": "array",
"items": {
"enum": ["push", "pull_request", "tag", "deployment"]
},
"minLength": 1
"minLength": 1,
"items": { "$ref": "#/definitions/event_enum" }
},
{
"enum": ["push", "pull_request", "tag", "deployment"]
"$ref": "#/definitions/event_enum"
}
]
},
Expand Down Expand Up @@ -270,6 +268,10 @@
}
}
},
"event_enum": {
"default": ["push", "pull_request", "tag", "deployment"],
"enum": ["push", "pull_request", "tag", "deployment"]
},
"step_image": {
"description": "Read more: https://woodpecker-ci.org/docs/usage/pipeline-syntax#image",
"type": "string"
Expand Down
4 changes: 3 additions & 1 deletion server/shared/procBuilder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,9 @@ depends_on: [ shouldbefiltered ]
func TestTree(t *testing.T) {
t.Parallel()

build := &model.Build{}
build := &model.Build{
Event: model.EventPush,
}

b := ProcBuilder{
Repo: &model.Repo{},
Expand Down