Skip to content

feat(ci): add cancel-in-progress concurrency to PR-triggered checks - #162

Merged
MusaMisto merged 1 commit into
mainfrom
feat/pr-check-concurrency
Aug 11, 2026
Merged

feat(ci): add cancel-in-progress concurrency to PR-triggered checks#162
MusaMisto merged 1 commit into
mainfrom
feat/pr-check-concurrency

Conversation

@MusaMisto

Copy link
Copy Markdown
Member

What

The three PR-triggered templates had no concurrency block, so every push to a PR started an additional billed run and all superseded runs ran to completion:

  • critical-vuln-check.yml
  • dependabot-auto-merge.yml
  • react-native-contract-check.yml

The push-triggered release templates already had concurrency — only the check side was missing it.

Measured effect

Across the 14 active mobile repos over 60 days: 302 PRs/month against 492 push events, so ~39% of check runs are superseded before they finish. Two repos drive it — mealivery-customer-mobile at 5.9 commits/PR and funride-mobile at 4.4; the other twelve average 1.0.

The absolute Linux saving is small (these tiers are single-digit dollars/month) but it is free and keeps the number bounded as volume grows.

Why true here and false on releases

Triggercancel-in-progressWhy
PR checkstrueProduce no artifact, deploy nothing. A vuln-gate run is an Alerts API query; rn-contract is a static version comparison; gh pr merge --auto is idempotent. Only the newest verdict is meaningful.
push release/publishfalseA superseded run may already be mid-upload to TestFlight, Play, a registry or a cluster. Cancelling can leave a partial release.

Also in this PR

Documents the convention in README under Core Architecture — including a note that android-app.yml, ios-app.yml and the flutter-* pair predate it and combine a push trigger with cancel-in-progress: true. Tolerable (a cancelled build just produces no artifact) but a push landing during the upload stage could interrupt it. Flagged rather than changed here, since that is a separate decision.

Records a confirmed monitoring finding in the React Native contract section: with the react/renderer mismatch in place the app crashes reliably on demand, yet neither Sentry nor Crashlytics records anything — despite Sentry being correctly initialised (enabled: !__DEV__, Sentry.init() runs during module evaluation, before the throw). An uncaught JS error in a release build unwinds through ErrorUtils to RCTFatal and aborts the process before the transport can flush.

That makes this a blind spot for the entire failure class, not a misconfiguration — for this class the PR gate is the only signal available. Nothing downstream will tell you.

🤖 Generated with Claude Code

The three PR-triggered templates (critical-vuln-check, dependabot-auto-merge,
react-native-contract-check) had no concurrency block, so every push to a PR
started an additional billed run and all superseded runs ran to completion.
The push-triggered release templates already had concurrency; only the check
side was missing it.
Measured on the 14 active mobile repos over 60 days: 603 PRs but 492 push
events per month against 302 PRs -- so ~39% of check runs are superseded
before they finish. Two repos drive it (mealivery-customer-mobile at 5.9
commits/PR, funride-mobile at 4.4); the other twelve average 1.0.
cancel-in-progress is true for these three specifically because they produce
no artifact and deploy nothing -- a vuln-gate run is an Alerts API query, the
rn-contract run is a static version comparison, and `gh pr merge --auto` is
idempotent. The push-triggered release workflows keep cancel-in-progress:
false, since a superseded run there may already be mid-upload to TestFlight,
Play, a registry or a cluster.
Also documents the convention in README under Core Architecture, including a
note that the existing android-app/ios-app/flutter-* release templates predate
it and combine push triggers with cancel-in-progress: true -- tolerable but
worth revisiting.
Separately records a confirmed finding in the React Native contract section:
with the react/renderer mismatch in place the app crashes reliably on demand,
yet NEITHER Sentry NOR Crashlytics records anything, despite Sentry being
correctly initialised before the throw. An uncaught JS error in a release
build unwinds through ErrorUtils to RCTFatal and aborts before the transport
flushes. For this failure class the PR gate is the only signal available.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitaiBot commented Aug 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary

  • Added cancel-in-progress: true to three PR-triggered workflows:
    • critical-vuln-check.yml
    • dependabot-auto-merge.yml
    • react-native-contract-check.yml
  • Kept release workflows at cancel-in-progress: false to avoid interrupting deployments and artifact uploads.
  • Documented the concurrency convention and React Native monitoring limitation in README.md.

Risk

risk:low. The changes affect workflow scheduling only.

Security-sensitive areas

The vulnerability check and Dependabot auto-merge workflows changed their concurrency behavior. No permissions, credentials, dependency rules, or security controls changed.

