From 70491dbbe40055f2c04c9a526115963284f88ae6 Mon Sep 17 00:00:00 2001 From: JeffreyChen Date: Tue, 21 Apr 2026 18:49:42 +0800 Subject: [PATCH 1/2] Handle pre-existing bump branch in stable publish When release/bump-v already exists from a prior run, query its actual tip and pass it as expectedHeadOid. Fixes STALE_DATA from createCommitOnBranch after a partial retry. --- .github/workflows/ci-stable.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-stable.yml b/.github/workflows/ci-stable.yml index 80d1200..f2c6397 100644 --- a/.github/workflows/ci-stable.yml +++ b/.github/workflows/ci-stable.yml @@ -146,9 +146,15 @@ jobs: method="POST", body={"ref": f"refs/heads/{branch}", "sha": head_oid}, ) + expected_oid = head_oid except urllib.error.HTTPError as error: if error.code != 422: # 422 = ref already exists; OK to reuse raise + # Branch already exists (likely from a previous run); use its + # actual tip as expectedHeadOid so createCommitOnBranch doesn't + # fail with STALE_DATA. + ref_info = api(f"repos/{repo}/git/ref/heads/{branch}") + expected_oid = ref_info["object"]["sha"] def b64(path: str) -> str: with open(path, "rb") as fp: @@ -173,7 +179,7 @@ jobs: "message": { "headline": f"Bump version to v{version} [skip ci]", }, - "expectedHeadOid": head_oid, + "expectedHeadOid": expected_oid, "fileChanges": { "additions": [ {"path": "stable.toml", "contents": b64("stable.toml")}, From c459f800c84c04ac3f34119d86bbfd80423a11c6 Mon Sep 17 00:00:00 2001 From: JeffreyChen Date: Tue, 21 Apr 2026 18:51:56 +0800 Subject: [PATCH 2/2] Always start bump from a fresh release branch Delete any pre-existing release/bump-v branch before creating it, so the version bump always sits directly on main's HEAD. Prevents STALE_DATA from createCommitOnBranch and avoids stacking multiple bump commits when a prior publish run failed partway through. --- .github/workflows/ci-stable.yml | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci-stable.yml b/.github/workflows/ci-stable.yml index f2c6397..3213470 100644 --- a/.github/workflows/ci-stable.yml +++ b/.github/workflows/ci-stable.yml @@ -140,21 +140,24 @@ jobs: raw = resp.read() return json.loads(raw) if raw else None + # Delete any pre-existing release branch (from a prior partial run) + # so the bump always starts from main's HEAD. Avoids STALE_DATA from + # createCommitOnBranch and prevents stacking multiple bump commits. + # Any open PR on the stale branch gets auto-closed when the branch + # is deleted, which is fine — we always open a fresh PR below. try: - api( - f"repos/{repo}/git/refs", - method="POST", - body={"ref": f"refs/heads/{branch}", "sha": head_oid}, - ) - expected_oid = head_oid + api(f"repos/{repo}/git/refs/heads/{branch}", method="DELETE") + print(f"deleted stale branch: {branch}") except urllib.error.HTTPError as error: - if error.code != 422: # 422 = ref already exists; OK to reuse + if error.code not in (404, 422): # ref doesn't exist; nothing to clean raise - # Branch already exists (likely from a previous run); use its - # actual tip as expectedHeadOid so createCommitOnBranch doesn't - # fail with STALE_DATA. - ref_info = api(f"repos/{repo}/git/ref/heads/{branch}") - expected_oid = ref_info["object"]["sha"] + + api( + f"repos/{repo}/git/refs", + method="POST", + body={"ref": f"refs/heads/{branch}", "sha": head_oid}, + ) + expected_oid = head_oid def b64(path: str) -> str: with open(path, "rb") as fp: