The cast half of the flow designed in heavy-duty/box#83, aligned with box#90 and rig#40, plus the piece unique to cast: a prebuilt release asset, because cast is the one repo where the source tarball is not the package. - CHANGELOG.md (box's format) with this PR's entry under Unreleased; feature PRs land their entry as part of the PR. - `cast --version` / `-V` answers with package.json's version, read relative to the compiled module so a source checkout and an installed prebuilt tree agree. - release.yml, on EVERY tag push (no shape filter — a mismatched tag must fail the assert loudly, not be pattern-skipped): asserts tag == package.json version FIRST, extracts that version's changelog section (.github/scripts/release-notes.sh, shared with the tests; missing or empty refuses), builds once (npm ci && npm run build && npm prune --omit=dev), stages bin/ dist/ node_modules/ package.json as cast-X.Y.Z/ and attaches cast-X.Y.Z.tgz to `gh release create --verify-tag`. No tests here — ci.yml gated the merge commit, and the suite needs age. - install.sh grows the three channels: default = the latest release's asset (tag resolved off the releases/latest redirect Location — no API, no token; failure dies loudly naming CAST_REF=main, never a silent fallback), CAST_REF=<tag> = pinned (asset first, source fallback), CAST_REF=main = dev build-from-source. npm is required only on the source path, and a prebuilt tree is sanity-checked (dist/, node_modules/) before $DEST is replaced. - test/release.test.ts drives it all offline: --version, the extraction against fixtures (0.7.0 never matches 0.7.0-rc1) and the real changelog, and REAL install.sh runs through all three channels with a stub curl and a poisoned npm — including the loud no-releases refusal with no $DEST side effects. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
60 lines
2.2 KiB
YAML
60 lines
2.2 KiB
YAML
name: ci
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
|
|
jobs:
|
|
build:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: "22"
|
|
cache: npm
|
|
# the secrets tests round-trip a real age identity
|
|
- run: sudo apt-get update && sudo apt-get install -y age
|
|
- run: npm ci
|
|
- run: npm run check
|
|
- run: npm run build
|
|
- run: npm test
|
|
- name: installer is valid bash
|
|
run: bash -n install.sh bin/cast scripts/*.sh .github/scripts/*.sh
|
|
- name: labels state-machine tests
|
|
run: bash test/labels-reconcile.sh
|
|
|
|
# The installer, proven by RUNNING it — CAST_INSTALL_SOURCE points it at
|
|
# this checkout, so CI proves the installer under review (the versioned
|
|
# layout, the current symlink, the PATH chain, the uninstall's absence
|
|
# assert), not a hand-built imitation of it. Box's CI installs box the
|
|
# same way. This is the one place the real npm ci + tsc build path runs
|
|
# end to end; the vitest installer tests cover the layout semantics
|
|
# offline with a shimmed npm.
|
|
install:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: "22"
|
|
cache: npm
|
|
- name: install via install.sh, from this checkout
|
|
run: |
|
|
CAST_NO_MODIFY_PATH=1 CAST_INSTALL_SOURCE="$GITHUB_WORKSPACE" bash install.sh
|
|
# assert what landed: the layout, the chain, and that it answers
|
|
readlink -f "$HOME/.local/bin/cast" | grep '/versions/'
|
|
"$HOME/.local/bin/cast" --version
|
|
"$HOME/.local/bin/cast" versions
|
|
- name: converging no-op — a re-run changes nothing and builds nothing
|
|
run: |
|
|
CAST_NO_MODIFY_PATH=1 CAST_INSTALL_SOURCE="$GITHUB_WORKSPACE" bash install.sh \
|
|
| tee /tmp/rerun.log
|
|
grep -q 'already installed' /tmp/rerun.log
|
|
- name: uninstall --all — ends with the absence assert
|
|
run: |
|
|
CAST_YES=1 "$HOME/.local/bin/cast" uninstall --all
|
|
test ! -e "$HOME/.local/share/cast"
|
|
test ! -e "$HOME/.local/bin/cast"
|
|
test ! -L "$HOME/.local/bin/cast"
|