Awesome Reviewers

Design GitHub Actions concurrency so overlapping runs can’t corrupt multi-step outcomes.

Rules: 1) Don’t assume concurrency is a durable multi-stage queue. If stage A and stage B must be serialized as one logical transaction, either:

2) Align the concurrency group predicate with the job if gate. GitHub evaluates concurrency before job if, so any kill-switch/feature flag that changes run behavior must be included in the concurrency group condition too.

3) Prevent “request accepted, nothing happens”. When concurrency saturation can drop jobs (only one running + one pending), add an always-hosted acknowledgement path (e.g., in authorize) that posts a visible “queued/dropped” notice based on in-flight counts.

4) Make publication overwrite-safe:

Example patterns:

A) Same-boundary serialization across dependent stages (use when B must not overlap A):

jobs:
  verify:
    concurrency:
      group: ${{ format('{0}-verify-{1}', github.workflow, github.event.issue.number) }}
      cancel-in-progress: false
  publish-verify:
    needs: [verify]
    concurrency:
      group: ${{ format('{0}-verify-{1}', github.workflow, github.event.issue.number) }}
      cancel-in-progress: false

B) Per-run isolation + idempotent publication (use when concurrency can’t be made durable):

jobs:
  verify:
    concurrency:
      group: ${{ format('{0}-verify-run-{1}', github.workflow, github.run_id) }}
      cancel-in-progress: false
  publish-verify:
    needs: [verify]
    concurrency:
      group: ${{ format('{0}-verify-run-{1}', github.workflow, github.run_id) }}
      cancel-in-progress: false

C) Include kill-switch/qualifiers in both if and concurrency.group (conceptually):

If you apply these principles, your concurrency design becomes correct under race conditions, feature toggles, and saturation—without relying on brittle scheduling assumptions.