ci: run the release pack-and-smoke gate on every PR (#297) #753
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| jobs: | |
| test: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 | |
| # Reads `packageManager` from root package.json (corepack-style pin). | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: 24 | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| - run: pnpm check | |
| - run: pnpm test | |
| - name: Coverage (measure-only, per-directory) | |
| run: pnpm test:coverage | |
| - name: Upload coverage report | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: coverage-report | |
| path: coverage/ | |
| if-no-files-found: error | |
| - name: Changeset presence (warn-only) | |
| if: github.event_name == 'pull_request' | |
| run: | | |
| base="${{ github.event.pull_request.base.sha }}" | |
| subject="$(git log -1 --format=%s)" | |
| if printf '%s' "$subject" | grep -qE '^(chore|ci)(\(|:)'; then | |
| echo "::notice::chore/ci commit — changeset not expected, skipping check." | |
| exit 0 | |
| fi | |
| if git diff --name-only "$base"...HEAD -- '.changeset/*.md' | grep -q .; then | |
| echo "::notice::Changeset present." | |
| else | |
| echo "::warning::No changeset found for this PR. Behavioral/user-facing changes should ship a .changeset/*.md (see .changeset/README.md). chore:/ci: PRs are exempt." | |
| fi | |
| smoke: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: 24 | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| - run: pnpm -r build | |
| - name: Pack and smoke cycling-coach | |
| # Mirrors release.yml's smoke gate: install the packed tarball into a | |
| # fresh consumer and run the bundled binary. Runs on every PR (including | |
| # the Version PR) and on main, so a broken published bundle — e.g. an ESM | |
| # dynamic-require of a Node builtin that only surfaces in the packed | |
| # artifact, not in `pnpm test` — is caught before merge, not at release. | |
| # cycling-coach is the only publishable binary (ADR-0009); extend when | |
| # running-coach / duathlon-coach graduate. | |
| run: | | |
| set -euo pipefail | |
| PACKAGE=cycling-coach | |
| cd "packages/$PACKAGE" | |
| pnpm pack --pack-destination "/tmp/smoke-pack-$PACKAGE" | |
| mkdir -p "/tmp/smoke-consumer-$PACKAGE" | |
| cd "/tmp/smoke-consumer-$PACKAGE" | |
| npm init -y > /dev/null | |
| npm install /tmp/smoke-pack-$PACKAGE/*.tgz | |
| timeout 30 node "node_modules/$PACKAGE/dist/index.js" --help | |
| secrets-macos: | |
| runs-on: macos-latest | |
| env: | |
| CI: macos | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9 | |
| # Reads `packageManager` from root package.json (corepack-style pin). | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: 22 | |
| cache: pnpm | |
| - run: pnpm install --frozen-lockfile | |
| - run: pnpm --filter @enduragent/core exec vitest run tests/secrets |