From 0ad611c6ab81e99ca21b9277474a323a03b6b1e7 Mon Sep 17 00:00:00 2001 From: Andrey Shulzhenko Date: Tue, 19 May 2026 22:34:46 +0100 Subject: [PATCH] feat: support concurrency.queue in workflow schema GitHub Actions added the `queue` property to the `concurrency` mapping (single | max, default single), but act's schema rejected any workflow using it. Mirror SchemaStore's encoding so workflows like `concurrency: { group: g, queue: max }` validate. Docs: https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#concurrency Added in github/docs@336b7f5. --- pkg/schema/schema_test.go | 83 +++++++++++++++++++++++++++++++++ pkg/schema/workflow_schema.json | 7 +++ 2 files changed, 90 insertions(+) diff --git a/pkg/schema/schema_test.go b/pkg/schema/schema_test.go index ce571c96533..6e80f4cc70a 100644 --- a/pkg/schema/schema_test.go +++ b/pkg/schema/schema_test.go @@ -90,3 +90,86 @@ jobs: }).UnmarshalYAML(&node) assert.NoError(t, err) } + +func TestConcurrencyQueue(t *testing.T) { + cases := []struct { + name string + yaml string + wantErr bool + }{ + { + name: "queue single is accepted", + yaml: ` +on: push +concurrency: + group: g + queue: single +jobs: + noop: + runs-on: ubuntu-latest + steps: + - run: echo ok +`, + }, + { + name: "queue max is accepted", + yaml: ` +on: push +concurrency: + group: g + queue: max +jobs: + noop: + runs-on: ubuntu-latest + steps: + - run: echo ok +`, + }, + { + name: "queue at job level is accepted", + yaml: ` +on: push +jobs: + noop: + runs-on: ubuntu-latest + concurrency: + group: g + queue: max + steps: + - run: echo ok +`, + }, + { + name: "queue with unknown value is rejected", + yaml: ` +on: push +concurrency: + group: g + queue: bogus +jobs: + noop: + runs-on: ubuntu-latest + steps: + - run: echo ok +`, + wantErr: true, + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + var node yaml.Node + if err := yaml.Unmarshal([]byte(tc.yaml), &node); !assert.NoError(t, err) { + return + } + err := (&Node{ + Definition: "workflow-root-strict", + Schema: GetWorkflowSchema(), + }).UnmarshalYAML(&node) + if tc.wantErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + }) + } +} diff --git a/pkg/schema/workflow_schema.json b/pkg/schema/workflow_schema.json index b65bf6ff4d0..8315f1ba697 100644 --- a/pkg/schema/workflow_schema.json +++ b/pkg/schema/workflow_schema.json @@ -1643,10 +1643,17 @@ "cancel-in-progress": { "type": "boolean", "description": "To cancel any currently running job or workflow in the same concurrency group, specify cancel-in-progress: true." + }, + "queue": { + "type": "concurrency-queue", + "description": "Controls how pending jobs or workflow runs are queued in the concurrency group. `single` (default): at most one job or workflow run can be pending. `max`: up to 100 jobs or workflow runs can be pending. The combination of `queue: max` and `cancel-in-progress: true` is not allowed and will result in a workflow validation error.\n\n[Documentation](https://docs.github.com/actions/using-workflows/workflow-syntax-for-github-actions#concurrency)" } } } }, + "concurrency-queue": { + "allowed-values": ["single", "max"] + }, "job-environment": { "description": "The environment that the job references. All environment protection rules must pass before a job referencing the environment is sent to a runner.", "context": ["github", "inputs", "vars", "needs", "strategy", "matrix"],