{{ message }}
Repository navigation
286 lines (280 loc) · 12.1 KB
/
Copy pathverify-install-channels.yml
File metadata and controls
286 lines (280 loc) · 12.1 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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
name: Verify Install Channels
# Post-publish end-to-end verification that the *published* install channels
# (Homebrew, Scoop, and the curl|bash install script) actually install the
# just-released CLI and serve artifacts whose checksums match what the channel
# manifests declare. Runs automatically after every brew/scoop publish (called
# from release-shared.yml's `verify-install-channels` job) and can also be
# dispatched manually against any already-published version when debugging an
# install regression.
#
# Exists primarily to catch regressions like CLI v2.107.0, where the Homebrew
# formula and Scoop manifest shipped sha256 checksums that did not match the
# tarballs on the GitHub Release, so `brew install` / `scoop install` failed
# for every user with "Formula reports different checksum". brew, scoop, and
# the install script all verify the declared checksum against the downloaded
# bytes before installing, so a real install reproduces that failure exactly
# instead of trusting the manifest the publish step wrote.
#
# Each leg goes beyond `supabase --version` (handled by the Bun wrapper without
# touching the sidecar) and runs `supabase completion bash`, a Go-proxied
# command, so a package that omits or misplaces the colocated `supabase-go`
# sidecar fails here instead of silently shipping broken proxied commands.
on:
workflow_call:
inputs:
version:
description: Supabase CLI version that was just published (with or without leading v)
required: true
type: string
brew_name:
description: Homebrew formula name (e.g. supabase or supabase-beta)
required: true
type: string
scoop_name:
description: Scoop manifest name (e.g. supabase or supabase-beta)
required: true
type: string
workflow_dispatch:
inputs:
version:
description: Supabase CLI version to verify (must already be published; with or without leading v)
required: true
type: string
brew_name:
description: Homebrew formula name (e.g. supabase or supabase-beta)
required: false
type: string
default: supabase
scoop_name:
description: Scoop manifest name (e.g. supabase or supabase-beta)
required: false
type: string
default: supabase
permissions:
contents: read
jobs:
homebrew:
# macOS and Linux exercise different stanzas of the formula
# (`on_macos` vs `on_linux`), each with its own URL + sha256, so both must
# install for the tap to be considered verified. Homebrew is preinstalled
# on GitHub-hosted Ubuntu runners.
name: Homebrew ${{ inputs.brew_name }} (${{ matrix.runner }})
strategy:
fail-fast: false
matrix:
runner:
- macos-latest
- ubuntu-latest
runs-on: ${{ matrix.runner }}
timeout-minutes: 10
env:
VERSION: ${{ inputs.version }}
BREW_NAME: ${{ inputs.brew_name }}
# Don't auto-update Homebrew itself before installing; `brew install
# <user>/<tap>/<formula>` taps supabase/homebrew-tap from its git HEAD
# regardless, so the freshly-pushed formula is picked up either way.
#
# NB: do NOT set HOMEBREW_NO_INSTALL_FROM_API here. It only affects the
# homebrew/core + cask taps (third-party taps are always read from git),
# and on Linux runners it forces a large, slow local checkout of
# homebrew/core that makes this job hang for 10+ minutes.
HOMEBREW_NO_AUTO_UPDATE: "1"
steps:
- name: Set up Homebrew on PATH
if: runner.os == 'Linux'
run: |
set -euo pipefail
# Homebrew ships preinstalled on GitHub's Ubuntu runners but is not on
# PATH in the non-login shells `run:` steps use, so expose it for the
# steps below. macOS runners already have `brew` on PATH.
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
echo "${HOMEBREW_PREFIX}/bin" >> "$GITHUB_PATH"
echo "${HOMEBREW_PREFIX}/sbin" >> "$GITHUB_PATH"
- name: Install from Homebrew tap
run: |
set -euo pipefail
# `brew install <user>/<tap>/<formula>` taps supabase/homebrew-tap at
# its current git HEAD and installs from source, verifying the
# formula's sha256 against the downloaded tarball. A checksum mismatch
# (the v2.107.0 failure mode) aborts the install here.
#
# Retry ONLY Homebrew's intermittent "Broken pipe" failures. During its
# bash startup brew runs pipelines like
# grep -E "^(flags|Features)" /proc/cpuinfo | grep -q ssse3
# where the downstream `grep -q` matches and exits early, closing the
# pipe; the still-writing upstream takes SIGPIPE and brew aborts with
# `Error: Broken pipe` (exit 1). It is a timing race (more likely on
# multi-core runners with a larger /proc/cpuinfo), so it is flaky, not
# deterministic, and a re-run succeeds. macOS reads CPU features via
# sysctl, not /proc/cpuinfo, which is why only the Linux leg hits it.
# Upstream fix: Homebrew/brew#21366.
#
# Any OTHER failure (notably a sha256 mismatch — the regression this
# job exists to catch) is non-transient and fails immediately, so the
# retry never masks a genuinely broken release.
attempts=0
max_attempts=3
while :; do
attempts=$((attempts + 1))
if out="$(brew install "supabase/tap/${BREW_NAME}" 2>&1)"; then
printf '%s\n' "${out}"
break
fi
printf '%s\n' "${out}" >&2
case "${out}" in
*"Broken pipe"*)
if [ "${attempts}" -ge "${max_attempts}" ]; then
echo "brew install still failing with 'Broken pipe' after ${attempts} attempts" >&2
exit 1
fi
echo "Transient Homebrew 'Broken pipe' on attempt ${attempts}; retrying in $((attempts * 5))s..." >&2
sleep "$((attempts * 5))"
;;
*)
echo "brew install failed with a non-transient error; not retrying." >&2
exit 1
;;
esac
done
- name: Verify supabase --version
run: |
set -euo pipefail
# `supabase --version` prints the version without the leading `v`,
# while release tags / dispatch inputs may include it, so strip it
# before comparing.
expected="${VERSION#v}"
actual="$(supabase --version | tr -d '\r' | head -n1)"
echo "supabase --version: ${actual}"
if [ "${actual}" != "${expected}" ]; then
echo "Version mismatch: expected ${expected}, got ${actual}" >&2
exit 1
fi
- name: Verify Go sidecar
run: |
set -euo pipefail
# `completion bash` is proxied to the colocated `supabase-go` sidecar,
# so this fails (NotFound: ChildProcess.spawn) if the package omitted
# or misplaced supabase-go, even though `--version` above passed.
out="$(supabase completion bash 2>&1)" || {
echo "${out}"
echo "Go sidecar probe failed: 'supabase completion bash' did not exit 0" >&2
exit 1
}
printf '%s' "${out}" | grep -q "supabase" || {
echo "${out}"
echo "Go sidecar probe failed: unexpected completion output" >&2
exit 1
}
echo "Go sidecar probe OK"
scoop:
name: Scoop (${{ inputs.scoop_name }})
runs-on: windows-latest
timeout-minutes: 10
env:
VERSION: ${{ inputs.version }}
SCOOP_NAME: ${{ inputs.scoop_name }}
steps:
- name: Install Scoop
shell: pwsh
run: |
iex "& {$(irm get.scoop.sh)} -RunAsAdmin"
Join-Path (Resolve-Path ~).Path "scoop\shims" >> $env:GITHUB_PATH
- name: Install from Scoop bucket
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
# Adding the bucket clones supabase/scoop-bucket at its current HEAD;
# `scoop install` then verifies the manifest hash against the
# downloaded tarball before extracting it. A hash mismatch (the
# v2.107.0 failure mode) aborts the install here.
scoop bucket add supabase https://github.com/supabase/scoop-bucket
scoop install "supabase/$env:SCOOP_NAME"
- name: Verify supabase --version
# Force bash so ${VERSION} expands the same way it does on the other
# legs — windows-latest defaults to pwsh, which treats it as an empty
# PowerShell variable (env vars are `$env:VAR`).
shell: bash
run: |
set -euo pipefail
expected="${VERSION#v}"
actual="$(supabase --version | tr -d '\r' | head -n1)"
echo "supabase --version: ${actual}"
if [ "${actual}" != "${expected}" ]; then
echo "Version mismatch: expected ${expected}, got ${actual}" >&2
exit 1
fi
- name: Verify Go sidecar
shell: bash
run: |
set -euo pipefail
# `completion bash` is proxied to the colocated `supabase-go` sidecar,
# so this fails if the package omitted or misplaced supabase-go.exe,
# even though `--version` above passed.
out="$(supabase completion bash 2>&1)" || {
echo "${out}"
echo "Go sidecar probe failed: 'supabase completion bash' did not exit 0" >&2
exit 1
}
printf '%s' "${out}" | grep -q "supabase" || {
echo "${out}"
echo "Go sidecar probe failed: unexpected completion output" >&2
exit 1
}
echo "Go sidecar probe OK"
install-script:
name: install script (${{ matrix.runner }})
strategy:
fail-fast: false
matrix:
runner:
- ubuntu-latest
- macos-latest
runs-on: ${{ matrix.runner }}
timeout-minutes: 10
env:
VERSION: ${{ inputs.version }}
steps:
- name: Install via the published install script
shell: bash
run: |
set -euo pipefail
version="${VERSION#v}"
# Fetch the install script that shipped with THIS release (uploaded as
# a release asset by release-shared.yml's publish job) rather than the
# copy in the repo checkout — users run the published script, which can
# diverge from the release branch. The script downloads the GitHub
# Release tarball plus checksums.txt and aborts on a sha256 mismatch.
# --no-modify-path keeps it from editing the runner's shell rc files;
# in GitHub Actions it still appends the install dir to $GITHUB_PATH,
# so `supabase` is on PATH for the verification steps below.
curl -fsSL "https://github.com/supabase/cli/releases/download/v${version}/install" -o install.sh
bash install.sh --version "${version}" --no-modify-path
- name: Verify supabase --version
shell: bash
run: |
set -euo pipefail
expected="${VERSION#v}"
actual="$(supabase --version | tr -d '\r' | head -n1)"
echo "supabase --version: ${actual}"
if [ "${actual}" != "${expected}" ]; then
echo "Version mismatch: expected ${expected}, got ${actual}" >&2
exit 1
fi
- name: Verify Go sidecar
shell: bash
run: |
set -euo pipefail
# `completion bash` is proxied to the colocated `supabase-go` sidecar,
# so this fails if the install script did not place supabase-go next
# to supabase, even though `--version` above passed.
out="$(supabase completion bash 2>&1)" || {
echo "${out}"
echo "Go sidecar probe failed: 'supabase completion bash' did not exit 0" >&2
exit 1
}
printf '%s' "${out}" | grep -q "supabase" || {
echo "${out}"
echo "Go sidecar probe failed: unexpected completion output" >&2
exit 1
}
echo "Go sidecar probe OK"
You can’t perform that action at this time.
