From 26ca6220a2a60ebfe5bd6729af1212d66c57a952 Mon Sep 17 00:00:00 2001 From: Manuk Date: Tue, 28 Apr 2026 13:36:34 +0400 Subject: [PATCH] ci(release): make release creation idempotent Previously the workflow failed with "Release.tag_name already exists" when a release was authored manually (which auto-creates the tag and triggers this workflow). Skip creation if the release already exists. Also drop the now-unused checkout steps and use the GitHub API for tag deletion in the cleanup job, which removes the need for a working tree. --- .github/workflows/release.yml | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 038b6eec..c5685095 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,23 +18,29 @@ jobs: runs-on: ubuntu-latest steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Determine if pre-release - id: prerelease + - name: Determine release flags + id: flags + env: + TAG: ${{ github.ref_name }} run: | - TAG="${{ github.ref_name }}" if [[ "$TAG" == *"-"* ]]; then - echo "flag=--prerelease" >> $GITHUB_OUTPUT + echo "prerelease=--prerelease" >> "$GITHUB_OUTPUT" else - echo "flag=" >> $GITHUB_OUTPUT + echo "prerelease=" >> "$GITHUB_OUTPUT" fi - name: Create GitHub Release - run: gh release create "${{ github.ref_name }}" --generate-notes ${{ steps.prerelease.outputs.flag }} env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + TAG: ${{ github.ref_name }} + PRERELEASE_FLAG: ${{ steps.flags.outputs.prerelease }} + run: | + if gh release view "$TAG" >/dev/null 2>&1; then + echo "Release $TAG already exists, skipping creation." + exit 0 + fi + gh release create "$TAG" --generate-notes $PRERELEASE_FLAG cleanup: needs: tests @@ -44,8 +50,9 @@ jobs: contents: write steps: - - name: Checkout code - uses: actions/checkout@v6 - - name: Delete tag on test failure - run: git push --delete origin "${{ github.ref_name }}" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + TAG: ${{ github.ref_name }} + run: gh api -X DELETE "repos/$GH_REPO/git/refs/tags/$TAG"