Skip to content

Commit

Permalink
Add when evaluate filter (#1213)
Browse files Browse the repository at this point in the history
  • Loading branch information
anbraten authored Oct 5, 2022
1 parent f133941 commit 287800a
Show file tree
Hide file tree
Showing 12 changed files with 159 additions and 39 deletions.
5 changes: 4 additions & 1 deletion cli/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ func execWithAxis(c *cli.Context, file, repoPath string, axis matrix.Axis) error
}

// compiles the yaml file
compiled := compiler.New(
compiled, err := compiler.New(
compiler.WithEscalated(
c.StringSlice("privileged")...,
),
Expand Down Expand Up @@ -185,6 +185,9 @@ func execWithAxis(c *cli.Context, file, repoPath string, axis matrix.Axis) error
compiler.WithSecret(secrets...),
compiler.WithEnviron(droneEnv),
).Compile(conf)
if err != nil {
return err
}

backend.Init(context.WithValue(c.Context, types.CliContext, c))

Expand Down
27 changes: 27 additions & 0 deletions docs/docs/20-usage/20-pipeline-syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,33 @@ when:

**Hint:** Passing a defined ignore-message like `[ALL]` inside the commit message will ignore all path conditions.

#### `evaluate`

Execute a step only if the provided evaluate expression is equal to true. Each [`CI_` variable](./50-environment.md#built-in-environment-variables) can be used inside the expression.

The expression syntax can be found in [the docs](https://github.com/antonmedv/expr/blob/master/docs/Language-Definition.md) of the underlying library.

Run on pushes to the default branch for the repository `owner/repo`:

```yaml
when:
- evaluate: 'CI_BUILD_EVENT == "push" && CI_REPO == "owner/repo" && CI_COMMIT_BRANCH == CI_REPO_DEFAULT_BRANCH'
```

Run on commits created by user `woodpecker-ci`:

```yaml
when:
- evaluate: 'CI_COMMIT_AUTHOR == "woodpecker-ci"'
```

Skip all commits containing `please ignore me` in the commit message:

```yaml
when:
- evaluate: 'not (CI_COMMIT_MESSAGE contains "please ignore me")'
```

### `group` - Parallel execution

Woodpecker supports parallel step execution for same-machine fan-in and fan-out. Parallel steps are configured using the `group` attribute. This instructs the pipeline runner to execute the named group in parallel.
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.18
require (
code.gitea.io/sdk/gitea v0.15.1-0.20220831004139-a0127ed0e7fe
codeberg.org/6543/go-yaml2json v0.2.1
github.com/antonmedv/expr v1.9.0
github.com/bmatcuk/doublestar/v4 v4.2.0
github.com/caddyserver/certmagic v0.17.1-0.20220901172127-2e22c6fa8c47
github.com/docker/cli v20.10.17+incompatible
Expand Down
16 changes: 16 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOEl
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA=
Expand All @@ -85,6 +86,8 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/antonmedv/expr v1.9.0 h1:j4HI3NHEdgDnN9p6oI6Ndr0G5QryMY0FNxT4ONrFDGU=
github.com/antonmedv/expr v1.9.0/go.mod h1:5qsM3oLGDND7sDmQGDXHkYfkjYMUX14qsgqmHhwGEk8=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
Expand Down Expand Up @@ -143,6 +146,7 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg=
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down Expand Up @@ -195,6 +199,8 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
Expand Down Expand Up @@ -506,6 +512,8 @@ github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
Expand All @@ -532,6 +540,8 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
Expand Down Expand Up @@ -624,6 +634,7 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pkg/sftp v1.13.4 h1:Lb0RYJCmgUcBgZosfoi9Y9sbl6+LJgOIgk/2Y4YjMFg=
github.com/pkg/sftp v1.13.4/go.mod h1:LzqnAvaD5TWeNBsZpfKxSYn1MbjWwOsCIAFFJbpIsK8=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
Expand Down Expand Up @@ -663,6 +674,8 @@ github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0ua
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/tview v0.0.0-20200219210816-cd38d7432498/go.mod h1:6lkG1x+13OShEf0EaOCaTQYyB7d5nSbb181KtjlS+84=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
Expand All @@ -683,6 +696,7 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/sanity-io/litter v1.2.0/go.mod h1:JF6pZUFgu2Q0sBZ+HSV35P8TVPI1TTzEwyu9FXAw2W4=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
Expand Down Expand Up @@ -716,6 +730,7 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
Expand Down Expand Up @@ -962,6 +977,7 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down
23 changes: 16 additions & 7 deletions pipeline/frontend/yaml/compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,15 @@ func New(opts ...Option) *Compiler {

// Compile compiles the YAML configuration to the pipeline intermediate
// representation configuration format.
func (c *Compiler) Compile(conf *yaml.Config) *backend.Config {
func (c *Compiler) Compile(conf *yaml.Config) (*backend.Config, error) {
config := new(backend.Config)

if !conf.When.Match(c.metadata, true) {
if match, err := conf.When.Match(c.metadata, true); !match && err == nil {
// This pipeline does not match the configured filter so return an empty config and stop further compilation.
// An empty pipeline will just be skipped completely.
return config
return config, nil
} else if err != nil {
return nil, err
}

// create a default volume
Expand Down Expand Up @@ -166,9 +168,12 @@ func (c *Compiler) Compile(conf *yaml.Config) *backend.Config {
config.Stages = append(config.Stages, stage)
} else if !c.local && !conf.SkipClone {
for i, container := range conf.Clone.Containers {
if !container.When.Match(c.metadata, false) {
if match, err := container.When.Match(c.metadata, false); !match && err == nil {
continue
} else if err != nil {
return nil, err
}

stage := new(backend.Stage)
stage.Name = fmt.Sprintf("%s_clone_%v", c.prefix, i)
stage.Alias = container.Name
Expand All @@ -193,8 +198,10 @@ func (c *Compiler) Compile(conf *yaml.Config) *backend.Config {
stage.Alias = nameServices

for i, container := range conf.Services.Containers {
if !container.When.Match(c.metadata, false) {
if match, err := container.When.Match(c.metadata, false); !match && err == nil {
continue
} else if err != nil {
return nil, err
}

name := fmt.Sprintf("%s_%s_%d", c.prefix, nameServices, i)
Expand All @@ -213,8 +220,10 @@ func (c *Compiler) Compile(conf *yaml.Config) *backend.Config {
continue
}

if !container.When.Match(c.metadata, false) {
if match, err := container.When.Match(c.metadata, false); !match && err == nil {
continue
} else if err != nil {
return nil, err
}

if stage == nil || group != container.Group || container.Group == "" {
Expand All @@ -233,7 +242,7 @@ func (c *Compiler) Compile(conf *yaml.Config) *backend.Config {

c.setupCacheRebuild(conf, config)

return config
return config, nil
}

func (c *Compiler) setupCache(conf *yaml.Config, ir *backend.Config) {
Expand Down
24 changes: 16 additions & 8 deletions pipeline/frontend/yaml/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,37 +79,45 @@ func TestParse(t *testing.T) {
}

g.It("Should match event tester", func() {
g.Assert(matchConfig.When.Match(frontend.Metadata{
match, err := matchConfig.When.Match(frontend.Metadata{
Curr: frontend.Build{
Event: "tester",
},
}, false)).Equal(true)
}, false)
g.Assert(match).Equal(true)
g.Assert(err).IsNil()
})

g.It("Should match event tester2", func() {
g.Assert(matchConfig.When.Match(frontend.Metadata{
match, err := matchConfig.When.Match(frontend.Metadata{
Curr: frontend.Build{
Event: "tester2",
},
}, false)).Equal(true)
}, false)
g.Assert(match).Equal(true)
g.Assert(err).IsNil()
})

g.It("Should match branch tester", func() {
g.Assert(matchConfig.When.Match(frontend.Metadata{
match, err := matchConfig.When.Match(frontend.Metadata{
Curr: frontend.Build{
Commit: frontend.Commit{
Branch: "tester",
},
},
}, true)).Equal(true)
}, true)
g.Assert(match).Equal(true)
g.Assert(err).IsNil()
})

g.It("Should not match event push", func() {
g.Assert(matchConfig.When.Match(frontend.Metadata{
match, err := matchConfig.When.Match(frontend.Metadata{
Curr: frontend.Build{
Event: "push",
},
}, false)).Equal(false)
}, false)
g.Assert(match).Equal(false)
g.Assert(err).IsNil()
})
})
})
Expand Down
31 changes: 25 additions & 6 deletions pipeline/frontend/yaml/constraint/constraint.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"strings"

"github.com/antonmedv/expr"
"github.com/bmatcuk/doublestar/v4"
"gopkg.in/yaml.v3"

Expand Down Expand Up @@ -31,6 +32,7 @@ type (
Matrix Map
Local types.BoolTrue
Path Path
Evaluate string `yaml:"evaluate,omitempty"`
}

// List defines a runtime constraint for exclude & include string slices.
Expand Down Expand Up @@ -58,10 +60,14 @@ func (when *When) IsEmpty() bool {
}

// Returns true if at least one of the internal constraints is true.
func (when *When) Match(metadata frontend.Metadata, global bool) bool {
func (when *When) Match(metadata frontend.Metadata, global bool) (bool, error) {
for _, c := range when.Constraints {
if c.Match(metadata, global) {
return true
match, err := c.Match(metadata, global)
if err != nil {
return false, err
}
if match {
return true, nil
}
}

Expand All @@ -70,7 +76,7 @@ func (when *When) Match(metadata frontend.Metadata, global bool) bool {
empty := &Constraint{}
return empty.Match(metadata, global)
}
return false
return false, nil
}

func (when *When) IncludesStatus(status string) bool {
Expand Down Expand Up @@ -126,7 +132,7 @@ 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, global bool) bool {
func (c *Constraint) Match(metadata frontend.Metadata, global bool) (bool, error) {
match := true
if !global {
c.SetDefaultEventFilter()
Expand Down Expand Up @@ -155,7 +161,20 @@ func (c *Constraint) Match(metadata frontend.Metadata, global bool) bool {
match = match && c.Cron.Match(metadata.Curr.Cron)
}

return match
if c.Evaluate != "" {
env := metadata.Environ()
out, err := expr.Compile(c.Evaluate, expr.Env(env), expr.AsBool())
if err != nil {
return false, err
}
result, err := expr.Run(out, env)
if err != nil {
return false, err
}
match = match && result.(bool)
}

return match, nil
}

// SetDefaultEventFilter set default e event filter if not event filter is already set
Expand Down
21 changes: 18 additions & 3 deletions pipeline/frontend/yaml/constraint/constraint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -484,14 +484,29 @@ func TestConstraints(t *testing.T) {
},
want: false,
},
{
desc: "filter by eval based on event",
conf: `{ evaluate: 'CI_BUILD_EVENT == "push"' }`,
with: frontend.Metadata{Curr: frontend.Build{Event: frontend.EventPush}},
want: true,
},
{
desc: "filter by eval based on event and repo",
conf: `{ evaluate: 'CI_BUILD_EVENT == "push" && CI_REPO == "owner/repo"' }`,
with: frontend.Metadata{Curr: frontend.Build{Event: frontend.EventPush}, Repo: frontend.Repo{Name: "owner/repo"}},
want: true,
},
}

for _, test := range testdata {
t.Run(test.desc, func(t *testing.T) {
c := parseConstraints(t, test.conf)
got, want := c.Match(test.with, false), test.want
if got != want {
t.Errorf("Expect %+v matches %q is %v", test.with, test.conf, want)
got, err := c.Match(test.with, false)
if err != nil {
t.Errorf("Match returned error: %v", err)
}
if got != test.want {
t.Errorf("Expect %+v matches %q is %v", test.with, test.conf, test.want)
}
})
}
Expand Down
Loading

0 comments on commit 287800a

Please sign in to comment.