From ad80fa144c1223149d37ef05e5470ba5d2702f0e Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 18 Oct 2026 17:35:12 +0000 Subject: [PATCH] ci: run npm publish on self-hosted Mac minis Move the last GitHub-hosted job onto the JWS Mac mini fleet ([self-hosted, macOS, ARM64]). npm trusted publishing does not support self-hosted runners, so publish now authenticates with NODE_AUTH_TOKEN from the org NPM_TOKEN secret. That drops OIDC trusted publishing and automatic provenance. Version/tag matching, the npm >=11.5.1 CLI check, prepack, and prepublishOnly tests are unchanged. Co-authored-by: Joe Blau --- .github/workflows/publish_npm.yml | 20 ++++++++++++++------ apps/docs/content/docs/development.mdx | 2 +- docs/ci-runners.md | 9 ++++++--- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/.github/workflows/publish_npm.yml b/.github/workflows/publish_npm.yml index 30915d0..a12512d 100644 --- a/.github/workflows/publish_npm.yml +++ b/.github/workflows/publish_npm.yml @@ -1,8 +1,12 @@ name: Publish to npm -# npm trusted publishing requires a GitHub-hosted runner. See docs/ci-runners.md. # Publishing a GitHub release publishes @bloxwap/chart at the version in packages/chart/package.json. # Release flow: bump the version in a PR, merge it, then create a release tagged v. +# +# npm trusted publishing does not support self-hosted runners +# (https://docs.npmjs.com/trusted-publishers/). This job authenticates with the +# NPM_TOKEN secret instead. That drops OIDC trusted publishing and +# automatic provenance. See docs/ci-runners.md. on: release: types: [published] @@ -17,18 +21,22 @@ concurrency: jobs: publish: - runs-on: ubuntu-latest + runs-on: [self-hosted, macOS, ARM64] timeout-minutes: 20 permissions: contents: read - id-token: write + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} steps: + # Job-level env cannot use the runner context; RUNNER_TEMP is set by the runner. + - name: Point TMPDIR at runner temp + run: echo "TMPDIR=$RUNNER_TEMP" >> "$GITHUB_ENV" - uses: actions/checkout@v7 - # npm publishes via OIDC trusted publishing (no token here), which needs npm >= 11.5.1. - uses: actions/setup-node@v7 with: node-version: '24' + registry-url: 'https://registry.npmjs.org' cache: npm cache-dependency-path: package-lock.json @@ -61,12 +69,12 @@ jobs: echo "version=$VERSION" >> "$GITHUB_OUTPUT" echo "value=$TAG" >> "$GITHUB_OUTPUT" - - name: Check npm supports trusted publishing + - name: Check npm CLI run: | npm --version npx --yes semver -r '>=11.5.1' "$(npm --version)" > /dev/null || npm install -g npm@latest # prepack builds and prepublishOnly runs the full test suite before anything is uploaded; - # publishConfig.access is public, and trusted publishing attaches provenance. + # publishConfig.access is public. Token publish does not attach provenance. - name: Publish @bloxwap/chart@${{ steps.tag.outputs.version }} run: npm publish --workspace @bloxwap/chart --tag ${{ steps.tag.outputs.value }} diff --git a/apps/docs/content/docs/development.mdx b/apps/docs/content/docs/development.mdx index 0c2aca9..1fc1e43 100644 --- a/apps/docs/content/docs/development.mdx +++ b/apps/docs/content/docs/development.mdx @@ -60,7 +60,7 @@ The preview server reads the exported base path, so this build opens at `http:// ## Release to npm -Publishing a GitHub release publishes `@bloxwap/chart` from CI (`.github/workflows/publish_npm.yml`) through npm trusted publishing, so no npm token is stored in the repository. +Publishing a GitHub release publishes `@bloxwap/chart` from CI (`.github/workflows/publish_npm.yml`) on the org Mac mini runners. Authentication uses the org `NPM_TOKEN` secret (`NODE_AUTH_TOKEN`). npm trusted publishing and automatic provenance are unavailable on self-hosted runners. 1. In a pull request, bump `version` in `packages/chart/package.json` (and the `version` export in `packages/chart/src/index.ts`), then merge it. A test fails if the two disagree. 2. Create a GitHub release tagged `v`, for example `v0.0.2`. The workflow fails if the tag and the package version disagree. diff --git a/docs/ci-runners.md b/docs/ci-runners.md index 33e7d5c..c58a9b5 100644 --- a/docs/ci-runners.md +++ b/docs/ci-runners.md @@ -1,6 +1,6 @@ # CI runners -Tests, coverage, and documentation jobs target the org Mac mini fleet: +Every GitHub Actions job in this repository runs on self-hosted Apple Silicon Mac minis (runner group JWS): ```yaml runs-on: [self-hosted, macOS, ARM64] @@ -8,7 +8,9 @@ runs-on: [self-hosted, macOS, ARM64] These jobs stay queued until a runner with all three labels is online. Workflows do not call `apt`, `sudo`, or `playwright install --with-deps` (that flag installs Linux packages). Shell used by CI is POSIX / BSD-portable, and Mac jobs write scratch files under `$RUNNER_TEMP` (`TMPDIR` and Playwright's browser path are exported from `$RUNNER_TEMP` in a setup step; GitHub Actions does not allow the `runner` context in job-level `env`). -The npm publish job uses `ubuntu-latest` because [npm trusted publishing requires a GitHub-hosted runner](https://docs.npmjs.com/trusted-publishers/). Self-hosted runners cannot authenticate with the existing tokenless OIDC release flow. +## Trusted publishing is unavailable + +[npm trusted publishing does not support self-hosted runners](https://docs.npmjs.com/trusted-publishers/). The publish job therefore authenticates with a long-lived `NPM_TOKEN` secret (`NODE_AUTH_TOKEN`). That **drops OIDC trusted publishing and automatic provenance**. The org-level `NPM_TOKEN` (publish rights for `@bloxwap` packages) must be shared with this repository. ## Jobs @@ -18,7 +20,7 @@ The npm publish job uses `ubuntu-latest` because [npm trusted publishing require | [`.github/workflows/coverage.yml`](../.github/workflows/coverage.yml) | `coverage` | Mac mini | LCOV report and Codecov upload | | [`.github/workflows/docs.yml`](../.github/workflows/docs.yml) | `build` | Mac mini | Docs export, typecheck, lint, Playwright Chrome checks, Pages artifact | | [`.github/workflows/docs.yml`](../.github/workflows/docs.yml) | `deploy` | Mac mini | `configure-pages` + `deploy-pages` on `main` | -| [`.github/workflows/publish_npm.yml`](../.github/workflows/publish_npm.yml) | `publish` | GitHub-hosted Ubuntu | Version/tag check and `npm publish` of `@bloxwap/chart` | +| [`.github/workflows/publish_npm.yml`](../.github/workflows/publish_npm.yml) | `publish` | Mac mini | Version/tag check and `npm publish` of `@bloxwap/chart` (`NPM_TOKEN`; no provenance) | ## Prerequisites on each Mac mini @@ -57,4 +59,5 @@ Browsers go to `$RUNNER_TEMP/ms-playwright` (`PLAYWRIGHT_BROWSERS_PATH`). There - Give the runner enough free disk for `npm ci`, the Next.js static export, and a Chrome for Testing download. - Headless Chrome on macOS does not need the Accessibility TCC prompt that headed browsers do. +- npm publish (`Publish to npm`) uses the `NPM_TOKEN` secret, not OIDC. GitHub Pages deploy still uses `pages: write` and `id-token: write`. - Fork pull requests on a public repository should stay on GitHub-hosted runners or a dedicated untrusted pool if org policy forbids self-hosted runners on forks. This repo's workflows themselves do not special-case forks.