Test coverage impact

No application test coverage changed. The PR changes CI workflow execution behavior and documentation. Validation should confirm that newer commits cancel older PR runs and that release runs remain queued.

Operational concerns

Superseded PR checks now stop automatically after a new commit. Release workflows remain protected from cancellation. React Native contract failures may remain detectable only through the PR contract gate because Sentry and Crashlytics do not capture the relevant crashes.

Walkthrough

The README documents React Native crash observability limits and workflow concurrency rules. Vulnerability checks, Dependabot auto-merge, and React Native contract checks now cancel superseded runs using workflow- and pull-request-aware concurrency groups.

Changes

Workflow concurrency controls

Layer / File(s)Summary
Concurrency policy documentation
README.md
Documents React Native version-contract crash behavior and distinguishes cancellation for pull-request checks from queued release and publishing workflows.
Workflow concurrency configuration
workflow-templates/critical-vuln-check.yml, workflow-templates/dependabot-auto-merge.yml, workflow-templates/react-native-contract-check.yml
Adds workflow-level concurrency groups and cancels superseded pull-request or ref runs.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested labels:infra, testing, risk:high

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description check✅ PassedThe description clearly explains the workflow concurrency changes and the related documentation updates.
Title check✅ PassedThe title clearly identifies the addition of cancel-in-progress concurrency to pull-request checks.
Docstring Coverage✅ PassedNo functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.

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.

@coderabbitaicoderabbitaiBot left a comment

