2424 fetch-depth : 0
2525 persist-credentials : false
2626
27+ - name : Guard - workflow SHA must match main HEAD
28+ env :
29+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
30+ REPO : ${{ github.repository }}
31+ SHA : ${{ github.sha }}
32+ run : |
33+ set -euo pipefail
34+ main_head=$(gh api "repos/${REPO}/git/ref/heads/main" --jq .object.sha)
35+ if [[ "$main_head" != "$SHA" ]]; then
36+ echo "::error::main HEAD ($main_head) differs from workflow SHA ($SHA); refusing to publish canary"
37+ exit 1
38+ fi
39+
2740 - name : Setup project and build environment
2841 uses : ./.github/actions/common-setup
2942
43+ - name : Package application
44+ run : ./gradlew installDist
45+
46+ - name : Create ZIP file from the directory
47+ run : zip -r octi-server-canary.zip ./build/install/octi-server
48+
49+ - name : Prepare canary metadata
50+ id : canary-meta
51+ env :
52+ REPO : ${{ github.repository }}
53+ SHA : ${{ github.sha }}
54+ run : |
55+ set -euo pipefail
56+ short_sha="${SHA:0:7}"
57+ tag="canary"
58+ title="Canary (${short_sha})"
59+ notes_file="canary-notes.md"
60+ {
61+ printf '## Octi Server Canary\n\n'
62+ printf 'This is a rolling bleeding-edge pre-release built from `main`.\n\n'
63+ printf -- '- Commit: `%s`\n' "$SHA"
64+ printf -- '- Docker tags: `ghcr.io/%s:canary`, `ghcr.io/%s:sha-%s`\n\n' "$REPO" "$REPO" "$short_sha"
65+ printf 'Do not use this build for production unless you accept breakage risk.\n'
66+ } > "$notes_file"
67+ echo "tag=$tag" >> "$GITHUB_OUTPUT"
68+ echo "title=$title" >> "$GITHUB_OUTPUT"
69+ echo "notes_file=$notes_file" >> "$GITHUB_OUTPUT"
70+
3071 - name : Set up QEMU
3172 uses : docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
3273
5697 env :
5798 DOCKER_METADATA_ANNOTATIONS_LEVELS : manifest,index
5899
100+ - name : Guard - main HEAD must still match before publishing
101+ env :
102+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
103+ REPO : ${{ github.repository }}
104+ SHA : ${{ github.sha }}
105+ run : |
106+ set -euo pipefail
107+ main_head=$(gh api "repos/${REPO}/git/ref/heads/main" --jq .object.sha)
108+ if [[ "$main_head" != "$SHA" ]]; then
109+ echo "::error::main HEAD ($main_head) advanced past workflow SHA ($SHA); aborting before Docker push"
110+ exit 1
111+ fi
112+
59113 - name : Build and push Docker image
60114 uses : docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
61115 with :
@@ -66,36 +120,9 @@ jobs:
66120 labels : ${{ steps.docker-meta.outputs.labels }}
67121 annotations : ${{ steps.docker-meta.outputs.annotations }}
68122
69- - name : Package application
70- run : ./gradlew installDist
71-
72- - name : Create ZIP file from the directory
73- run : zip -r octi-server-canary.zip ./build/install/octi-server
74-
75- - name : Prepare canary metadata
76- id : canary-meta
77- env :
78- SHA : ${{ github.sha }}
79- run : |
80- set -euo pipefail
81- short_sha="${SHA:0:7}"
82- tag="canary"
83- title="Canary (${short_sha})"
84- notes_file="canary-notes.md"
85- {
86- echo "## Octi Server Canary"
87- echo
88- echo "This is a rolling bleeding-edge pre-release built from \\`main\\`."
89- echo
90- echo "- Commit: \\`${SHA}\\`"
91- echo "- Docker tags: \\`ghcr.io/${{ github.repository }}:canary\\`, \\`ghcr.io/${{ github.repository }}:sha-${short_sha}\\`"
92- echo
93- echo "Do not use this build for production unless you accept breakage risk."
94- } > "$notes_file"
95- echo "tag=$tag" >> "$GITHUB_OUTPUT"
96- echo "title=$title" >> "$GITHUB_OUTPUT"
97- echo "notes_file=$notes_file" >> "$GITHUB_OUTPUT"
98-
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.
99126 - name : Move canary tag to current commit
100127 env :
101128 GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
0 commit comments