ci: harden installer canary and add pre-merge Bash 3.2 gate
Follow-on to the #558/#568 installer incident and the #569 canary: the canary had no Windows coverage, no alerting, and pre-merge CI had no real Bash 3.2 coverage.
Canary (installer-smoke.yml)
- Push paths now include
scripts/install.ps1— the raw URL serves main, so merge == deploy for the PowerShell installer too. - Windows job runs the README's documented
irm | iexshape under both Windows PowerShell 5.1 (the stock interpreter, exercising install.ps1's 5.1-specific branches) and pwsh 7, in a fail-fast-off matrix. Fetch and execution both happen inside the matrix interpreter (GitHub Actions doesn't evaluate expressions insteps[*].shell, so a pwsh launcher invokes it explicitly). Writes are contained under a scratchUSERPROFILE/BASECAMP_BIN_DIRinRUNNER_TEMP;?sha=cache-busts the raw URL (it varies its cache key on unknown query params). No basecamp.com endpoint exists for install.ps1, so the raw URL is the documented shape. - Notify job: on any leg's failure, files or updates an "Installer canary failure" issue (exact-title dedupe, best-effort
ghcalls,::error::annotation — same idiom as release.yml's skills-sync alert). Skipped entirely on green runs.
Pre-merge (test.yml): installer-bash32
Plain steps on macos-latest, not bats — bats 1.11 execs env bash at every layer, so the interpreter isn't pinnable through it. Asserts /bin/bash is exactly 3.2, syntax-checks install.sh, then runs it piped with curl off PATH and asserts the guard's clean failure message with no unbound-variable errors (the #558 regression class). Path-filtered to scripts/install.sh, e2e/installer.bats, and test.yml itself, so the job proves itself on this PR. Skipped filters still report job success, so it's safe to mark as a required check later (branch-protection change, out of repo).
Verification
Branch dispatches run the branch's workflow file against the published main installer — that validates the Windows matrix and notify mechanics, which is the correct scope for a post-deploy canary (PR-head script changes are covered pre-merge by bats + the new 3.2 gate, and post-merge by the push-triggered canary).
- Green baseline dispatch: all four legs pass, notify skipped — run 30305890057.
- Notify drill: temporarily broken Linux assert → notify filed #574 with per-leg results (closed as drill) — run 30306010077.
- Post-revert dispatch: green again, notify skipped — run 30306162446.
bin/cigreen (actionlint + zizmor included).
The workflow-level BASECAMP_NO_KEYRING stays in place for now: the published v0.7.2 binary probes the keyring eagerly on startup and would hang the macOS leg without it. The follow-up PR (lazy store construction + installer belts) removes it.
Summary by cubic
Hardens the installer canary with Windows coverage and alerting, and adds a pre-merge Bash 3.2 gate with a full offline install to catch regressions early.
-
New Features
- Canary: trigger on
scripts/install.ps1. - Canary: Windows matrix (PowerShell 5.1 and
pwsh7) running the documentedirm | iex, with isolated HOME/bin and?sha=cache-busting. - Canary: notify job files/updates an "Installer canary failure" issue on any leg failure; skipped on green.
- Pre-merge:
installer-bash32(PRs only, path-filtered) onmacos-latest. - Pre-merge: assert
/bin/bashis 3.2,bash -noninstall.sh, piped run fails cleanly withoutcurl(no unbound vars). - Pre-merge: full offline install under Bash 3.2 using a fixture
curland local release + checksums; assert expected output and that the installed stub runs.
- Canary: trigger on
-
Bug Fixes
- Permissions: grant
pull-requests: readsodorny/paths-filtercan enumerate changed files.
- Permissions: grant