Skip to content

ci(release): serialize release runs so back-to-back merges can't race - #172

Merged
jjeff merged 1 commit into
mainfrom
ci/release-concurrency
Sep 4, 2026
Merged

jjeff merged 1 commit into
mainfrom
ci/release-concurrency

Conversation

@jjeff

@jjeff jjeff commented Sep 4, 2026

Copy link
Copy Markdown
Owner

Found while merging #168, #170 and #171 in one session: they had to go in one at a time, waiting for each Release run to finish, because nothing stops two from running at once.

release.yml triggers on every push to main and declares no concurrency. Merging a second PR before the first release finishes starts two semantic-release jobs concurrently. Both read the same tag history, both compute the same next version, and both try to tag, push and publish it — one loses, and which one is a coin flip.

The change

concurrency:
  group: release-${{ github.ref }}
  cancel-in-progress: false

cancel-in-progress: false is the load-bearing half. The default (true) would cancel the queued run, which means the commits merged second would never be released at all — a quieter failure than the race it replaces. With it false, the second run waits and then publishes normally.

Grouping on github.ref keeps main, develop and alpha independent, since each is its own release channel.

Verified

npx prettier --check .github/workflows/release.yml — clean.

Behaviour cannot be verified before merge: the workflow only runs on push to a release branch, so the guard is exercised the first time two PRs merge close together.

Self-review: skipped — three-line workflow change, no application code.

🤖 Generated with Claude Code

https://claude.ai/code/session_016znpWBRUXSTsHbJcKmVpN6


🤖 Created with Claude Code · origin interactive · 2026-09-04 00:52 UTC

release.yml triggers on every push to main with no concurrency guard, so
merging a second PR before the first release finishes starts two
semantic-release jobs at once. Both compute a version from the same tag
history and both try to tag, push and publish it; one of them loses.

This is not hypothetical — it is why resortable PRs have to be merged one
at a time, waiting for each Release run to finish before starting the next.

cancel-in-progress is false deliberately. Cancelling the queued run would
mean the commits merged second never get released at all.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_016znpWBRUXSTsHbJcKmVpN6
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@jjeff
jjeff merged commit 48eb859 into main Sep 4, 2026
16 checks passed
@jjeff
jjeff deleted the ci/release-concurrency branch September 4, 2026 01:23
Sign up for free to 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