@@ -120,35 +120,31 @@ jobs:
120120 labels : ${{ steps.docker-meta.outputs.labels }}
121121 annotations : ${{ steps.docker-meta.outputs.annotations }}
122122
123- # The `canary` tag is intentionally mutable. Per .claude/rules/release.md, tag rulesets
124- # in this org cover only `main` and `v*` tags, so GITHUB_TOKEN can force-update it.
125- # If a future ruleset covers `canary*`, switch this step to an App token.
126- - name : Move canary tag to current commit
123+ # GitHub's immutable-releases feature on this repo prevents editing existing releases
124+ # and their tags. Rolling canary is therefore implemented as delete-then-create on
125+ # every run. Per .claude/rules/release.md, tag rulesets cover only `main` and `v*`,
126+ # so deletion of `canary` via GITHUB_TOKEN is permitted.
127+ - name : Replace rolling canary release
127128 env :
128129 GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
129130 REPO : ${{ github.repository }}
130131 SHA : ${{ github.sha }}
131132 TAG : ${{ steps.canary-meta.outputs.tag }}
132- run : |
133- set -euo pipefail
134- if gh api "repos/${REPO}/git/ref/tags/${TAG}" >/dev/null 2>&1; then
135- gh api --method PATCH "repos/${REPO}/git/refs/tags/${TAG}" -f sha="$SHA" -F force=true >/dev/null
136- else
137- gh api --method POST "repos/${REPO}/git/refs" -f ref="refs/tags/${TAG}" -f sha="$SHA" >/dev/null
138- fi
139-
140- - name : Update rolling canary pre-release
141- env :
142- GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
143- SHA : ${{ github.sha }}
144- TAG : ${{ steps.canary-meta.outputs.tag }}
145133 TITLE : ${{ steps.canary-meta.outputs.title }}
146134 NOTES_FILE : ${{ steps.canary-meta.outputs.notes_file }}
147135 run : |
148136 set -euo pipefail
137+ main_head=$(gh api "repos/${REPO}/git/ref/heads/main" --jq .object.sha)
138+ if [[ "$main_head" != "$SHA" ]]; then
139+ echo "::error::main HEAD ($main_head) advanced past workflow SHA ($SHA); refusing to replace canary"
140+ exit 1
141+ fi
149142 if gh release view "$TAG" >/dev/null 2>&1; then
150- gh release upload "$TAG" octi-server-canary.zip --clobber
151- gh release edit "$TAG" --title "$TITLE" --notes-file "$NOTES_FILE" --prerelease
152- else
153- gh release create "$TAG" octi-server-canary.zip --title "$TITLE" --notes-file "$NOTES_FILE" --prerelease --target "$SHA" --verify-tag
143+ gh release delete "$TAG" --yes
144+ fi
145+ if gh api "repos/${REPO}/git/ref/tags/${TAG}" >/dev/null 2>&1; then
146+ gh api --method DELETE "repos/${REPO}/git/refs/tags/${TAG}" >/dev/null
154147 fi
148+ gh release create "$TAG" octi-server-canary.zip \
149+ --title "$TITLE" --notes-file "$NOTES_FILE" \
150+ --prerelease --target "$SHA"
0 commit comments