mirror of
https://github.com/stablyai/orca.git
synced 2026-10-12 08:02:37 +00:00
fix(release): recover orphan tags instead of hard-failing the cut
If a cut pushes the tag but the workflow is cancelled (or the dependent release.yml job otherwise fails to start) before a GitHub release is published, every subsequent patch cut recomputes the same version and dies on "Tag already exists." This wedged the pipeline on 2026-05-01 when v1.3.26 was pushed by cancelled run 25237882049 — patch cuts kept failing for hours until release.yml was dispatched by hand. When the tag exists but no published release is attached, skip the bump/push steps and emit the existing tag as the job output so release.yml runs against it and finishes what the prior attempt started. Still refuse the collision when a real published release exists — that's a genuine conflict (e.g. a hand-tagged version) and needs human attention. Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
@@ -49,7 +49,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
outputs:
|
||||
tag: ${{ steps.tag.outputs.tag }}
|
||||
tag: ${{ steps.tag.outputs.tag || steps.version.outputs.recovered_tag }}
|
||||
steps:
|
||||
- name: Checkout ref
|
||||
uses: actions/checkout@v4
|
||||
@@ -187,10 +187,53 @@ jobs:
|
||||
;;
|
||||
esac
|
||||
|
||||
# Refuse tag collisions (possible if someone already tagged manually).
|
||||
# Orphan-tag recovery.
|
||||
#
|
||||
# Why: if a previous cut pushed the tag but was cancelled (or the
|
||||
# dependent release.yml job otherwise failed to start) before the
|
||||
# GitHub Release was published, the tag now exists on the remote
|
||||
# but "latest stable" still points at the prior version. Every
|
||||
# subsequent patch cut then recomputes the same version and dies
|
||||
# on "Tag already exists." This exact sequence wedged the cut
|
||||
# pipeline on 2026-05-01 when v1.3.26 was pushed by a cancelled
|
||||
# run (25237882049) — every patch cut after that rehit the same
|
||||
# tag for hours until the orphan release was dispatched by hand.
|
||||
#
|
||||
# Recovery policy: if the tag exists AND no GitHub release has
|
||||
# been published for it (draft-or-absent both count as "not
|
||||
# shipped"), treat this as a resumable state: emit the existing
|
||||
# tag as the job output so the downstream release.yml job runs
|
||||
# against it and finishes what the earlier attempt started. The
|
||||
# bump/commit/push steps are skipped in that case — there is
|
||||
# nothing to bump; the tag is already on the remote.
|
||||
#
|
||||
# Refuse collisions only when the tag *and* a published release
|
||||
# already exist — that's a real conflict (someone tagged manually
|
||||
# over a shipped version) and needs human attention.
|
||||
if git rev-parse "v$new" >/dev/null 2>&1; then
|
||||
echo "::error::Tag v$new already exists." >&2
|
||||
exit 1
|
||||
# Use the REST API, not `gh release view`: the latter returns
|
||||
# "release not found" for drafts *and* for absent releases,
|
||||
# which would cause us to "recover" over a draft that a human
|
||||
# is preparing. The API distinguishes them.
|
||||
release_state="$(gh api \
|
||||
"repos/$GITHUB_REPOSITORY/releases/tags/v$new" \
|
||||
--jq '.draft' 2>/dev/null || echo "missing")"
|
||||
case "$release_state" in
|
||||
missing|true)
|
||||
echo "::warning::Tag v$new already exists but no published release is attached — recovering by re-dispatching release.yml against the existing tag."
|
||||
echo "recovered_tag=v$new" >>"$GITHUB_OUTPUT"
|
||||
echo "recovered=true" >>"$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
;;
|
||||
false)
|
||||
echo "::error::Tag v$new already exists and has a published release. Refusing to re-cut over a shipped version." >&2
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
echo "::error::Unexpected release state for v$new: $release_state" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo "version=$new" >>"$GITHUB_OUTPUT"
|
||||
@@ -198,6 +241,7 @@ jobs:
|
||||
|
||||
- name: Bump package.json and tag
|
||||
id: tag
|
||||
if: steps.version.outputs.recovered != 'true'
|
||||
env:
|
||||
VERSION: ${{ steps.version.outputs.version }}
|
||||
run: |
|
||||
@@ -213,6 +257,7 @@ jobs:
|
||||
echo "sha=$(git rev-parse HEAD)" >>"$GITHUB_OUTPUT"
|
||||
|
||||
- name: Push tag
|
||||
if: steps.version.outputs.recovered != 'true'
|
||||
env:
|
||||
PUSH_MAIN: ${{ steps.resolve.outputs.push_main }}
|
||||
TAG: ${{ steps.tag.outputs.tag }}
|
||||
|
||||
Reference in New Issue
Block a user