-
Notifications
You must be signed in to change notification settings - Fork 319
Conclusion job concurrency is static per workflow and cannot be customized #24037
Description
Summary
gh-aw currently generates a static concurrency group for the compiler-generated conclusion job:
gh-aw-conclusion-<workflow-id>
This is not configurable from frontmatter, and it causes incorrect behavior in concurrent issue-driven workflows. When several runs of the same workflow happen at nearly the same time, GitHub Actions concurrency allows one running and one pending job per group, and later requests can cancel older pending conclusion jobs with messages like:
Canceling since a higher priority waiting request for gh-aw-conclusion-<workflow-id> exists.
This means the generated conclusion job can be dropped even though the rest of the workflow completed successfully.
Observed behavior
In an issue-triggered gh-aw workflow, multiple runs for different issues can complete activation, agent, detection, and safe_outputs, but the generated conclusion job is serialized across all runs of that workflow by a static group.
Because the group is static, concurrent runs for different issues compete for the same conclusion slot. If enough runs overlap, older pending conclusion jobs are cancelled by GitHub Actions queue behavior.
Observed example:
https://github.com/githubnext/gh-aw-security/actions/runs/23854981154
In that run, the main workflow work completed successfully, but the conclusion job was cancelled with:
Canceling since a higher priority waiting request for gh-aw-conclusion-pentest-xpia-victim-triage exists.
Why this is a problem
The docs describe the conclusion job concurrency as preventing collisions when multiple agents run the same workflow concurrently, and say queued conclusion runs complete in order rather than being discarded.
In practice, because the generated group is static per workflow, GitHub's concurrency semantics mean this is not true under higher fan-out. The static group causes unrelated runs for different issues or inputs to interfere with each other.
This is especially problematic for:
- issue-triggered workflows
- discussion-triggered workflows
- fan-out patterns where many runs of the same compiled workflow occur close together
- workflows where
conclusionis responsible for reporting, cleanup, or final status propagation
Current workaround
The only effective workaround I found is patching the generated lock file after compilation so the conclusion job group includes a per-run discriminator, for example:
conclusion:
concurrency:
group: "gh-aw-conclusion-pentest-xpia-victim-triage-${{ github.event.issue.number || github.run_id }}"
cancel-in-progress: falseThis fixes the cancellation behavior, but it is not viable because the change is lost on recompile.
Root cause
The compiler currently hardcodes the conclusion concurrency group from WorkflowID alone.
There is no frontmatter field to influence this group:
concurrency.job-discriminatoronly applies to compiler-generatedagentandoutputjob groupssafe-outputs.concurrency-grouponly applies to thesafe_outputsjobconclusionconcurrency has no override or discriminator support
Verified in source
Current compiler logic in pkg/workflow/notify_comment.go builds the group as:
group := "gh-aw-conclusion-" + data.WorkflowIDThe corresponding test in pkg/workflow/notify_comment_test.go asserts the same static pattern:
expectedGroup: "gh-aw-conclusion-my-workflow"The docs also state that conclusion job concurrency is automatic and not configurable.
Expected solution
One of these should be implemented:
- Preferred: apply
concurrency.job-discriminatorto the generatedconclusionjob as well. - Alternatively: add an explicit frontmatter override for conclusion job concurrency.
- At minimum: change the compiler-generated default for
conclusionto include a run-specific discriminator for triggers where multiple instances of the same workflow can run concurrently.
Suggested behavior
A good default would be something like:
group: "gh-aw-conclusion-<workflow-id>-${{ github.event.issue.number || github.event.pull_request.number || github.run_id }}"Or, if keeping defaults stable is important, allow users to opt in via frontmatter using an override or discriminator field.
Additional changes needed
Please update:
- compiler implementation for conclusion job concurrency generation
- schema and frontmatter docs
- unit tests covering conclusion job concurrency
- reference docs that currently state the conclusion group prevents collisions automatically and that queued runs are not discarded
Impact
Without this fix, concurrent runs of the same gh-aw workflow can silently lose their conclusion job, which breaks final reporting and cleanup semantics and makes generated workflow behavior unreliable under load.