mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-09-02 04:24:56 +00:00
Add support for pipeline root.when conditions (#770)
Co-authored-by: Zav Shotan <zshotan@bloomberg.net> Co-authored-by: Anbraten <anton@ju60.de> Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
@@ -85,6 +85,12 @@ func New(opts ...Option) *Compiler {
|
||||
func (c *Compiler) Compile(conf *yaml.Config) *backend.Config {
|
||||
config := new(backend.Config)
|
||||
|
||||
if !conf.When.Match(c.metadata, true) {
|
||||
// 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
|
||||
}
|
||||
|
||||
// create a default volume
|
||||
config.Volumes = append(config.Volumes, &backend.Volume{
|
||||
Name: fmt.Sprintf("%s_default", c.prefix),
|
||||
@@ -149,7 +155,7 @@ 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) {
|
||||
if !container.When.Match(c.metadata, false) {
|
||||
continue
|
||||
}
|
||||
stage := new(backend.Stage)
|
||||
@@ -176,7 +182,7 @@ 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) {
|
||||
if !container.When.Match(c.metadata, false) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -196,7 +202,7 @@ func (c *Compiler) Compile(conf *yaml.Config) *backend.Config {
|
||||
continue
|
||||
}
|
||||
|
||||
if !container.When.Match(c.metadata) {
|
||||
if !container.When.Match(c.metadata, false) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@@ -10,9 +10,9 @@ import (
|
||||
type (
|
||||
// Config defines a pipeline configuration.
|
||||
Config struct {
|
||||
When constraint.When `yaml:"when,omitempty"`
|
||||
Cache types.Stringorslice
|
||||
Platform string
|
||||
Branches constraint.List
|
||||
Workspace Workspace
|
||||
Clone Containers
|
||||
Pipeline Containers
|
||||
@@ -23,6 +23,8 @@ type (
|
||||
DependsOn []string `yaml:"depends_on,omitempty"`
|
||||
RunsOn []string `yaml:"runs_on,omitempty"`
|
||||
SkipClone bool `yaml:"skip_clone"`
|
||||
// Deprecated use When.Branch
|
||||
Branches constraint.List
|
||||
}
|
||||
|
||||
// Workspace defines a pipeline workspace.
|
||||
|
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/franela/goblin"
|
||||
|
||||
"github.com/woodpecker-ci/woodpecker/pipeline/frontend"
|
||||
"github.com/woodpecker-ci/woodpecker/pipeline/frontend/yaml/types"
|
||||
)
|
||||
|
||||
@@ -19,6 +20,8 @@ func TestParse(t *testing.T) {
|
||||
g.Fail(err)
|
||||
}
|
||||
|
||||
g.Assert(out.When.Constraints[0].Event.Match("tester")).Equal(true)
|
||||
|
||||
g.Assert(out.Workspace.Base).Equal("/go")
|
||||
g.Assert(out.Workspace.Path).Equal("src/github.com/octocat/hello-world")
|
||||
g.Assert(out.Volumes.Volumes[0].Name).Equal("custom")
|
||||
@@ -61,17 +64,65 @@ func TestParse(t *testing.T) {
|
||||
}
|
||||
g.Assert(out.Pipeline.Containers[0].Name).Equal("notify_fail")
|
||||
g.Assert(out.Pipeline.Containers[0].Image).Equal("plugins/slack")
|
||||
g.Assert(out.Pipeline.Containers[1].Name).Equal("notify_success")
|
||||
g.Assert(out.Pipeline.Containers[1].Image).Equal("plugins/slack")
|
||||
|
||||
g.Assert(len(out.Pipeline.Containers[0].When.Constraints)).Equal(0)
|
||||
g.Assert(out.Pipeline.Containers[1].Name).Equal("notify_success")
|
||||
g.Assert(out.Pipeline.Containers[1].Image).Equal("plugins/slack")
|
||||
g.Assert(out.Pipeline.Containers[1].When.Constraints[0].Event.Include).Equal([]string{"success"})
|
||||
})
|
||||
|
||||
matchConfig, err := ParseString(sampleYaml)
|
||||
if err != nil {
|
||||
g.Fail(err)
|
||||
}
|
||||
|
||||
g.It("Should match event tester", func() {
|
||||
g.Assert(matchConfig.When.Match(frontend.Metadata{
|
||||
Curr: frontend.Build{
|
||||
Event: "tester",
|
||||
},
|
||||
}, false)).Equal(true)
|
||||
})
|
||||
|
||||
g.It("Should match event tester2", func() {
|
||||
g.Assert(matchConfig.When.Match(frontend.Metadata{
|
||||
Curr: frontend.Build{
|
||||
Event: "tester2",
|
||||
},
|
||||
}, false)).Equal(true)
|
||||
})
|
||||
|
||||
g.It("Should match branch tester", func() {
|
||||
g.Assert(matchConfig.When.Match(frontend.Metadata{
|
||||
Curr: frontend.Build{
|
||||
Commit: frontend.Commit{
|
||||
Branch: "tester",
|
||||
},
|
||||
},
|
||||
}, true)).Equal(true)
|
||||
})
|
||||
|
||||
g.It("Should not match event push", func() {
|
||||
g.Assert(matchConfig.When.Match(frontend.Metadata{
|
||||
Curr: frontend.Build{
|
||||
Event: "push",
|
||||
},
|
||||
}, false)).Equal(false)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
var sampleYaml = `
|
||||
image: hello-world
|
||||
when:
|
||||
- event:
|
||||
- tester
|
||||
- tester2
|
||||
- branch:
|
||||
- tester
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
|
@@ -58,9 +58,9 @@ func (when *When) IsEmpty() bool {
|
||||
}
|
||||
|
||||
// Returns true if at least one of the internal constraints is true.
|
||||
func (when *When) Match(metadata frontend.Metadata) bool {
|
||||
func (when *When) Match(metadata frontend.Metadata, global bool) bool {
|
||||
for _, c := range when.Constraints {
|
||||
if c.Match(metadata) {
|
||||
if c.Match(metadata, global) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -68,7 +68,7 @@ func (when *When) Match(metadata frontend.Metadata) bool {
|
||||
if when.IsEmpty() {
|
||||
// test against default Constraints
|
||||
empty := &Constraint{}
|
||||
return empty.Match(metadata)
|
||||
return empty.Match(metadata, global)
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -126,24 +126,21 @@ 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,
|
||||
}
|
||||
func (c *Constraint) Match(metadata frontend.Metadata, global bool) bool {
|
||||
match := true
|
||||
if !global {
|
||||
c.SetDefaultEventFilter()
|
||||
|
||||
// apply step only filters
|
||||
match = c.Matrix.Match(metadata.Job.Matrix)
|
||||
}
|
||||
|
||||
match := c.Platform.Match(metadata.Sys.Platform) &&
|
||||
match = match && c.Platform.Match(metadata.Sys.Platform) &&
|
||||
c.Environment.Match(metadata.Curr.Target) &&
|
||||
c.Event.Match(metadata.Curr.Event) &&
|
||||
c.Repo.Match(metadata.Repo.Name) &&
|
||||
c.Ref.Match(metadata.Curr.Commit.Ref) &&
|
||||
c.Instance.Match(metadata.Sys.Host) &&
|
||||
c.Matrix.Match(metadata.Job.Matrix)
|
||||
c.Instance.Match(metadata.Sys.Host)
|
||||
|
||||
// changed files filter apply only for pull-request and push events
|
||||
if metadata.Curr.Event == frontend.EventPull || metadata.Curr.Event == frontend.EventPush {
|
||||
@@ -161,6 +158,18 @@ func (c *Constraint) Match(metadata frontend.Metadata) bool {
|
||||
return match
|
||||
}
|
||||
|
||||
// SetDefaultEventFilter set default e event filter if not event filter is already set
|
||||
func (c *Constraint) SetDefaultEventFilter() {
|
||||
if c.Event.IsEmpty() {
|
||||
c.Event.Include = []string{
|
||||
frontend.EventPush,
|
||||
frontend.EventPull,
|
||||
frontend.EventTag,
|
||||
frontend.EventDeploy,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IsEmpty return true if a constraint has no conditions
|
||||
func (c List) IsEmpty() bool {
|
||||
return len(c.Include) == 0 && len(c.Exclude) == 0
|
||||
|
@@ -489,7 +489,7 @@ func TestConstraints(t *testing.T) {
|
||||
for _, test := range testdata {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
c := parseConstraints(t, test.conf)
|
||||
got, want := c.Match(test.with), test.want
|
||||
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)
|
||||
}
|
||||
|
Reference in New Issue
Block a user