name: release # A release is a PR, then a tag (cast#96, the flow shared with box#83): # the `release: X.Y.Z` PR bumps package.json and stamps the CHANGELOG's # Unreleased section; merging and pushing the bare `X.Y.Z` tag lands here. # This workflow is where cast differs from its siblings: box/rig are pure # bash, so the source tarball IS the package — cast compiles, so the build # happens ONCE, here, and the release carries a prebuilt `cast-X.Y.Z.tgz` # the installer can drop in without npm ci or tsc on the operator's machine. on: push: # Bare X.Y.Z tags (the family scheme — box's 0.6.0 set the precedent, # no `v` prefix). The glob is loose; the assert step below is the gate. tags: ["[0-9]*.*.*"] permissions: contents: write jobs: release: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: "22" cache: npm - name: assert tag == package.json version # Fail loudly, create nothing: a tag that contradicts package.json # would mint a release whose `cast --version` disagrees with its # own name. The mismatch is a ritual error — retag, don't patch. run: | version="$(node -p 'require("./package.json").version')" if [ "$GITHUB_REF_NAME" != "$version" ]; then echo "tag '$GITHUB_REF_NAME' != package.json version '$version' — refusing to release" >&2 exit 1 fi - name: extract the release notes from CHANGELOG.md # The release body is the curated section we wrote, never the # auto-generated PR list. Missing/empty section fails the release — # before the tag has minted anything. run: bash scripts/changelog-section.sh "$GITHUB_REF_NAME" CHANGELOG.md > /tmp/release-notes.md - name: build the package, once run: | npm ci npm run check npm run build npm test - name: assemble cast-${{ github.ref_name }}.tgz # The runnable tree and nothing else: bin/, dist/, production # node_modules/, package.json. Pruned AFTER the tests so what ships # is the tree that passed. Top-level dir named like a GitHub # archive's, so the installer handles both shapes identically. run: | npm prune --omit=dev stage="$(mktemp -d)/cast-$GITHUB_REF_NAME" mkdir -p "$stage" cp -R bin dist node_modules package.json "$stage/" tar -C "$(dirname "$stage")" -czf "cast-$GITHUB_REF_NAME.tgz" "cast-$GITHUB_REF_NAME" tar -tzf "cast-$GITHUB_REF_NAME.tgz" | head -5 - name: create the GitHub release env: GH_TOKEN: ${{ github.token }} run: | gh release create "$GITHUB_REF_NAME" "cast-$GITHUB_REF_NAME.tgz" \ --verify-tag \ --title "cast $GITHUB_REF_NAME" \ --notes-file /tmp/release-notes.md