From a25e61ce57f6e529bc8cd15233306d7c40750288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Almeida?= Date: Tue, 5 May 2026 00:20:59 +0100 Subject: [PATCH] fix(release): push commit + tag atomically Without --atomic, git push can succeed for the tag ref and fail for the main ref on a non-fast-forward, leaving an orphaned tag at the pre-bump commit. The orphan then trips the 'Tag already exists on origin' guard on the next re-run, requiring manual tag deletion to unblock. --atomic makes the multi-ref push succeed-or-fail as a unit. Caught by Greptile as P1. --- .github/workflows/release.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3460350c77..855e754bdc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -175,9 +175,12 @@ jobs: git commit -m "release: $NEXT" git tag -a "$TAG" -m "release: $NEXT" - # Push commit and tag together. If main advanced concurrently this - # fails non-fast-forward; the maintainer just re-runs. - git push origin main "$TAG" + # Push commit and tag atomically — without --atomic, Git could + # accept the tag push but reject the main update on a non-fast-forward, + # leaving an orphaned tag at the pre-bump commit (and tripping the + # "tag already exists" guard on the next re-run). --atomic makes the + # whole multi-ref push succeed or fail as a unit. + git push --atomic origin main "$TAG" - name: Dry-run summary if: ${{ inputs.dry_run }}