Skip to content

ci: serialize Build runs per ref - #7

Merged
marsvogel merged 1 commit into
mainfrom
ci/serialize-main-builds
Jul 24, 2026
Merged

ci: serialize Build runs per ref#7
marsvogel merged 1 commit into
mainfrom
ci/serialize-main-builds

Conversation

@marsvogel

Copy link
Copy Markdown
Owner

Follow-up to the failed release run after #5 was merged.

What happened

#5 and #6 were merged twenty-eight seconds apart, putting two Build runs on main simultaneously. The older run's release step failed:

HTTP 403: Resource not accessible by integration (https://api.github.com/repos/marsvogel/QuickWeek/releases)

The newer run created v1.0.10 thirty seconds later without trouble, so v1.0.9 is simply missing — the tag was never created, and the maintainer chose to leave the gap rather than publish a superseded intermediate build.

The 403 itself was never explained: the job holds contents: write, the protect-main ruleset targets branches rather than tags, and the identical configuration succeeded moments later. What is clear is that two release jobs racing to create refs in one repository is not a state worth keeping, regardless of whether that race caused this particular 403.

Change

Runs now queue per ref. On main nothing is cancelled, so every merge still produces its release. On pull requests superseded runs are cancelled as they effectively were before — a stale PR build has nothing to publish — which also keeps macOS runner slots free. codeql.yml already carries the same pattern with unconditional cancellation.

Known trade-off

Three merges in quick succession would leave the middle run queued, and GitHub drops a queued run when a newer one arrives — that commit would get no release. For a repository that merges a few times a month, a missing release on a triple-merge is a better failure mode than two release jobs racing.

Verification

actionlint .github/workflows/build.yml passes. The effect itself is only observable on main, since it is the queueing behaviour of two concurrent pushes.

Merging #5 and #6 twenty-eight seconds apart put two Build runs on main at
once, and the older one's release step failed with HTTP 403 on POST /releases
while the newer one created v1.0.10 without trouble. The 403 was never
explained — the job holds contents:write, the protect-main ruleset targets
branches rather than tags, and the same configuration succeeded moments later —
but two release jobs racing to create refs in one repository is not a state
worth keeping either way.

The concurrency group queues runs per ref. On main nothing is cancelled, so
every merge still produces its release; on pull requests superseded runs are
cancelled as before, since a stale PR build has nothing to publish.

The known trade-off: three merges in quick succession would leave the middle
run queued, and GitHub drops a queued run when a newer one arrives — that
commit would get no release. For a repository that merges a few times a month
that is a better failure mode than a race.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@marsvogel
marsvogel merged commit b1820c4 into main Jul 24, 2026
5 checks passed
@marsvogel
marsvogel deleted the ci/serialize-main-builds branch July 24, 2026 20:05
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