-
Notifications
You must be signed in to change notification settings - Fork 1
160 lines (147 loc) · 6.52 KB
/
Copy pathrelease-canary.yml
File metadata and controls
160 lines (147 loc) · 6.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
name: Rolling canary build
# Triggered after the "Code tests & eval" workflow succeeds on main — so
# :canary always reflects the latest *tested* commit, never an untested or
# red-on-main one. Publishes the `:canary` Docker image; the Pages canary
# subpath at web.octi.darken.eu/canary/ is deployed by the separate
# deploy-pages.yml (workflow_run on this workflow's success).
#
# Naming follows the cross-vendor convention (Chrome Canary, GitHub canary
# deploys). The companion in-app banner says "Canary build" + "This is a
# bleeding edge build" — see src/ui/CanaryBanner.svelte.
on:
workflow_dispatch:
workflow_run:
workflows: ["Code tests & eval"]
types: [completed]
permissions:
contents: read
# Per-job concurrency (no workflow-level cancel) so publish can't be killed
# mid-run by a fresh push. Stale-SHA guard inside the publish step aborts if
# main has moved past us during the build window.
jobs:
compute-version:
name: Compute canary version
# workflow_dispatch always proceeds; workflow_run only when the upstream
# code-checks completed successfully on a push to main (skip PR runs and
# failures). Mirrors deploy-pages.yml's filter pattern.
if: |
github.event_name == 'workflow_dispatch' ||
(github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'push' &&
github.event.workflow_run.head_branch == 'main')
runs-on: ubuntu-22.04
concurrency:
group: release-canary-build-${{ github.repository }}
cancel-in-progress: true
outputs:
version: ${{ steps.derive.outputs.version }}
short_sha: ${{ steps.derive.outputs.short_sha }}
should_run: ${{ steps.skip-check.outputs.should_run }}
steps:
- name: Guard ref must be main
env:
REF: ${{ github.ref }}
run: |
set -euo pipefail
if [[ "$REF" != "refs/heads/main" ]]; then
echo "::error::canary must run on main (got '$REF')"
exit 1
fi
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
# Pin to the SHA that code-checks tested. With workflow_run trigger,
# github.sha is the default-branch tip at trigger time (which may
# have moved past the tested SHA); workflow_run.head_sha is the SHA
# the upstream actually ran on. Falls back to github.sha for
# workflow_dispatch.
ref: ${{ github.event.workflow_run.head_sha || github.sha }}
fetch-depth: 2
persist-credentials: false
- name: Skip release-bump commits
id: skip-check
run: |
set -euo pipefail
msg=$(git log -1 --pretty=%s)
# The release-prepare workflow pushes commits titled "Release: vX.Y.Z".
# Canary must NOT publish those — the release-tag workflow is the
# only mover for stable, and a canary publish from the same commit
# could race ahead of release-tag's E2E gate.
if [[ "$msg" =~ ^Release: ]]; then
echo "::notice::skipping canary for release-bump commit: $msg"
echo "should_run=false" >> "$GITHUB_OUTPUT"
else
echo "should_run=true" >> "$GITHUB_OUTPUT"
fi
- name: Derive canary version
id: derive
if: steps.skip-check.outputs.should_run == 'true'
run: |
set -euo pipefail
base=$(node -p "require('./package.json').version")
# Strip any -rc/-beta/-canary suffix from the package.json base. We want
# the X.Y.Z numeric core; -canary.<sha8> is appended below.
base_numeric=$(echo "$base" | sed -E 's/-(rc[0-9]+|beta[0-9]+|canary\.[0-9a-zA-Z]+)$//')
short=$(git rev-parse --short=8 HEAD)
echo "version=${base_numeric}-canary.${short}" >> "$GITHUB_OUTPUT"
echo "short_sha=${short}" >> "$GITHUB_OUTPUT"
build-and-publish-docker:
needs: [compute-version]
if: needs.compute-version.outputs.should_run == 'true'
name: Publish :canary Docker image (ghcr.io)
concurrency:
# Separate group from build so a fresh build cancelling an older build
# doesn't take this job down mid-publish.
group: release-canary-publish-${{ github.repository }}
cancel-in-progress: false
runs-on: ubuntu-22.04
permissions:
contents: read
packages: write
steps:
- name: Checkout main
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: main
fetch-depth: 1
persist-credentials: false
- name: Stale-SHA guard
# If main moved past the tested SHA during the build window, abort. A
# newer code-checks run will trigger a newer canary publish and we
# shouldn't move `:canary` backwards. EXPECTED_SHA is the SHA that
# code-checks ran on (workflow_run.head_sha); falls back to github.sha
# for workflow_dispatch.
env:
EXPECTED_SHA: ${{ github.event.workflow_run.head_sha || github.sha }}
run: |
set -euo pipefail
actual=$(git rev-parse HEAD)
if [[ "$actual" != "$EXPECTED_SHA" ]]; then
echo "::warning::main moved during build window (was $EXPECTED_SHA, now $actual). Aborting canary publish — a newer run will replace this."
exit 1
fi
- name: Log in to ghcr.io
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Build and push image
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository }}:canary
ghcr.io/${{ github.repository }}:canary-${{ needs.compute-version.outputs.short_sha }}
platforms: linux/amd64,linux/arm64
# Canary Docker images serve the SPA at root path (/) — the
# subpath-mounting only applies to GitHub Pages. Self-hosters who
# pull :canary get a fully-functional standalone build.
build-args: |
VITE_BASE=/
VITE_CHANNEL=canary
VITE_COMMIT_SHA=${{ github.event.workflow_run.head_sha || github.sha }}
VITE_APP_VERSION=${{ needs.compute-version.outputs.version }}