Add default event filter (#1140)

breakout from #934

when new events are added you don't have to worry that pipeline will behave different as it does now with this

Co-authored-by: Anbraten <anton@ju60.de>
This commit is contained in:
6543 2022-08-30 00:36:37 +02:00 committed by GitHub
parent 7e18e69563
commit ca84f703e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 101 additions and 65 deletions

View file

@ -52,6 +52,7 @@ else
all: build all: build
.PHONY: vendor
vendor: vendor:
go mod tidy go mod tidy
go mod vendor go mod vendor

View file

@ -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. 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]" git commit -m "updated README [CI SKIP]"
``` ```
@ -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: 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 #!/bin/sh
set -e set -e
@ -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: 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 docker run --entrypoint=build.sh golang
``` ```
@ -315,21 +315,21 @@ pipeline:
Execute a step if the branch is `master` or `develop`: Execute a step if the branch is `master` or `develop`:
```diff ```yaml
when: when:
- branch: [master, develop] - branch: [master, develop]
``` ```
Execute a step if the branch starts with `prefix/*`: Execute a step if the branch starts with `prefix/*`:
```diff ```yaml
when: when:
- branch: prefix/* - branch: prefix/*
``` ```
Execute a step using custom include and exclude logic: Execute a step using custom include and exclude logic:
```diff ```yaml
when: when:
- branch: - branch:
include: [ master, release/* ] include: [ master, release/* ]
@ -338,9 +338,17 @@ when:
#### `event` #### `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`: Execute a step if the build event is a `tag`:
```diff ```yaml
when: when:
- event: tag - event: tag
``` ```
@ -353,26 +361,19 @@ when:
+ branch: main + branch: main
``` ```
Execute a step for all non-pull request events: Execute a step for multiple events:
```diff ```yaml
when: when:
- event: [push, tag, deployment] - event: [push, tag, deployment]
``` ```
Execute a step for all build events:
```diff
when:
- event: [push, pull_request, tag, deployment]
```
#### `tag` #### `tag`
This filter only applies to tag events. This filter only applies to tag events.
Use glob expression to execute a step if the tag name starts with `v`: Use glob expression to execute a step if the tag name starts with `v`:
```diff ```yaml
when: when:
- event: tag - event: tag
tag: v* tag: v*
@ -400,14 +401,14 @@ This condition should be used in conjunction with a [matrix](/docs/usage/matrix-
Execute a step for a specific platform: Execute a step for a specific platform:
```diff ```yaml
when: when:
- platform: linux/amd64 - platform: linux/amd64
``` ```
Execute a step for a specific platform using wildcards: Execute a step for a specific platform using wildcards:
```diff ```yaml
when: when:
- platform: [ linux/*, windows/amd64 ] - platform: [ linux/*, windows/amd64 ]
``` ```
@ -416,7 +417,7 @@ when:
Execute a step for deployment events matching the target deployment environment: Execute a step for deployment events matching the target deployment environment:
```diff ```yaml
when: when:
- environment: production - environment: production
- event: deployment - event: deployment
@ -426,7 +427,7 @@ when:
Execute a step for a single matrix permutation: Execute a step for a single matrix permutation:
```diff ```yaml
when: when:
- matrix: - matrix:
GO_VERSION: 1.5 GO_VERSION: 1.5
@ -437,7 +438,7 @@ when:
Execute a step only on a certain Woodpecker instance matching the specified hostname: Execute a step only on a certain Woodpecker instance matching the specified hostname:
```diff ```yaml
when: when:
- instance: stage.woodpecker.company.com - instance: stage.woodpecker.company.com
``` ```
@ -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: Execute a step only on a pipeline with certain files being changed:
```diff ```yaml
when: when:
- path: "src/*" - 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`. 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: when:
- path: - path:
include: [ '.woodpecker/*.yml', '*.ini' ] include: [ '.woodpecker/*.yml', '*.ini' ]
@ -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: This would be equivalent to the following docker commands:
```bash ```sh
docker volume create my-named-volume docker volume create my-named-volume
docker run --volume=my-named-volume:/go golang:latest docker run --volume=my-named-volume:/go golang:latest

View file

@ -63,7 +63,13 @@ func (when *When) Match(metadata frontend.Metadata) bool {
return true 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 { func (when *When) IncludesStatus(status string) bool {
@ -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 // Match returns true if all constraints match the given input. If a single
// constraint fails a false value is returned. // constraint fails a false value is returned.
func (c *Constraint) Match(metadata frontend.Metadata) bool { 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) && match := c.Platform.Match(metadata.Sys.Platform) &&
c.Environment.Match(metadata.Curr.Target) && c.Environment.Match(metadata.Curr.Target) &&
c.Event.Match(metadata.Curr.Event) && c.Event.Match(metadata.Curr.Event) &&
@ -140,6 +156,11 @@ func (c *Constraint) Match(metadata frontend.Metadata) bool {
return match 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 returns true if the string matches the include patterns and does not
// match any of the exclude patterns. // match any of the exclude patterns.
func (c *List) Match(v string) bool { func (c *List) Match(v string) bool {

View file

@ -383,89 +383,98 @@ func TestConstraintMap(t *testing.T) {
func TestConstraints(t *testing.T) { func TestConstraints(t *testing.T) {
testdata := []struct { testdata := []struct {
desc string
conf string conf string
with frontend.Metadata with frontend.Metadata
want bool want bool
}{ }{
// no constraints, must match
{ {
desc: "no constraints, must match on default events",
conf: "", conf: "",
with: frontend.Metadata{}, with: frontend.Metadata{
Curr: frontend.Build{
Event: frontend.EventPush,
},
},
want: true, want: true,
}, },
// branch constraint
{ {
desc: "global branch filter",
conf: "{ branch: develop }", 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, want: false,
}, },
{ {
desc: "global branch filter",
conf: "{ branch: master }", 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, 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/* }", 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, want: true,
}, },
{ {
desc: "repo constraint",
conf: "{ repo: octocat/* }", 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, want: false,
}, },
// ref constraint
{ {
desc: "ref constraint",
conf: "{ ref: refs/tags/* }", 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, want: true,
}, },
{ {
desc: "ref constraint",
conf: "{ ref: refs/tags/* }", 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, want: false,
}, },
// platform constraint
{ {
desc: "platform constraint",
conf: "{ platform: linux/amd64 }", 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, want: true,
}, },
{ {
desc: "platform constraint",
conf: "{ repo: linux/amd64 }", 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, want: false,
}, },
// instance constraint
{ {
desc: "instance constraint",
conf: "{ instance: agent.tld }", 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, want: true,
}, },
{ {
desc: "instance constraint",
conf: "{ instance: agent.tld }", 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, want: false,
}, },
} }
for _, test := range testdata { for _, test := range testdata {
c := parseConstraints(t, test.conf) t.Run(test.desc, func(t *testing.T) {
got, want := c.Match(test.with), test.want c := parseConstraints(t, test.conf)
if got != want { got, want := c.Match(test.with), test.want
t.Errorf("Expect %+v matches %q is %v", test.with, test.conf, want) if got != want {
} t.Errorf("Expect %+v matches %q is %v", test.with, test.conf, want)
}
})
} }
} }

View file

@ -186,13 +186,11 @@
"oneOf": [ "oneOf": [
{ {
"type": "array", "type": "array",
"items": { "minLength": 1,
"enum": ["push", "pull_request", "tag", "deployment"] "items": { "$ref": "#/definitions/event_enum" }
},
"minLength": 1
}, },
{ {
"enum": ["push", "pull_request", "tag", "deployment"] "$ref": "#/definitions/event_enum"
} }
] ]
}, },
@ -270,6 +268,10 @@
} }
} }
}, },
"event_enum": {
"default": ["push", "pull_request", "tag", "deployment"],
"enum": ["push", "pull_request", "tag", "deployment"]
},
"step_image": { "step_image": {
"description": "Read more: https://woodpecker-ci.org/docs/usage/pipeline-syntax#image", "description": "Read more: https://woodpecker-ci.org/docs/usage/pipeline-syntax#image",
"type": "string" "type": "string"

View file

@ -465,7 +465,9 @@ depends_on: [ shouldbefiltered ]
func TestTree(t *testing.T) { func TestTree(t *testing.T) {
t.Parallel() t.Parallel()
build := &model.Build{} build := &model.Build{
Event: model.EventPush,
}
b := ProcBuilder{ b := ProcBuilder{
Repo: &model.Repo{}, Repo: &model.Repo{},