Copy link
Copy Markdown

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@README.md`:
- Around line 1310-1313: Update the cancel-in-progress guidance to avoid
claiming cancelled runs bill nothing or that there is only one billed run per
PR: in README.md lines 1310-1313, workflow-templates/critical-vuln-check.yml
lines 45-48, workflow-templates/dependabot-auto-merge.yml lines 54-58, and
workflow-templates/react-native-contract-check.yml lines 39-43, state that
cancellation reduces additional superseded runner work while previously consumed
time may still be billed.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: simplify9/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e8d24ced-e988-4c38-88ef-5066d0589906

📥 Commits

Reviewing files that changed from the base of the PR and between 7d3c468 and 066c95e.

📒 Files selected for processing (4)
  • README.md
  • workflow-templates/critical-vuln-check.yml
  • workflow-templates/dependabot-auto-merge.yml
  • workflow-templates/react-native-contract-check.yml
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: GitGuardian Security Checks
🔇 Additional comments (4)
README.md (1)

1260-1267: LGTM!

workflow-templates/critical-vuln-check.yml (1)

49-51: LGTM!

workflow-templates/dependabot-auto-merge.yml (1)

59-61: 🗄️ Data Integrity & Integration

Verify the cancellation boundary around the auto-merge write.

cancel-in-progress: true can terminate the runner while gh pr merge --auto --squash is in flight. Confirm that a later run safely repeats an accepted auto-merge request and that an interrupted command cannot leave an unintended merge state. Use a disposable Dependabot PR for this test.

workflow-templates/react-native-contract-check.yml (1)

44-46: LGTM!

Comment threadREADME.md
Comment on lines +1310 to +1313
| Trigger | `cancel-in-progress` | Why |
| --- | --- | --- |
| `pull_request` / `pull_request_target` checks | **`true`** | A developer iterating pushes five times; only the newest result is meaningful. Cancelling the four superseded runs costs nothing and bills nothing. These checks produce no artifact and deploy nothing. |
| `push` release/publish workflows | **`false`** | A superseded run may already be mid-upload to TestFlight, Play, a registry or a cluster. Cancelling there can leave a partial release. Queue instead. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bashset -eu
printf'%s\n''--- referenced files ---'
git ls-files README.md workflow-templates/critical-vuln-check.yml workflow-templates/dependabot-auto-merge.yml workflow-templates/react-native-contract-check.yml
printf'%s\n''--- README excerpt ---'
sed -n '1298,1320p' README.md
printf'%s\n''--- critical-vuln-check excerpt ---'
sed -n '1,90p' workflow-templates/critical-vuln-check.yml
printf'%s\n''--- dependabot-auto-merge excerpt ---'
sed -n '1,100p' workflow-templates/dependabot-auto-merge.yml
printf'%s\n''--- react-native-contract-check excerpt ---'
sed -n '1,80p' workflow-templates/react-native-contract-check.yml
printf'%s\n''--- related concurrency and billing wording ---'
rg -n -C 2 --glob 'README.md' --glob 'workflow-templates/*.yml' \
'cancel-in-progress|bills nothing|billed run|billing|superseded|concurrency'.

Repository: simplify9/.github

Length of output: 1920


🌐 Web query:

site:docs.github.com GitHub Actions cancel-in-progress billing canceled jobs runner minutes

💡 Result:

When you use the cancel-in-progress option in GitHub Actions, GitHub cancels the specified in-progress workflow runs, which prevents them from consuming additional runner minutes [1][2]. Key details regarding this process include: Billing Impact: GitHub Actions billing for GitHub-hosted runners is based on the total processing time used by each job [3][4]. When a workflow run is canceled, the jobs that are successfully terminated stop consuming runner minutes [5]. You are billed only for the time the job was actually running up to the point of cancellation [3][4]. Note that GitHub rounds the minutes and partial minutes used by each job up to the nearest whole minute [6]. How Cancellation Works: 1. When a workflow is canceled, the server re-evaluates the if conditions for currently running jobs [5]. Jobs that do not have conditions that force them to continue (such as if: always()) will be marked for cancellation [5]. 2. The server sends a cancellation message to the runner machines [5]. 3. The runner machine attempts to gracefully stop processes (using signals like SIGINT/SIGTERM) [5]. 4. If the processes do not exit within the designated timeout periods (a 5-minute cancellation timeout is applied for forcible termination), the server will forcefully terminate all jobs and steps that are still running [5]. Because the cancellation process consumes no further runner time once the job is terminated, using cancel-in-progress: true is an effective strategy to optimize and reduce your GitHub Actions runner minute usage by ensuring that only the most recent workflow runs are active [1][2].

Citations:


🌐 Web query:

site:docs.github.com GitHub Actions usage limits billing minutes canceled workflow jobs

💡 Result:

Yes, canceled workflow jobs count toward your GitHub Actions billing minutes for the time they were actively running before being canceled [1]. If a job is canceled, you are billed for the duration it ran on a GitHub-hosted runner up until the point of cancellation [1]. GitHub Actions billing is based on the total processing time used by each runner type [1]. Consequently, if a job runs for a period of time and is then canceled, that elapsed time is included in your usage calculation [1]. It is important to note: - Billing for GitHub Actions minutes only applies to private repositories using GitHub-hosted runners [2][3]. - Public repositories and jobs run on self-hosted runners do not incur billable minutes [2][4]. - When a workflow is canceled, GitHub takes steps to terminate running jobs and steps, but any time consumed by the runner prior to this termination remains part of your usage [5]. - Billing is calculated based on the actual time used, though billable minutes for GitHub-hosted runners are generally rounded up to the nearest whole minute per job [2]. You can monitor your usage and billable minutes through the GitHub interface under your organization or repository settings [2][4].

Citations:


🏁 Script executed:

#!/bin/bashset -eu
forfilein README.md workflow-templates/critical-vuln-check.yml workflow-templates/dependabot-auto-merge.yml workflow-templates/react-native-contract-check.yml;doprintf'%s\n'"--- $file ---"
git show "HEAD:$file"| sed -n '1,1400p'| rg -n -C 4 \
'cancel-in-progress|bills nothing|billed run|billing|superseded|concurrency'||truedone

Repository: simplify9/.github

Length of output: 1920


Use accurate cancel-in-progress billing language.

cancel-in-progress: true stops superseded jobs from consuming additional runner time after cancellation, but it does not erase time already used. Replace “bills nothing” and each “One billed run per PR” claim with wording that describes reduced superseded work in README.md, workflow-templates/critical-vuln-check.yml, workflow-templates/dependabot-auto-merge.yml, and workflow-templates/react-native-contract-check.yml.

📍 Affects 4 files
  • README.md#L1310-L1313 (this comment)
  • workflow-templates/critical-vuln-check.yml#L45-L48
  • workflow-templates/dependabot-auto-merge.yml#L54-L58
  • workflow-templates/react-native-contract-check.yml#L39-L43
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@README.md` around lines 1310 - 1313, Update the cancel-in-progress guidance
to avoid claiming cancelled runs bill nothing or that there is only one billed
run per PR: in README.md lines 1310-1313,
workflow-templates/critical-vuln-check.yml lines 45-48,
workflow-templates/dependabot-auto-merge.yml lines 54-58, and
workflow-templates/react-native-contract-check.yml lines 39-43, state that
cancellation reduces additional superseded runner work while previously consumed
time may still be billed.

@MusaMistoMusaMisto self-assigned this Aug 11, 2026
@MusaMisto
MusaMisto merged commit 23ac3b1 into mainAug 11, 2026
2 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@MusaMisto