-
Notifications
You must be signed in to change notification settings - Fork 296
Description
Summary
The default per-engine job-level concurrency group (gh-aw-{engine-id}-${{ github.workflow }}) prevents workflow_dispatch-triggered issue workflows from processing different issues simultaneously. Two runs of the same workflow for different issues are serialized at the agent and detection job level, even though they operate on completely independent data.
Reproduction
- Create an issue-triage workflow triggered via
workflow_dispatch(noton: issues:):
on:
workflow_dispatch:
inputs:
issue_number:
required: true
concurrency:
group: issue-triage-${{ github.event.inputs.issue_number }}`
cancel-in-progress: true
engine:
id: copilot- Compile with
gh aw compile - Dispatch two runs simultaneously for different issues (e.g., #277977 and #295537)
- Expected: Both run in parallel since they process different issues
- Actual: The second run's agent job is queued, waiting for the first to complete
Root Cause
In pkg/workflow/concurrency.go GenerateJobConcurrencyConfig():
func GenerateJobConcurrencyConfig(workflowData *WorkflowData) string {
// ...
if hasSpecialTriggers(workflowData) {
return "" // Skip for issues, PRs, push, etc.
}
// For generic triggers like workflow_dispatch, apply default concurrency
groupValue := fmt.Sprintf("gh-aw-%s-${{ github.workflow }}", engineID)
// ...
}hasSpecialTriggers() checks workflowData.On for substrings like "issues", "pull_request", etc. But workflows that use workflow_dispatch to process issues (common for triage workflows triggered by other workflows) don't contain these substrings, so they fall through to the default engine-scoped concurrency.
The compiled lock file gets:
jobs:
agent:
concurrency:
group: "gh-aw-copilot-${{ github.workflow }}" # Shared across ALL runs
detection:
concurrency:
group: "gh-aw-copilot-${{ github.workflow }}" # Same groupMeanwhile, the workflow-level concurrency is correctly per-issue:
concurrency:
group: issue-triage-${{ github.event.inputs.repo_owner }}-${{ github.event.inputs.repo_name }}-${{ github.event.inputs.issue_number }}`
cancel-in-progress: trueEvidence
Two runs on bv/triage-aw2 branch for different issues, dispatched simultaneously:
| Run | Issue | agent job | detection job | Notes |
|---|---|---|---|---|
| 22342722820 | #277977 | ✅ ran first | ✅ ran first | Completed normally |
| 22342722831 | #295537 | ⏳ queued ~6min | ⏳ queued | Waited for #277977's agent/detection to finish |
Both eventually succeeded, but #295537 was unnecessarily delayed by ~6 minutes waiting in the concurrency queue.
Interaction with workflow-level concurrency
The workflow-level concurrency (from the .md frontmatter) correctly includes the issue number. When both levels are set:
- Workflow-level
cancel-in-progress: truecancels runs for the same issue → correct - Job-level serialization blocks runs for different issues → incorrect for this use case
The user's intent (expressed via concurrency in the .md) is per-issue isolation. The compiler-injected job-level group overrides this for the agent/detection jobs.
Suggested Fixes
Option A: Inherit workflow-level concurrency context
When the user has set a custom workflow-level concurrency group, the job-level default should incorporate the same context variables. If the workflow concurrency group includes issue_number, the job group should too.
Option B: Skip job concurrency when workflow concurrency is set
If the user explicitly defined concurrency in their .md frontmatter, don't inject the default per-engine job concurrency — the user has already expressed their concurrency intent.
Option C: Allow engine.concurrency to suppress the default
Document that users can set engine.concurrency: none (or similar) to opt out of the default job-level serialization.
Workaround (current)
Users can manually edit the .lock.yml to remove the concurrency: blocks from agent and detection jobs, but this is lost on recompile.
Alternatively, set engine.concurrency in the .md frontmatter to include the issue number:
engine:
id: copilot
concurrency:
group: "gh-aw-copilot-${{ github.workflow }}-${{ github.event.inputs.issue_number }}"Environment
- gh-aw compiler: v0.50.0
- Copilot CLI: 0.0.415
- Workflow:
issue-triage.mdin microsoft/vscode-engineering