From 5194a53db461416701b6e8af6e9ec90d0dee35a7 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 17 Jun 2026 17:48:06 +0000 Subject: [PATCH 1/6] ci: verify install channels after publish Add a post-publish verify-install-channels reusable workflow that does a real brew install, scoop install, and curl|bash install-script install against the just-published channels, then asserts supabase --version matches. brew, scoop, and the install script each verify the declared sha256/hash against the downloaded tarball, so this reproduces the exact CLI v2.107.0 failure where the brew/scoop manifests shipped checksums that did not match the release tarballs. Wire it into release-shared.yml alongside setup-cli-smoke (non-gating, runs last) and only for beta/stable, which are the channels that publish brew/scoop. Document it in the release-process playbook. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01RNp9yTyRoDYJTs5xsWRbAr --- .github/workflows/release-shared.yml | 19 +++ .github/workflows/verify-install-channels.yml | 161 ++++++++++++++++++ apps/cli/docs/release-process.md | 12 +- 3 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/verify-install-channels.yml diff --git a/.github/workflows/release-shared.yml b/.github/workflows/release-shared.yml index 43577b3535..3e29e03850 100644 --- a/.github/workflows/release-shared.yml +++ b/.github/workflows/release-shared.yml @@ -538,3 +538,22 @@ jobs: uses: ./.github/workflows/setup-cli-smoke-test.yml with: version: ${{ inputs.version }} + + # Post-publish end-to-end check that the Homebrew tap, Scoop bucket, and the + # curl|bash install script actually install the just-released CLI. brew/scoop + # verify the published checksum against the downloaded tarball, so this is the + # signal that would have caught CLI v2.107.0 (mismatched brew/scoop sha256s). + # + # Only runs when brew/scoop were published (beta/stable) and both pushes + # succeeded — alpha publishes neither channel and is covered by the GitHub + # Release download path in setup-cli-smoke. Like setup-cli-smoke, it runs last + # and does not gate the rest of the channel: by the time it runs the manifests + # are already live, so a failure surfaces as a red post-release signal. + verify-install-channels: + needs: [publish, publish-homebrew, publish-scoop] + if: ${{ always() && !inputs.dry_run && inputs.publish_brew_scoop && needs.publish-homebrew.result == 'success' && needs.publish-scoop.result == 'success' }} + uses: ./.github/workflows/verify-install-channels.yml + with: + version: ${{ inputs.version }} + brew_name: ${{ inputs.brew_name }} + scoop_name: ${{ inputs.scoop_name }} diff --git a/.github/workflows/verify-install-channels.yml b/.github/workflows/verify-install-channels.yml new file mode 100644 index 0000000000..a6eb2030ea --- /dev/null +++ b/.github/workflows/verify-install-channels.yml @@ -0,0 +1,161 @@ +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. + +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: + name: Homebrew (${{ inputs.brew_name }}) + runs-on: macos-latest + env: + VERSION: ${{ inputs.version }} + BREW_NAME: ${{ inputs.brew_name }} + # Skip the formulae.brew.sh API and read the tap straight from its git + # HEAD, so a formula pushed seconds ago is picked up immediately. Auto + # update is disabled because the explicit tap clone already fetches HEAD + # and updating homebrew/core here only adds latency and flake. + HOMEBREW_NO_INSTALL_FROM_API: "1" + HOMEBREW_NO_AUTO_UPDATE: "1" + steps: + - name: Install from Homebrew tap + run: | + set -euo pipefail + # `brew install //` 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. + brew install "supabase/tap/${BREW_NAME}" + - 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 + + scoop: + name: Scoop (${{ inputs.scoop_name }}) + runs-on: windows-latest + 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 + + install-script: + name: install script (${{ matrix.runner }}) + strategy: + fail-fast: false + matrix: + runner: + - ubuntu-latest + - macos-latest + runs-on: ${{ matrix.runner }} + env: + VERSION: ${{ inputs.version }} + steps: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + - name: Install via install script + shell: bash + run: | + set -euo pipefail + # The install script downloads the GitHub Release tarball plus + # checksums.txt and aborts on a sha256 mismatch (verify_checksum). + # --no-modify-path keeps it from editing the runner's shell rc files. + ./install --version "${VERSION#v}" --no-modify-path + - name: Verify supabase --version + shell: bash + run: | + set -euo pipefail + expected="${VERSION#v}" + actual="$("$HOME/.supabase/bin/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 diff --git a/apps/cli/docs/release-process.md b/apps/cli/docs/release-process.md index 84c6801897..81a92dc389 100644 --- a/apps/cli/docs/release-process.md +++ b/apps/cli/docs/release-process.md @@ -240,6 +240,9 @@ flowchart TD pub --> rel["softprops/action-gh-release
(draft) → gh release edit --draft=false"] rel --> hb["publish-homebrew
App-token-authed clone of homebrew-tap
update-homebrew.ts --name "] rel --> sc["publish-scoop
App-token-authed clone of scoop-bucket
update-scoop.ts --name "] + rel --> sucs["setup-cli-smoke
install via supabase/setup-cli
(GitHub Release download)"] + hb --> vic["verify-install-channels
real brew/scoop/install-script installs
against the live channels"] + sc --> vic ``` ### Trigger @@ -291,9 +294,16 @@ Both updaters run automatically from `release-shared.yml`'s `publish-homebrew` a - `beta` → `--name supabase-beta` (a separate formula / manifest for the prerelease channel) - `alpha` → skipped (Homebrew + Scoop are not part of the v3 alpha story; npm only) +### Post-publish: install-channel verification + +Once the channels are live, two reusable workflows run automatically (last in `release-shared.yml`, non-gating — by the time they run the artifacts are already published, so a failure surfaces as a red post-release signal rather than blocking distribution): + +- `[setup-cli-smoke-test.yml](../../../.github/workflows/setup-cli-smoke-test.yml)` (`setup-cli-smoke` job) — installs the released version through `supabase/setup-cli` (the GitHub Release download path) on Linux, macOS, Windows, and Alpine. +- `[verify-install-channels.yml](../../../.github/workflows/verify-install-channels.yml)` (`verify-install-channels` job) — runs a **real** `brew install`, `scoop install`, and `curl|bash` install-script install against the just-published Homebrew tap, Scoop bucket, and GitHub Release, then asserts `supabase --version` matches. brew, scoop, and the install script each verify the published `sha256`/`hash` against the downloaded tarball, so this is the signal that would have caught CLI v2.107.0 (where the brew/scoop manifests shipped checksums that did not match the release tarballs and every `brew install` / `scoop install` failed). It only runs for `beta`/`stable` (the channels that publish brew/scoop) and can be dispatched manually against any already-published version via the Actions tab. + ### Verification -After `release-shared.yml` finishes (all jobs including `publish-homebrew` and `publish-scoop`): +The `verify-install-channels` workflow above automates the manual checks below for the brew/scoop/install-script channels; the steps remain useful for a manual sanity check or for the npm/provenance bits the workflow does not cover. After `release-shared.yml` finishes (all jobs including `publish-homebrew` and `publish-scoop`): ```sh npm view supabase@0.1.0 dist-tags # expect: latest: 0.1.0 (or beta: 0.1.0-beta.N for beta channel) From eba1ca4fee2e8b4e2d21aaf3d0813e3f47568e8e Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 18 Jun 2026 07:44:22 +0000 Subject: [PATCH 2/6] ci: strengthen install-channel verification Address review feedback on the post-publish verification workflow: - Add a Linux Homebrew leg (matrix over macos-latest + ubuntu-latest) so the formula's on_linux URL/sha256 stanza is exercised, not just on_macos. - Probe the Go sidecar on every leg via `supabase completion bash` (a Go-proxied command). `supabase --version` is served by the Bun wrapper and never spawns supabase-go, so a package that omits/misplaces the sidecar would otherwise pass. `projects list` is natively ported now, so completion bash is the reliable side-effect-free proxied probe. - Verify the published install script (fetched from the release asset) instead of `./install` from the checkout, since users run the published script which can diverge from the release branch. Also refresh release-process.md: the sidecar smoke example referenced the now-native `projects list --help`; replace it with `completion bash`. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01RNp9yTyRoDYJTs5xsWRbAr --- .github/workflows/verify-install-channels.yml | 95 ++++++++++++++++--- apps/cli/docs/release-process.md | 6 +- 2 files changed, 86 insertions(+), 15 deletions(-) diff --git a/.github/workflows/verify-install-channels.yml b/.github/workflows/verify-install-channels.yml index a6eb2030ea..66a7f2f1de 100644 --- a/.github/workflows/verify-install-channels.yml +++ b/.github/workflows/verify-install-channels.yml @@ -15,6 +15,11 @@ name: Verify Install Channels # 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: @@ -53,8 +58,18 @@ permissions: jobs: homebrew: - name: Homebrew (${{ inputs.brew_name }}) - runs-on: macos-latest + # 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 }} env: VERSION: ${{ inputs.version }} BREW_NAME: ${{ inputs.brew_name }} @@ -86,6 +101,23 @@ jobs: 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 }}) @@ -123,6 +155,24 @@ jobs: 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 }}) @@ -136,26 +186,47 @@ jobs: env: VERSION: ${{ inputs.version }} steps: - - name: Checkout - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - persist-credentials: false - - name: Install via install script + - name: Install via the published install script shell: bash run: | set -euo pipefail - # The install script downloads the GitHub Release tarball plus - # checksums.txt and aborts on a sha256 mismatch (verify_checksum). - # --no-modify-path keeps it from editing the runner's shell rc files. - ./install --version "${VERSION#v}" --no-modify-path + 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="$("$HOME/.supabase/bin/supabase" --version | tr -d '\r' | head -n1)" + 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" diff --git a/apps/cli/docs/release-process.md b/apps/cli/docs/release-process.md index 81a92dc389..7b2e985dc1 100644 --- a/apps/cli/docs/release-process.md +++ b/apps/cli/docs/release-process.md @@ -183,10 +183,10 @@ Validated on Windows x64 (`v0.0.1`, 2026-04-21): installed with no SmartScreen b Beyond `--version` and `brew test`, exercise a Phase-0 proxied subcommand that requires the `supabase-go` sidecar (`--shell legacy` only): ```sh -supabase projects list --help +supabase completion bash ``` -This must spawn the colocated `supabase-go` and print help text — not return `NotFound: ChildProcess.spawn (supabase ...)`. If it fails, the Homebrew install step is wrong: check that `[apps/cli/scripts/update-homebrew.ts](../scripts/update-homebrew.ts)`'s install-lines block ran `bin.install "supabase-go" if File.exist?("supabase-go")`, and that the built archive actually contains `supabase-go` (it should, for any `--shell legacy` build). +This must spawn the colocated `supabase-go` and print the generated completion script — not return `NotFound: ChildProcess.spawn (supabase ...)`. (`supabase --version` is served by the Bun wrapper and never touches the sidecar, so it is not a sufficient check on its own.) If it fails, the Homebrew install step is wrong: check that `[apps/cli/scripts/update-homebrew.ts](../scripts/update-homebrew.ts)`'s install-lines block ran `bin.install "supabase-go" if File.exist?("supabase-go")`, and that the built archive actually contains `supabase-go` (it should, for any `--shell legacy` build). ### Local-artifact testing (no GitHub Release upload) @@ -299,7 +299,7 @@ Both updaters run automatically from `release-shared.yml`'s `publish-homebrew` a Once the channels are live, two reusable workflows run automatically (last in `release-shared.yml`, non-gating — by the time they run the artifacts are already published, so a failure surfaces as a red post-release signal rather than blocking distribution): - `[setup-cli-smoke-test.yml](../../../.github/workflows/setup-cli-smoke-test.yml)` (`setup-cli-smoke` job) — installs the released version through `supabase/setup-cli` (the GitHub Release download path) on Linux, macOS, Windows, and Alpine. -- `[verify-install-channels.yml](../../../.github/workflows/verify-install-channels.yml)` (`verify-install-channels` job) — runs a **real** `brew install`, `scoop install`, and `curl|bash` install-script install against the just-published Homebrew tap, Scoop bucket, and GitHub Release, then asserts `supabase --version` matches. brew, scoop, and the install script each verify the published `sha256`/`hash` against the downloaded tarball, so this is the signal that would have caught CLI v2.107.0 (where the brew/scoop manifests shipped checksums that did not match the release tarballs and every `brew install` / `scoop install` failed). It only runs for `beta`/`stable` (the channels that publish brew/scoop) and can be dispatched manually against any already-published version via the Actions tab. +- `[verify-install-channels.yml](../../../.github/workflows/verify-install-channels.yml)` (`verify-install-channels` job) — runs a **real** `brew install` (macOS **and** Linux, so both the `on_macos` and `on_linux` stanzas of the formula are exercised), `scoop install`, and `curl|bash` install of the **published** install script (fetched from the release asset, not the repo checkout) against the just-published Homebrew tap, Scoop bucket, and GitHub Release. Each leg then asserts `supabase --version` matches and runs `supabase completion bash` (a Go-proxied command) so a package that omits or misplaces the `supabase-go` sidecar fails too. brew, scoop, and the install script each verify the published `sha256`/`hash` against the downloaded tarball, so this is the signal that would have caught CLI v2.107.0 (where the brew/scoop manifests shipped checksums that did not match the release tarballs and every `brew install` / `scoop install` failed). It only runs for `beta`/`stable` (the channels that publish brew/scoop) and can be dispatched manually against any already-published version via the Actions tab. ### Verification From 206e68b60499a25beb5ca254b447f91aa6c937ba Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 18 Jun 2026 08:18:01 +0000 Subject: [PATCH 3/6] test: temporarily run verify-install-channels on the PR Validate the new reusable workflow end-to-end against published v2.107.0 before merging. Removed before merge. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01RNp9yTyRoDYJTs5xsWRbAr --- .../verify-install-channels-pr-check.yml | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/verify-install-channels-pr-check.yml diff --git a/.github/workflows/verify-install-channels-pr-check.yml b/.github/workflows/verify-install-channels-pr-check.yml new file mode 100644 index 0000000000..02920ab8a2 --- /dev/null +++ b/.github/workflows/verify-install-channels-pr-check.yml @@ -0,0 +1,27 @@ +name: TEMP Verify Install Channels (PR validation) + +# TEMPORARY — DELETE BEFORE MERGE. +# +# Validates .github/workflows/verify-install-channels.yml on this PR before it +# lands on develop. `workflow_dispatch` cannot target a non-default branch, so +# the new reusable workflow can't be run by hand from this branch; this caller +# runs on `pull_request` instead and exercises every leg against an already +# published stable release (v2.107.0 — the release whose brew/scoop checksums +# this PR exists to guard, since corrected by homebrew-tap#820 / scoop-bucket#819). +# +# Once the run is green, this file is removed in the same PR. + +on: + pull_request: + branches: [develop] + +permissions: + contents: read + +jobs: + test: + uses: ./.github/workflows/verify-install-channels.yml + with: + version: "2.107.0" + brew_name: supabase + scoop_name: supabase From e12b81714db50911b8e12bfdaa24043c284185fd Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 18 Jun 2026 08:19:36 +0000 Subject: [PATCH 4/6] ci: put Homebrew on PATH for the Linux verify leg GitHub's Ubuntu runners ship Homebrew preinstalled but it is not on PATH in the non-login shells used by `run:` steps, so `brew install` failed with exit 127 on the Linux leg. Add a Linux-only step that sources `brew shellenv` and appends the prefix to $GITHUB_PATH. Caught by the temporary PR validation run against published v2.107.0. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01RNp9yTyRoDYJTs5xsWRbAr --- .github/workflows/verify-install-channels.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/verify-install-channels.yml b/.github/workflows/verify-install-channels.yml index 66a7f2f1de..1d3a02bd08 100644 --- a/.github/workflows/verify-install-channels.yml +++ b/.github/workflows/verify-install-channels.yml @@ -80,6 +80,16 @@ jobs: HOMEBREW_NO_INSTALL_FROM_API: "1" 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 From e9f1e335ae612b42282c15a3e4ac987c1c419eb3 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 18 Jun 2026 08:24:10 +0000 Subject: [PATCH 5/6] ci: drop HOMEBREW_NO_INSTALL_FROM_API from verify legs The flag forces a large, slow local checkout of homebrew/core on Linux runners, which made the Linux Homebrew leg hang for 10+ minutes (macOS runners have core pre-checked-out, so they were unaffected). It is also unnecessary: `brew install //` always reads a third-party tap from its git HEAD; the API only caches homebrew/core and cask. Caught by the temporary PR validation run. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01RNp9yTyRoDYJTs5xsWRbAr --- .github/workflows/verify-install-channels.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/verify-install-channels.yml b/.github/workflows/verify-install-channels.yml index 1d3a02bd08..9847fbfedd 100644 --- a/.github/workflows/verify-install-channels.yml +++ b/.github/workflows/verify-install-channels.yml @@ -73,11 +73,14 @@ jobs: env: VERSION: ${{ inputs.version }} BREW_NAME: ${{ inputs.brew_name }} - # Skip the formulae.brew.sh API and read the tap straight from its git - # HEAD, so a formula pushed seconds ago is picked up immediately. Auto - # update is disabled because the explicit tap clone already fetches HEAD - # and updating homebrew/core here only adds latency and flake. - HOMEBREW_NO_INSTALL_FROM_API: "1" + # Don't auto-update Homebrew itself before installing; `brew install + # //` 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 From f1f716343038641e4d6ad6b1e5d3a730327b6362 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 18 Jun 2026 08:27:07 +0000 Subject: [PATCH 6/6] test: remove temporary verify-install-channels PR validation The reusable workflow was validated end-to-end against published v2.107.0 (Homebrew macOS+Linux, Scoop, and the install script, all green including the sidecar probe). Drop the temporary caller now that it has served its purpose. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01RNp9yTyRoDYJTs5xsWRbAr --- .../verify-install-channels-pr-check.yml | 27 ------------------- 1 file changed, 27 deletions(-) delete mode 100644 .github/workflows/verify-install-channels-pr-check.yml diff --git a/.github/workflows/verify-install-channels-pr-check.yml b/.github/workflows/verify-install-channels-pr-check.yml deleted file mode 100644 index 02920ab8a2..0000000000 --- a/.github/workflows/verify-install-channels-pr-check.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: TEMP Verify Install Channels (PR validation) - -# TEMPORARY — DELETE BEFORE MERGE. -# -# Validates .github/workflows/verify-install-channels.yml on this PR before it -# lands on develop. `workflow_dispatch` cannot target a non-default branch, so -# the new reusable workflow can't be run by hand from this branch; this caller -# runs on `pull_request` instead and exercises every leg against an already -# published stable release (v2.107.0 — the release whose brew/scoop checksums -# this PR exists to guard, since corrected by homebrew-tap#820 / scoop-bucket#819). -# -# Once the run is green, this file is removed in the same PR. - -on: - pull_request: - branches: [develop] - -permissions: - contents: read - -jobs: - test: - uses: ./.github/workflows/verify-install-channels.yml - with: - version: "2.107.0" - brew_name: supabase - scoop_name: supabase