From fa39d29a8b6a23afe475c5631687d25ee0174452 Mon Sep 17 00:00:00 2001 From: foxnne Date: Thu, 8 Oct 2026 08:20:50 -0500 Subject: [PATCH] ci: sdk-tag never replaces a released SDK tarball Every push to main touching `sdk/**` ran the pack and publish steps even when the version's tag already existed, and the publish step uploaded with `--clobber`: the released `fizzy-sdk-v.tar.gz` was replaced by main's later `sdk/`. Plugins pin that asset by hash, so a replaced one fails every clean fetch. It has happened: `sdk-v0.2.15` was released on 10-02 and its tarball repacked from #207's merge on 10-04 (the asset's creation time is that run's). Now a push that leaves `sdk_version` alone publishes nothing. The tag step reports whether to publish: yes for a tag it just created, and for an existing tag whose release has no tarball (a run that failed after pushing the tag), which is then packed from the tag's own commit, not from main. The upload no longer clobbers, so if `gh` misreports a tarball as missing, the run fails rather than replacing it. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/sdk-tag.yml | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/.github/workflows/sdk-tag.yml b/.github/workflows/sdk-tag.yml index cd214441..d6ea408d 100644 --- a/.github/workflows/sdk-tag.yml +++ b/.github/workflows/sdk-tag.yml @@ -10,6 +10,12 @@ name: SDK tag # `sdk-v*` is a separate namespace from the app's `v*` release tags (release.yml triggers on # `tags: ["v*"]`, a glob on the ref's start — `sdk-v...` doesn't start with `v`, so this can # never fire the app build/package pipeline). +# +# A released tarball is never replaced. Plugins pin it by hash, so packing a later `main` into an +# existing tag's release breaks every one of them on a clean fetch — which is what happened to +# `sdk-v0.2.15`, repacked from #207's merge two days after it shipped. A push that leaves +# `sdk_version` alone therefore publishes nothing. The one exception is a release whose tarball +# is missing (a run that failed after pushing the tag): it is packed from the tag's own commit. on: push: @@ -58,13 +64,24 @@ jobs: echo "Resolved sdk_version -> $tag" - name: Create tag if missing + id: tag + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} shell: bash run: | set -euo pipefail tag="${{ steps.ver.outputs.tag }}" + asset="fizzy-sdk-v${{ steps.ver.outputs.version }}.tar.gz" if git rev-parse -q --verify "refs/tags/$tag" >/dev/null; then - echo "Tag $tag already exists." + if gh release view "$tag" --json assets --jq '.assets[].name' 2>/dev/null | grep -qxF "$asset"; then + echo "Tag $tag and its $asset already exist: nothing to publish." + echo "publish=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + echo "Tag $tag exists without $asset: packing it from the tag's own commit." + git checkout -q "$tag" + echo "publish=true" >> "$GITHUB_OUTPUT" exit 0 fi @@ -73,8 +90,10 @@ jobs: git tag -a "$tag" -m "SDK ${{ steps.ver.outputs.version }} (plugin pin + ABI fingerprint)" git push origin "$tag" echo "Pushed $tag" + echo "publish=true" >> "$GITHUB_OUTPUT" - name: Build changelog since previous SDK tag + if: steps.tag.outputs.publish == 'true' id: changelog shell: bash run: | @@ -118,6 +137,7 @@ jobs: cat "$out" - name: Pack SDK tarball + if: steps.tag.outputs.publish == 'true' shell: bash run: | set -euo pipefail @@ -126,6 +146,7 @@ jobs: ls -la zig-out/sdk/ - name: Publish GitHub release asset + if: steps.tag.outputs.publish == 'true' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} shell: bash @@ -166,10 +187,10 @@ jobs: printf '\n---\n\n' >>"$notes_file" cat "${{ steps.changelog.outputs.file }}" >>"$notes_file" - # Idempotent: create the release if missing, else replace the sdk asset + notes. + # A release that exists here is one without its tarball (the tag step stops otherwise). if gh release view "$tag" >/dev/null 2>&1; then - echo "Release $tag exists — uploading/replacing asset and refreshing notes." - gh release upload "$tag" "$asset" --clobber + echo "Release $tag exists without its tarball — uploading it and refreshing notes." + gh release upload "$tag" "$asset" gh release edit "$tag" --notes-file "$notes_file" else # Never GitHub's "latest": that is the app's newest `v*` release, and