diff --git a/ast.go b/ast.go index 335f5c3a3..08e5bf8cf 100644 --- a/ast.go +++ b/ast.go @@ -400,6 +400,8 @@ type Concurrency struct { Group *String // CancelInProgress is a flag that shows if canceling this workflow cancels other jobs in progress. CancelInProgress *Bool + // Queue is the queue strategy for pending workflow runs. Valid values are "single" (default) and "max". + Queue *String // Pos is a position in source. Pos *Pos } diff --git a/parse.go b/parse.go index 77c892168..36b7854d2 100644 --- a/parse.go +++ b/parse.go @@ -820,13 +820,26 @@ func (p *parser) parseConcurrency(pos *Pos, n *yaml.Node) *Concurrency { ret.Group = p.parseString(e.val, false) case "cancel-in-progress": ret.CancelInProgress = p.parseBool(e.val) + case "queue": + ret.Queue = p.parseString(e.val, false) + if ret.Queue != nil && !ret.Queue.ContainsExpression() { + switch ret.Queue.Value { + case "max", "single": + // ok + default: + p.errorf(e.val, "invalid value %q for \"queue\" in \"concurrency\" section. valid values are \"max\" and \"single\"", ret.Queue.Value) + } + } default: - p.unexpectedKey(e.key, "concurrency", []string{"group", "cancel-in-progress"}) + p.unexpectedKey(e.key, "concurrency", []string{"cancel-in-progress", "group", "queue"}) } } if ret.Group == nil { p.errorAt(pos, "group name is missing in \"concurrency\" section") } + if ret.Queue != nil && ret.CancelInProgress != nil && !ret.Queue.ContainsExpression() && ret.Queue.Value == "max" && ret.CancelInProgress.Expression == nil && ret.CancelInProgress.Value { + p.errorfAt(ret.Queue.Pos, "\"queue: max\" cannot be combined with \"cancel-in-progress: true\" in \"concurrency\" section") + } return ret } diff --git a/rule_expression.go b/rule_expression.go index eab7a934b..19fd0e7fb 100644 --- a/rule_expression.go +++ b/rule_expression.go @@ -511,6 +511,7 @@ func (rule *RuleExpression) checkConcurrency(c *Concurrency, workflowKey string) } rule.checkString(c.Group, workflowKey) rule.checkBool(c.CancelInProgress, workflowKey) + rule.checkString(c.Queue, workflowKey) } func (rule *RuleExpression) checkDefaults(d *Defaults, workflowKey string) { diff --git a/testdata/err/case_sensitive_keys.out b/testdata/err/case_sensitive_keys.out index 353f1f5e4..9b88e62cf 100644 --- a/testdata/err/case_sensitive_keys.out +++ b/testdata/err/case_sensitive_keys.out @@ -8,9 +8,9 @@ test.yaml:22:9: unexpected key "DESCRIPTION" for outputs at workflow_call event. test.yaml:25:5: unexpected key "BRANCHES" for "push" section. expected one of "branches", "branches-ignore", "paths", "paths-ignore", "tags", "tags-ignore", "types", "workflows" [syntax-check] test.yaml:28:3: expected "run" key for "defaults" section but got "RUN" [syntax-check] test.yaml:30:5: unexpected key "SHELL" for "run" section. expected one of "shell", "working-directory" [syntax-check] -test.yaml:33:3: unexpected key "GROUP" for "concurrency" section. expected one of "cancel-in-progress", "group" [syntax-check] +test.yaml:33:3: unexpected key "GROUP" for "concurrency" section. expected one of "cancel-in-progress", "group", "queue" [syntax-check] test.yaml:39:5: unexpected key "NAME" for "job" section. expected one of "concurrency", "container", "continue-on-error", "defaults", "env", "environment", "if", "name", "needs", "outputs", "permissions", "runs-on", "secrets", "services", "snapshot", "steps", "strategy", "timeout-minutes", "uses", "with" [syntax-check] -test.yaml:41:7: unexpected key "GROUP" for "concurrency" section. expected one of "cancel-in-progress", "group" [syntax-check] +test.yaml:41:7: unexpected key "GROUP" for "concurrency" section. expected one of "cancel-in-progress", "group", "queue" [syntax-check] test.yaml:44:7: unexpected key "NAME" for "environment" section. expected one of "deployment", "name", "url" [syntax-check] test.yaml:47:7: expected "run" key for "defaults" section but got "RUN" [syntax-check] test.yaml:49:9: unexpected key "SHELL" for "run" section. expected one of "shell", "working-directory" [syntax-check] diff --git a/testdata/err/concurrency_queue.out b/testdata/err/concurrency_queue.out new file mode 100644 index 000000000..a74dff2ea --- /dev/null +++ b/testdata/err/concurrency_queue.out @@ -0,0 +1,2 @@ +test.yaml:5:10: invalid value "invalid" for "queue" in "concurrency" section. valid values are "max" and "single" [syntax-check] +test.yaml:13:14: "queue: max" cannot be combined with "cancel-in-progress: true" in "concurrency" section [syntax-check] diff --git a/testdata/err/concurrency_queue.yaml b/testdata/err/concurrency_queue.yaml new file mode 100644 index 000000000..772238887 --- /dev/null +++ b/testdata/err/concurrency_queue.yaml @@ -0,0 +1,15 @@ +on: push + +concurrency: + group: test + queue: invalid + +jobs: + test: + runs-on: ubuntu-latest + concurrency: + group: job-test + cancel-in-progress: true + queue: max + steps: + - run: echo diff --git a/testdata/err/unexpected_keys.out b/testdata/err/unexpected_keys.out index c2b6e835a..3d3169403 100644 --- a/testdata/err/unexpected_keys.out +++ b/testdata/err/unexpected_keys.out @@ -8,7 +8,7 @@ test.yaml:22:9: unexpected key "invalid_key" for outputs at workflow_call event. test.yaml:23:5: unexpected key "invalid_key" for "workflow_call" section. expected one of "inputs", "outputs", "secrets" [syntax-check] test.yaml:27:5: unexpected key "invalid_key" for "run" section. expected one of "shell", "working-directory" [syntax-check] test.yaml:28:3: expected "run" key for "defaults" section but got "invalid_key" [syntax-check] -test.yaml:32:3: unexpected key "invalid_key" for "concurrency" section. expected one of "cancel-in-progress", "group" [syntax-check] +test.yaml:32:3: unexpected key "invalid_key" for "concurrency" section. expected one of "cancel-in-progress", "group", "queue" [syntax-check] test.yaml:38:7: unexpected key "invalid_key" for "environment" section. expected one of "deployment", "name", "url" [syntax-check] test.yaml:40:7: unexpected key "invalid_key" for "strategy" section. expected one of "fail-fast", "matrix", "max-parallel" [syntax-check] test.yaml:46:9: unexpected key "invalid_key" for "credentials" section. expected one of "password", "username" [syntax-check] diff --git a/testdata/ok/concurrency_queue.yaml b/testdata/ok/concurrency_queue.yaml new file mode 100644 index 000000000..969dce553 --- /dev/null +++ b/testdata/ok/concurrency_queue.yaml @@ -0,0 +1,22 @@ +on: push + +concurrency: + group: deploy-queue + queue: max + +jobs: + test: + runs-on: ubuntu-latest + concurrency: + group: job-queue + cancel-in-progress: false + queue: max + steps: + - run: echo "deploy" + test2: + runs-on: ubuntu-latest + concurrency: + group: job-single + queue: single + steps: + - run: echo "single"