@@ -120,31 +120,35 @@ jobs:
120120 labels : ${{ steps.docker-meta.outputs.labels }}
121121 annotations : ${{ steps.docker-meta.outputs.annotations }}
122122
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
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
128127 env :
129128 GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
130129 REPO : ${{ github.repository }}
131130 SHA : ${{ github.sha }}
132131 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 }}
133145 TITLE : ${{ steps.canary-meta.outputs.title }}
134146 NOTES_FILE : ${{ steps.canary-meta.outputs.notes_file }}
135147 run : |
136148 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
142149 if gh release view "$TAG" >/dev/null 2>&1; then
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
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
147154 fi
148- gh release create "$TAG" octi-server-canary.zip \
149- --title "$TITLE" --notes-file "$NOTES_FILE" \
150- --prerelease --target "$SHA"
0 commit comments