From 510ab8e88b7fb2d741a090b3698c37c3e39a0374 Mon Sep 17 00:00:00 2001 From: fOuttaMyPaint Date: Thu, 4 Jun 2026 20:58:07 -0400 Subject: [PATCH] ci: clean up draft release on failed release runs Adds a cleanup-failed-release job to the tag release path. The draft-then-publish flow leaves a draft release if the upload matrix fails partway, since publish-release is then skipped. That draft is invisible to the public but lingers until removed by hand. This job runs only when a tag-triggered release run failed (if: failure() and ref is a v* tag) and needs the release-stage jobs so it does not fire on ordinary non-tag build failures. It deletes the draft release for the tag and the tag ref, so a partial release leaves nothing behind. It only deletes a draft (never a published release), is a no-op when nothing matches, and scopes contents: write to itself. Co-authored-by: Cursor --- .github/workflows/go.yml | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 77e5947..9beef45 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -174,3 +174,43 @@ jobs: draft: false env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # Failure-path cleanup. If the upload matrix fails partway, publish-release is + # skipped and the draft release created above would otherwise linger + # invisibly until someone removes it by hand. This job runs only when a + # tag-triggered release run failed. It deletes the draft release for this tag + # and the tag ref so a partial release leaves nothing behind. It only ever + # deletes a draft (never a published release) and is a no-op when there is + # nothing to clean, so it is safe and idempotent. + cleanup-failed-release: + needs: [create-release, upload-assets] + if: ${{ failure() && startsWith(github.ref, 'refs/tags/v') }} + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Remove draft release and tag for failed run + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG: ${{ github.ref_name }} + REPO: ${{ github.repository }} + shell: bash + run: | + set -euo pipefail + rel=$(gh api "repos/${REPO}/releases" --jq "([.[] | select(.tag_name==\"${TAG}\")][0]) // empty") + if [ -z "${rel}" ]; then + echo "No release found for ${TAG}; nothing to clean." + exit 0 + fi + id=$(printf '%s' "${rel}" | jq -r '.id') + draft=$(printf '%s' "${rel}" | jq -r '.draft') + if [ "${draft}" != "true" ]; then + echo "Release ${id} for ${TAG} is published (draft=${draft}); leaving it intact." + exit 0 + fi + echo "Deleting draft release ${id} for ${TAG}." + gh api -X DELETE "repos/${REPO}/releases/${id}" + echo "Deleting tag ref ${TAG}." + gh api -X DELETE "repos/${REPO}/git/refs/tags/${TAG}" || echo "Tag ref already removed." + echo "Cleanup complete for ${TAG}."