From f0f9d38b7c72310e0b6f3493a7fbecc81547bb76 Mon Sep 17 00:00:00 2001 From: andychoquette <78888816+andychoquette@users.noreply.github.com> Date: Wed, 23 Sep 2026 09:27:23 -0700 Subject: [PATCH] fix: force-with-lease the bump branch so a stale one cannot fail the push The PushPR step did a plain `git push` of bump/$NEXT_SEMVER. That branch is recreated from $BASE_REF on every run, so when one already exists remotely for the same version it has diverged and the push is rejected non-fast-forward, failing the whole bump. This happens whenever a release PR is closed unmerged and the bump is re-run after $BASE_REF has moved on, which is not rare: deadline-cloud-for-cinema-4d had a bump/0.12.3 left over from a closed PR #560 and every subsequent Bump run failed until the branch was deleted by hand. Nine other stale bump/* branches are sitting in that repo, each one a latent repeat. Force is safe here because the branch only ever holds the release commit this run generated. --force-with-lease rather than --force keeps the protection against a genuinely concurrent push, and Checkout's fetch-depth: 0 guarantees the remote-tracking ref the lease compares against. Deleting the remote branch before pushing was the alternative, but that would close any open release PR for it. Also guard `gh pr create`: a closed PR for the head does not block a new one, but an open one does, and the force-push has already updated it. Signed-off-by: andychoquette <78888816+andychoquette@users.noreply.github.com> --- .github/workflows/reusable_bump.yml | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/.github/workflows/reusable_bump.yml b/.github/workflows/reusable_bump.yml index 452ee99..12be1f3 100644 --- a/.github/workflows/reusable_bump.yml +++ b/.github/workflows/reusable_bump.yml @@ -117,7 +117,22 @@ jobs: # Pass context via env, not inline ${{ }}, to avoid template injection. BASE_REF: ${{ github.ref_name }} run: | - git push -u origin bump/$NEXT_SEMVER - + # bump/$NEXT_SEMVER is recreated from $BASE_REF on every run, so a leftover branch + # from an earlier bump of this same version -- a release PR closed unmerged, then + # re-run after $BASE_REF moved on -- has diverged, and a plain push is rejected + # non-fast-forward. Forcing is safe because the branch only ever holds this run's + # generated release commit. --force-with-lease (not --force) still refuses if the + # remote moved after Checkout fetched it, which fetch-depth: 0 above guarantees a + # remote-tracking ref for. Deleting the remote branch instead would close any open + # release PR for it. + git push --force-with-lease -u origin "bump/$NEXT_SEMVER" + + # A closed PR for this head does not block opening a new one, but an open one does, + # and the push above has already updated it. # Needs "Allow GitHub Actions to create and approve pull requests" under Settings > Actions - gh pr create --base "$BASE_REF" --title "chore(release): $NEXT_SEMVER" --body "$RELEASE_NOTES" + EXISTING_PR=$(gh pr list --head "bump/$NEXT_SEMVER" --state open --json number --jq '.[0].number // empty') + if [[ -n "$EXISTING_PR" ]]; then + echo "bump/$NEXT_SEMVER already has open PR #$EXISTING_PR; the push above updated it." + else + gh pr create --base "$BASE_REF" --title "chore(release): $NEXT_SEMVER" --body "$RELEASE_NOTES" + fi