diff --git a/.github/workflows/auto-tag-on-release-pr-merge.yml b/.github/workflows/auto-tag-on-release-pr-merge.yml index 9472b0a222..05bcceca59 100644 --- a/.github/workflows/auto-tag-on-release-pr-merge.yml +++ b/.github/workflows/auto-tag-on-release-pr-merge.yml @@ -105,8 +105,9 @@ jobs: TAG: ${{ steps.release.outputs.tag }} run: | set -euo pipefail - EXISTING_REF="$(gh api "repos/$GITHUB_REPOSITORY/git/ref/tags/$TAG" --jq .ref 2>/dev/null || true)" - if [ -n "$EXISTING_REF" ]; then + # Check gh's exit status, not its output. A missing ref returns a 404 + # JSON body on stdout, which must not be mistaken for an existing tag. + if gh api "repos/$GITHUB_REPOSITORY/git/ref/tags/$TAG" --silent 2>/dev/null; then EXISTING_SHA="$(gh api "repos/$GITHUB_REPOSITORY/commits/$TAG" --jq .sha)" if [ "$EXISTING_SHA" = "$GITHUB_SHA" ]; then echo "Tag $TAG already exists at $GITHUB_SHA — skipping tag creation" diff --git a/scripts/test-release-ref-contract.sh b/scripts/test-release-ref-contract.sh index 672767f589..5d420695c2 100755 --- a/scripts/test-release-ref-contract.sh +++ b/scripts/test-release-ref-contract.sh @@ -60,6 +60,11 @@ grep -q 'private-key:.*secrets\.BUZZ_RELEASE_TAGGER_PRIVATE_KEY' "$auto_tag" grep -q 'permission-contents: write' "$auto_tag" grep -q 'GH_TOKEN:.*steps\.release-tagger\.outputs\.token' "$auto_tag" grep -Fq 'git/refs' "$auto_tag" +grep -Fq 'if gh api "repos/$GITHUB_REPOSITORY/git/ref/tags/$TAG" --silent 2>/dev/null; then' "$auto_tag" +if grep -F 'git/ref/tags/$TAG' "$auto_tag" | grep -Fq '|| true'; then + echo "auto-tag ignores a failed tag lookup, so a 404 body can look like an existing tag" >&2 + exit 1 +fi if grep -q 'gh workflow run' "$auto_tag"; then echo "auto-tag still dispatches a publisher instead of using the tag push" >&2 exit 1