Skip to content

Commit 469e167

Browse files
committed
Harden canary workflow: HEAD guards, ordering, notes escaping
1 parent b135585 commit 469e167

1 file changed

Lines changed: 57 additions & 30 deletions

File tree

.github/workflows/release-canary.yml

Lines changed: 57 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,50 @@ jobs:
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

@@ -56,6 +97,19 @@ jobs:
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

Comments
 (0)