Skip to content

Workflow concurrency control#83

Merged
Kavirubc merged 2 commits intosimiligh:mainfrom
Sachindu-Nethmin:workflow-concurrency-control
Feb 19, 2026
Merged

Workflow concurrency control#83
Kavirubc merged 2 commits intosimiligh:mainfrom
Sachindu-Nethmin:workflow-concurrency-control

Conversation

@Sachindu-Nethmin
Copy link
Copy Markdown
Contributor

@Sachindu-Nethmin Sachindu-Nethmin commented Feb 19, 2026

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

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to change)
  • 📚 Documentation update
  • 🔧 Configuration/build change
  • ♻️ Refactoring (no functional changes)
  • 🧪 Test update

Related Issues

Fixes #58

Changes Made

  • Added concurrency configuration to .github/workflows/triage.yml.
  • Set the concurrency group to simili-${{ github.event.issue.number || github.event.pull_request.number }} to scope limits to individual issues/PRs.
  • Set cancel-in-progress: false to ensures all events are processed in order rather than keeping only the latest.

Testing

  • I have run go build ./... successfully
  • I have run go test ./... successfully
  • I have run go vet ./... successfully
  • I have tested the changes locally

Screenshots (if applicable)

Screenshot 2026-02-19 143405

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • New and existing unit tests pass locally with my changes

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

  • Chores
    • Added concurrency controls to CI workflows to isolate runs per issue/PR and per test run, preventing in-progress jobs from being cancelled by newer events and improving stability of triage and end-to-end test runs.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 19, 2026

📝 Walkthrough

Walkthrough

Adds concurrency blocks to GitHub Actions workflows to group runs by issue/PR or PR/sha and set cancel-in-progress: false, preventing overlapping workflow runs for the same issue/PR.

Changes

Cohort / File(s) Summary
Triage workflow
.github/workflows/triage.yml
Added concurrency group `simili-${{ github.event.issue.number
E2E test workflow
.github/workflows/e2e-test.yml
Added top-level concurrency group `e2e-${{ github.event.pull_request.number

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested labels

workflow, enhancement, ci/cd

Poem

🐰 I hop between YAML and light,
Grouping runs so none take flight,
One triage at a time I keep,
No duplicate comments disturb my sleep,
Hooray — clean runs, and all is right.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Workflow concurrency control' clearly and specifically summarizes the main change—adding concurrency control to GitHub Actions workflows to prevent race conditions.
Linked Issues check ✅ Passed The PR successfully implements all coding requirements from issue #58: adds concurrency configuration to workflow files with the correct group expression and cancel-in-progress setting as specified.
Out of Scope Changes check ✅ Passed All changes are directly in scope—modifications to .github/workflows/triage.yml and .github/workflows/e2e-test.yml add only the concurrency blocks specified in issue #58 requirements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +11 to +13
concurrency:
group: simili-${{ github.event.issue.number || github.event.pull_request.number }}
cancel-in-progress: false
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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.

Copy link
Copy Markdown
Contributor

@Kavirubc Kavirubc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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: false

Add 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.

@Sachindu-Nethmin Sachindu-Nethmin force-pushed the workflow-concurrency-control branch from 412bad4 to 6271e55 Compare February 19, 2026 09:28
Copy link
Copy Markdown
Contributor

@Kavirubc Kavirubc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
@Sachindu-Nethmin Sachindu-Nethmin force-pushed the workflow-concurrency-control branch from 4f6b110 to 3467e08 Compare February 19, 2026 09:53
@Kavirubc Kavirubc added the e2e label Feb 19, 2026
@gh-simili-bot
Copy link
Copy Markdown
Contributor

🧪 E2E Test

Bot responded: yes

Test repo → gh-simili-bot/simili-e2e-22176942341
Run → logs

Auto-generated by E2E pipeline

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +243 to +245
concurrency:
group: simili-${{ github.event.issue.number || github.event.pull_request.number }}
cancel-in-progress: false
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

${{ }} 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.number83

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: false

Every 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: false

Then, 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.yml

The 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.

@Kavirubc Kavirubc merged commit 967f759 into similigh:main Feb 19, 2026
7 checks passed
Sachindu-Nethmin added a commit to Sachindu-Nethmin/simili-bot that referenced this pull request Feb 27, 2026
* 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enhancement: Workflow concurrency control

3 participants