From bd3889a61e09b60eaae2fd16a80cf35e823aeac9 Mon Sep 17 00:00:00 2001 From: ecrupper Date: Fri, 25 Oct 2024 09:59:41 -0500 Subject: [PATCH] enhance(ruleset): add stage status rule for independent stages --- compiler/types/pipeline/ruleset.go | 56 +++++++++------- compiler/types/yaml/ruleset.go | 65 ++++++++++--------- compiler/types/yaml/ruleset_test.go | 34 +++++----- .../types/yaml/testdata/ruleset_simple.yml | 1 + 4 files changed, 87 insertions(+), 69 deletions(-) diff --git a/compiler/types/pipeline/ruleset.go b/compiler/types/pipeline/ruleset.go index a6e5101f6..efc07036e 100644 --- a/compiler/types/pipeline/ruleset.go +++ b/compiler/types/pipeline/ruleset.go @@ -29,17 +29,18 @@ type ( // // swagger:model PipelineRules Rules struct { - Branch Ruletype `json:"branch,omitempty" yaml:"branch,omitempty"` - Comment Ruletype `json:"comment,omitempty" yaml:"comment,omitempty"` - Event Ruletype `json:"event,omitempty" yaml:"event,omitempty"` - Path Ruletype `json:"path,omitempty" yaml:"path,omitempty"` - Repo Ruletype `json:"repo,omitempty" yaml:"repo,omitempty"` - Status Ruletype `json:"status,omitempty" yaml:"status,omitempty"` - Tag Ruletype `json:"tag,omitempty" yaml:"tag,omitempty"` - Target Ruletype `json:"target,omitempty" yaml:"target,omitempty"` - Label Ruletype `json:"label,omitempty" yaml:"label,omitempty"` - Instance Ruletype `json:"instance,omitempty" yaml:"instance,omitempty"` - Parallel bool `json:"-" yaml:"-"` + Branch Ruletype `json:"branch,omitempty" yaml:"branch,omitempty"` + Comment Ruletype `json:"comment,omitempty" yaml:"comment,omitempty"` + Event Ruletype `json:"event,omitempty" yaml:"event,omitempty"` + Path Ruletype `json:"path,omitempty" yaml:"path,omitempty"` + Repo Ruletype `json:"repo,omitempty" yaml:"repo,omitempty"` + Status Ruletype `json:"status,omitempty" yaml:"status,omitempty"` + StageStatus Ruletype `json:"stage_status,omitempty" yaml:"stage_status,omitempty"` + Tag Ruletype `json:"tag,omitempty" yaml:"tag,omitempty"` + Target Ruletype `json:"target,omitempty" yaml:"target,omitempty"` + Label Ruletype `json:"label,omitempty" yaml:"label,omitempty"` + Instance Ruletype `json:"instance,omitempty" yaml:"instance,omitempty"` + Parallel bool `json:"-" yaml:"-"` } // Ruletype is the pipeline representation of an element @@ -51,17 +52,18 @@ type ( // RuleData is the data to check our ruleset // against for a step in a pipeline. RuleData struct { - Branch string `json:"branch,omitempty" yaml:"branch,omitempty"` - Comment string `json:"comment,omitempty" yaml:"comment,omitempty"` - Event string `json:"event,omitempty" yaml:"event,omitempty"` - Path []string `json:"path,omitempty" yaml:"path,omitempty"` - Repo string `json:"repo,omitempty" yaml:"repo,omitempty"` - Status string `json:"status,omitempty" yaml:"status,omitempty"` - Tag string `json:"tag,omitempty" yaml:"tag,omitempty"` - Target string `json:"target,omitempty" yaml:"target,omitempty"` - Label []string `json:"label,omitempty" yaml:"label,omitempty"` - Instance string `json:"instance,omitempty" yaml:"instance,omitempty"` - Parallel bool `json:"-" yaml:"-"` + Branch string `json:"branch,omitempty" yaml:"branch,omitempty"` + Comment string `json:"comment,omitempty" yaml:"comment,omitempty"` + Event string `json:"event,omitempty" yaml:"event,omitempty"` + Path []string `json:"path,omitempty" yaml:"path,omitempty"` + Repo string `json:"repo,omitempty" yaml:"repo,omitempty"` + Status string `json:"status,omitempty" yaml:"status,omitempty"` + StageStatus string `json:"stage_status,omitempty" yaml:"stage_status,omitempty"` + Tag string `json:"tag,omitempty" yaml:"tag,omitempty"` + Target string `json:"target,omitempty" yaml:"target,omitempty"` + Label []string `json:"label,omitempty" yaml:"label,omitempty"` + Instance string `json:"instance,omitempty" yaml:"instance,omitempty"` + Parallel bool `json:"-" yaml:"-"` } ) @@ -102,7 +104,7 @@ func (r *Ruleset) Match(from *RuleData) (bool, error) { // NoStatus returns true if the status field is empty. func (r *Rules) NoStatus() bool { // return true if every ruletype is empty - return len(r.Status) == 0 + return len(r.Status) == 0 && len(r.StageStatus) == 0 } // Empty returns true if the provided ruletypes are empty. @@ -114,6 +116,7 @@ func (r *Rules) Empty() bool { len(r.Path) == 0 && len(r.Repo) == 0 && len(r.Status) == 0 && + len(r.StageStatus) == 0 && len(r.Tag) == 0 && len(r.Target) == 0 && len(r.Label) == 0 && @@ -143,6 +146,13 @@ func (r *Rules) Match(from *RuleData, matcher, op string) (bool, error) { } } + if len(from.StageStatus) != 0 { + status, err = r.StageStatus.MatchSingle(from.StageStatus, matcher, op) + if err != nil { + return false, err + } + } + matchBranch, err := r.Branch.MatchSingle(from.Branch, matcher, op) if err != nil { return false, err diff --git a/compiler/types/yaml/ruleset.go b/compiler/types/yaml/ruleset.go index 348f6315b..680f2ed07 100644 --- a/compiler/types/yaml/ruleset.go +++ b/compiler/types/yaml/ruleset.go @@ -22,16 +22,17 @@ type ( // Rules is the yaml representation of the ruletypes // from a ruleset block for a step in a pipeline. Rules struct { - Branch []string `yaml:"branch,omitempty,flow" json:"branch,omitempty" jsonschema:"description=Limits the execution of a step to matching build branches.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` - Comment []string `yaml:"comment,omitempty,flow" json:"comment,omitempty" jsonschema:"description=Limits the execution of a step to matching a pull request comment.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` - Event []string `yaml:"event,omitempty,flow" json:"event,omitempty" jsonschema:"description=Limits the execution of a step to matching build events.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` - Path []string `yaml:"path,omitempty,flow" json:"path,omitempty" jsonschema:"description=Limits the execution of a step to matching files changed in a repository.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` - Repo []string `yaml:"repo,omitempty,flow" json:"repo,omitempty" jsonschema:"description=Limits the execution of a step to matching repos.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` - Status []string `yaml:"status,omitempty,flow" json:"status,omitempty" jsonschema:"enum=[failure],enum=[success],description=Limits the execution of a step to matching build statuses.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` - Tag []string `yaml:"tag,omitempty,flow" json:"tag,omitempty" jsonschema:"description=Limits the execution of a step to matching build tag references.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` - Target []string `yaml:"target,omitempty,flow" json:"target,omitempty" jsonschema:"description=Limits the execution of a step to matching build deployment targets.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` - Label []string `yaml:"label,omitempty,flow" json:"label,omitempty" jsonschema:"description=Limits step execution to match on pull requests labels.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` - Instance []string `yaml:"instance,omitempty,flow" json:"instance,omitempty" jsonschema:"description=Limits step execution to match on certain instances.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` + Branch []string `yaml:"branch,omitempty,flow" json:"branch,omitempty" jsonschema:"description=Limits the execution of a step to matching build branches.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` + Comment []string `yaml:"comment,omitempty,flow" json:"comment,omitempty" jsonschema:"description=Limits the execution of a step to matching a pull request comment.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` + Event []string `yaml:"event,omitempty,flow" json:"event,omitempty" jsonschema:"description=Limits the execution of a step to matching build events.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` + Path []string `yaml:"path,omitempty,flow" json:"path,omitempty" jsonschema:"description=Limits the execution of a step to matching files changed in a repository.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` + Repo []string `yaml:"repo,omitempty,flow" json:"repo,omitempty" jsonschema:"description=Limits the execution of a step to matching repos.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` + Status []string `yaml:"status,omitempty,flow" json:"status,omitempty" jsonschema:"enum=[failure],enum=[success],description=Limits the execution of a step to matching build statuses.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` + StageStatus []string `yaml:"stage_status,omitempty,flow" json:"stage_status,omitempty" jsonschema:"description=Limits the execution of a step to matching stage statuses.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` + Tag []string `yaml:"tag,omitempty,flow" json:"tag,omitempty" jsonschema:"description=Limits the execution of a step to matching build tag references.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` + Target []string `yaml:"target,omitempty,flow" json:"target,omitempty" jsonschema:"description=Limits the execution of a step to matching build deployment targets.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` + Label []string `yaml:"label,omitempty,flow" json:"label,omitempty" jsonschema:"description=Limits step execution to match on pull requests labels.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` + Instance []string `yaml:"instance,omitempty,flow" json:"instance,omitempty" jsonschema:"description=Limits step execution to match on certain instances.\nReference: https://go-vela.github.io/docs/reference/yaml/steps/#the-ruleset-key"` } ) @@ -84,6 +85,7 @@ func (r *Ruleset) UnmarshalYAML(unmarshal func(interface{}) error) error { advanced.If.Path = append(advanced.If.Path, simple.Path...) advanced.If.Repo = append(advanced.If.Repo, simple.Repo...) advanced.If.Status = append(advanced.If.Status, simple.Status...) + advanced.If.StageStatus = append(advanced.If.StageStatus, simple.StageStatus...) advanced.If.Tag = append(advanced.If.Tag, simple.Tag...) advanced.If.Target = append(advanced.If.Target, simple.Target...) advanced.If.Label = append(advanced.If.Label, simple.Label...) @@ -109,16 +111,17 @@ func (r *Ruleset) UnmarshalYAML(unmarshal func(interface{}) error) error { // type to a pipeline Rules type. func (r *Rules) ToPipeline() *pipeline.Rules { return &pipeline.Rules{ - Branch: r.Branch, - Comment: r.Comment, - Event: r.Event, - Path: r.Path, - Repo: r.Repo, - Status: r.Status, - Tag: r.Tag, - Target: r.Target, - Label: r.Label, - Instance: r.Instance, + Branch: r.Branch, + Comment: r.Comment, + Event: r.Event, + Path: r.Path, + Repo: r.Repo, + Status: r.Status, + StageStatus: r.StageStatus, + Tag: r.Tag, + Target: r.Target, + Label: r.Label, + Instance: r.Instance, } } @@ -126,16 +129,17 @@ func (r *Rules) ToPipeline() *pipeline.Rules { func (r *Rules) UnmarshalYAML(unmarshal func(interface{}) error) error { // rules struct we try unmarshalling to rules := new(struct { - Branch raw.StringSlice - Comment raw.StringSlice - Event raw.StringSlice - Path raw.StringSlice - Repo raw.StringSlice - Status raw.StringSlice - Tag raw.StringSlice - Target raw.StringSlice - Label raw.StringSlice - Instance raw.StringSlice + Branch raw.StringSlice + Comment raw.StringSlice + Event raw.StringSlice + Path raw.StringSlice + Repo raw.StringSlice + Status raw.StringSlice + StageStatus raw.StringSlice `yaml:"stage_status"` + Tag raw.StringSlice + Target raw.StringSlice + Label raw.StringSlice + Instance raw.StringSlice }) // attempt to unmarshal rules @@ -146,6 +150,7 @@ func (r *Rules) UnmarshalYAML(unmarshal func(interface{}) error) error { r.Path = rules.Path r.Repo = rules.Repo r.Status = rules.Status + r.StageStatus = rules.StageStatus r.Tag = rules.Tag r.Target = rules.Target r.Label = rules.Label diff --git a/compiler/types/yaml/ruleset_test.go b/compiler/types/yaml/ruleset_test.go index d1f559daa..0f7ee3073 100644 --- a/compiler/types/yaml/ruleset_test.go +++ b/compiler/types/yaml/ruleset_test.go @@ -98,14 +98,15 @@ func TestYaml_Ruleset_UnmarshalYAML(t *testing.T) { file: "testdata/ruleset_simple.yml", want: &Ruleset{ If: Rules{ - Branch: []string{"main"}, - Comment: []string{"test comment"}, - Event: []string{"push"}, - Path: []string{"foo.txt"}, - Repo: []string{"github/octocat"}, - Status: []string{"success"}, - Tag: []string{"v0.1.0"}, - Target: []string{"production"}, + Branch: []string{"main"}, + Comment: []string{"test comment"}, + Event: []string{"push"}, + Path: []string{"foo.txt"}, + Repo: []string{"github/octocat"}, + Status: []string{"success"}, + StageStatus: []string{"failure"}, + Tag: []string{"v0.1.0"}, + Target: []string{"production"}, }, Matcher: "filepath", Operator: "and", @@ -223,14 +224,15 @@ func TestYaml_Rules_UnmarshalYAML(t *testing.T) { failure: false, file: "testdata/ruleset_simple.yml", want: &Rules{ - Branch: []string{"main"}, - Comment: []string{"test comment"}, - Event: []string{"push"}, - Path: []string{"foo.txt"}, - Repo: []string{"github/octocat"}, - Status: []string{"success"}, - Tag: []string{"v0.1.0"}, - Target: []string{"production"}, + Branch: []string{"main"}, + Comment: []string{"test comment"}, + Event: []string{"push"}, + Path: []string{"foo.txt"}, + Repo: []string{"github/octocat"}, + Status: []string{"success"}, + StageStatus: []string{"failure"}, + Tag: []string{"v0.1.0"}, + Target: []string{"production"}, }, }, { diff --git a/compiler/types/yaml/testdata/ruleset_simple.yml b/compiler/types/yaml/testdata/ruleset_simple.yml index 7696e49b1..cc5e1f008 100644 --- a/compiler/types/yaml/testdata/ruleset_simple.yml +++ b/compiler/types/yaml/testdata/ruleset_simple.yml @@ -6,5 +6,6 @@ event: push path: foo.txt repo: github/octocat status: success +stage_status: failure tag: v0.1.0 target: production