From a036dd092abd85e76bb240b29949fd541b1df50b Mon Sep 17 00:00:00 2001 From: navjottomer Date: Mon, 17 Aug 2026 04:20:29 +0000 Subject: [PATCH] Key release concurrency on the commit, not the branch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every push to main shared one group, and GitHub keeps only the newest pending run in a group, so merging several packages in quick succession cancelled the runs in between — and each was the only thing that would ever release its package. The serialisation that was wanted is per package and version, which is now on the release job itself. --- .github/workflows/release.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1abf1f5..81bd216 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,8 +10,15 @@ on: push: branches: [main] +# Keyed on the commit, not the branch. Every push to main used to share one group, +# and GitHub keeps only the newest *pending* run in a group — so merging several +# packages in quick succession cancelled the runs in between. Each of those runs was +# the only thing that would ever release its package, because detect works from that +# push's own github.event.before: the merge succeeded, the run showed "cancelled", +# and the package simply had no release until someone noticed. Per-commit means a run +# can never supersede another push's. concurrency: - group: release-${{ github.ref }} + group: release-${{ github.sha }} cancel-in-progress: false permissions: @@ -46,6 +53,13 @@ jobs: timeout-minutes: 10 permissions: contents: write + # The serialisation that is actually wanted: one leg at a time per package and + # version, so two pushes touching the same package cannot both get past the + # tag-exists check and race to create it. Waiting rather than cancelling, because + # the loser here still has work to do. + concurrency: + group: release-${{ matrix.package.slug }}-${{ matrix.package.version }} + cancel-in-progress: false strategy: fail-fast: false matrix: