mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-26 11:51:02 +00:00
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:
parent
7e18e69563
commit
ca84f703e3
6 changed files with 101 additions and 65 deletions
1
Makefile
1
Makefile
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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{},
|
||||||
|
|
Loading…
Reference in a new issue