Workflow concurrency control#83
Conversation
📝 WalkthroughWalkthroughAdds Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Suggested labels
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/triage.yml:
- Around line 11-13: The workflow comment and/or PR description overstates
concurrency guarantees; update the text near the concurrency block (the
concurrency: group: simili-${{ github.event.issue.number ||
github.event.pull_request.number }} and cancel-in-progress: false entries) to
state that only one run can be running and at most one pending run exists per
group, that pending runs are replaced (not queued) when new events arrive
regardless of cancel-in-progress, and that ordering is not guaranteed; ensure
the updated wording explicitly says intermediate events may be dropped and that
the change only prevents simultaneous runs for the same issue/PR.
| concurrency: | ||
| group: simili-${{ github.event.issue.number || github.event.pull_request.number }} | ||
| cancel-in-progress: false |
There was a problem hiding this comment.
cancel-in-progress: false does not guarantee all events are processed — the effective queue depth is 1.
The PR description states workflows "queued instead of running in parallel" and "all events are processed in order", but this overstates the guarantee. When a concurrent workflow is queued and another using the same concurrency group is already in progress, the new run becomes pending — but any existing pending run in the same group is canceled and replaced by the new one. This is true regardless of the cancel-in-progress value.
The practical consequence: in a burst scenario where run A is in-progress and runs B and C arrive in quick succession, GitHub only queues the most recent pending build — you can have only one running and one pending build in a concurrency group irrespective of cancel-in-progress. So if A is still running and B is pending, a new push C causes B to be cancelled and C becomes the pending build.
Additionally, ordering is not guaranteed for jobs or workflow runs using concurrency groups; runs in the same concurrency group are handled in an arbitrary order.
The primary goal of the PR (preventing two runs for the same issue/PR from executing simultaneously and producing duplicate bot comments) is achieved and this is a meaningful improvement. But the team should be aware that under rapid-fire edits, intermediate events can be silently dropped rather than queued, and rely on the most-recent run to produce the correct final triage state.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/triage.yml around lines 11 - 13, The workflow comment
and/or PR description overstates concurrency guarantees; update the text near
the concurrency block (the concurrency: group: simili-${{
github.event.issue.number || github.event.pull_request.number }} and
cancel-in-progress: false entries) to state that only one run can be running and
at most one pending run exists per group, that pending runs are replaced (not
queued) when new events arrive regardless of cancel-in-progress, and that
ordering is not guaranteed; ensure the updated wording explicitly says
intermediate events may be dropped and that the change only prevents
simultaneous runs for the same issue/PR.
Kavirubc
left a comment
There was a problem hiding this comment.
Review: Changes Requested
Thanks for the fix — the concurrency logic in triage.yml is correct and solves the race condition described in #58.
Required Change
E2E test template is missing the concurrency block.
The e2e-test.yml workflow pushes a hardcoded triage.yml to the test repo (around line 229), but that template does not include the concurrency block added by this PR. This means the E2E pipeline never exercises the fix it's supposed to validate.
Please update the inline template in e2e-test.yml to match the real triage.yml:
concurrency:
group: simili-${{ github.event.issue.number || github.event.pull_request.number }}
cancel-in-progress: falseAdd it between the on: block and permissions: in the heredoc at the Enable Simili workflow step.
Minor Note (non-blocking)
If issue #N and PR #N exist simultaneously, they share the concurrency group simili-N and would serialize against each other. Low probability in practice, but worth being aware of.
Once the E2E template is updated and commits are signed off, this is good to merge.
412bad4 to
6271e55
Compare
Kavirubc
left a comment
There was a problem hiding this comment.
Changes addressed. The E2E embedded template now includes the concurrency block, and the e2e workflow itself also got a top-level concurrency group (e2e-${{ ... }}) as a bonus improvement. All CI checks pass (Build, Lint, Vet, CodeRabbit). DCO is being handled separately. LGTM.
Signed-off-by: Sachindu-Nethmin <sachindunethminweerasinghe@gmail.com>
Signed-off-by: Sachindu-Nethmin <sachindunethminweerasinghe@gmail.com>
4f6b110 to
3467e08
Compare
🧪 E2E Test✅ Bot responded: yes Test repo → gh-simili-bot/simili-e2e-22176942341 Auto-generated by E2E pipeline |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/e2e-test.yml:
- Around line 243-245: The heredoc currently embeds a `${{ }}` concurrency
expression which GitHub evaluates eagerly, producing a hardcoded group; instead
mirror the existing placeholder pattern used for `__PR_SHA__`: write a
single-quoted literal expression into the heredoc via a shell variable (e.g.
`CONC_EXPR='simili-${{ github.event.issue.number ||
github.event.pull_request.number }}'`) and then use `sed` (like the `__PR_SHA__`
replacement) to substitute a `__CONC_EXPR__` placeholder in the generated
triage.yml with the expanded `${CONC_EXPR}` so the final file contains the
runtime `${{ }}` template rather than a baked-in number.
---
Duplicate comments:
In @.github/workflows/triage.yml:
- Around line 11-13: The concurrency block using "group: simili-${{
github.event.issue.number || github.event.pull_request.number }}" with
"cancel-in-progress: false" still enforces a single running + single queued run
(queue depth 1) and can drop intermediate events; to fix this, remove or
redesign the concurrency usage: either delete the entire concurrency block so
GitHub will run events concurrently, or replace it with a different coordination
mechanism (e.g., an external queue or a workflow_run-based serial processor)
instead of relying on the current "concurrency" semantics; look for the
"concurrency" section and the keys "group: simili-${{ github.event.issue.number
|| github.event.pull_request.number }}" and "cancel-in-progress: false" to
modify.
| concurrency: | ||
| group: simili-${{ github.event.issue.number || github.event.pull_request.number }} | ||
| cancel-in-progress: false |
There was a problem hiding this comment.
${{ }} expression inside the heredoc is eagerly evaluated in the e2e context — the generated triage.yml gets a hardcoded group name, not a dynamic expression.
GitHub Actions literally replaces ${{ }} before invoking any shell, and this applies even inside a single-quoted heredoc delimiter (<< 'WFEOF'), because the substitution happens at the workflow-runner level, before bash is started. When the e2e workflow runs for PR #83, line 244 evaluates as:
github.event.issue.number→""(not an issue event)github.event.pull_request.number→83
So the generated triage.yml in the test repo will contain:
concurrency:
group: simili-83 # hardcoded e2e PR number, not a dynamic expression
cancel-in-progress: falseEvery triage run in the test repo — regardless of which issue triggered it — will land in simili-83, rather than per-issue groups. The e2e test itself passes because only one trigger issue is created, but the deployed config diverges from the production triage.yml behavior.
The codebase already uses __PR_SHA__ + sed (lines 264, 279) for exactly this purpose — escaping a ${{ }} expression that must survive into the generated file. Apply the same pattern here:
🐛 Proposed fix using the existing `__PLACEHOLDER__` + sed pattern
- concurrency:
- group: simili-${{ github.event.issue.number || github.event.pull_request.number }}
- cancel-in-progress: false
+ concurrency:
+ group: simili-__CONC_EXPR__
+ cancel-in-progress: falseThen, in the shell block after the heredoc, alongside the existing sed for __PR_SHA__:
SHA="${{ github.event.pull_request.head.sha || inputs.sha }}"
sed -i "s|__PR_SHA__|$SHA|g" .github/workflows/triage.yml
+ CONC_EXPR='${{ github.event.issue.number || github.event.pull_request.number }}'
+ sed -i "s/__CONC_EXPR__/${CONC_EXPR}/g" .github/workflows/triage.ymlThe CONC_EXPR shell variable is single-quoted so bash treats ${{ }} as a literal string; the outer double-quoted sed argument then expands ${CONC_EXPR} to that literal string, writing the correct GitHub Actions template expression into the generated file.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/e2e-test.yml around lines 243 - 245, The heredoc currently
embeds a `${{ }}` concurrency expression which GitHub evaluates eagerly,
producing a hardcoded group; instead mirror the existing placeholder pattern
used for `__PR_SHA__`: write a single-quoted literal expression into the heredoc
via a shell variable (e.g. `CONC_EXPR='simili-${{ github.event.issue.number ||
github.event.pull_request.number }}'`) and then use `sed` (like the `__PR_SHA__`
replacement) to substitute a `__CONC_EXPR__` placeholder in the generated
triage.yml with the expanded `${CONC_EXPR}` so the final file contains the
runtime `${{ }}` template rather than a baked-in number.
* feat: add concurrency control Signed-off-by: Sachindu-Nethmin <sachindunethminweerasinghe@gmail.com> * feat: add concurrency to e2e tests and embedded template Signed-off-by: Sachindu-Nethmin <sachindunethminweerasinghe@gmail.com> --------- Signed-off-by: Sachindu-Nethmin <sachindunethminweerasinghe@gmail.com>
Description
This PR adds concurrency control to the triage workflow to prevent race conditions and duplicate bot comments when multiple events trigger simultaneously (e.g., issue opened + issue edited). It ensures that workflows for the same issue or PR run sequentially.
Type of Change
Related Issues
Fixes #58
Changes Made
concurrencyconfiguration to .github/workflows/triage.yml.simili-${{ github.event.issue.number || github.event.pull_request.number }}to scope limits to individual issues/PRs.cancel-in-progress: falseto ensures all events are processed in order rather than keeping only the latest.Testing
go build ./...successfullygo test ./...successfullygo vet ./...successfullyScreenshots (if applicable)
Checklist
Additional Notes
Verified by triggering multiple edits on a PR and observing that the workflows queued correctly instead of running in parallel.
Summary by CodeRabbit