Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions .github/workflows/publish_npm.yml
Original file line number Diff line number Diff line change
@@ -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<version>.
#
# 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]
Expand All @@ -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

Expand Down Expand Up @@ -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 }}
2 changes: 1 addition & 1 deletion apps/docs/content/docs/development.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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<version>`, for example `v0.0.2`. The workflow fails if the tag and the package version disagree.
Expand Down
9 changes: 6 additions & 3 deletions docs/ci-runners.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
# 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]
```

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

Expand All @@ -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

Expand Down Expand Up @@ -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.