Skip to content
Open
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
23 changes: 16 additions & 7 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -315,14 +315,15 @@ jobs:

publish-npm:
needs: [release-context, asset-gate]
# Temporarily disable npm publishing by setting repo variable SKIP_NPM=true
# (e.g. while the npm token can't publish — 2FA-bypass granular token not yet
# configured). The job is cleanly SKIPPED (gray), not failed/masked. Clear
# the SKIP_NPM repo variable to re-enable. See RELEASE.md.
# Temporarily disable npm publishing by setting repo variable SKIP_NPM=true.
# The job is cleanly SKIPPED (gray), not failed/masked. Clear the SKIP_NPM
# repo variable to re-enable. Publishing authenticates through npm trusted
# publishing (OIDC), configured per package on npmjs.com. See RELEASE.md.
if: ${{ vars.SKIP_NPM != 'true' }}
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # npm trusted publishing (OIDC), no token secret
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
Expand All @@ -333,6 +334,11 @@ jobs:
node-version: 22
registry-url: https://registry.npmjs.org

# Trusted publishing needs npm 11.5.1 or later; the npm bundled with
# Node 22 is older.
- name: Update npm for trusted publishing
run: npm install -g npm@latest

- name: Download and verify platform release assets
shell: bash
env:
Expand All @@ -352,7 +358,6 @@ jobs:
- name: Idempotent publish (platform packages)
shell: bash
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
VERSION: ${{ needs.release-context.outputs.version }}
run: |
set -euo pipefail
Expand Down Expand Up @@ -405,7 +410,6 @@ jobs:
- name: Idempotent publish (main package)
shell: bash
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
VERSION: ${{ needs.release-context.outputs.version }}
run: |
set -euo pipefail
Expand Down Expand Up @@ -576,6 +580,7 @@ jobs:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write # npm trusted publishing (OIDC), no token secret
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
Expand All @@ -586,6 +591,11 @@ jobs:
node-version: 22
registry-url: https://registry.npmjs.org

# Trusted publishing needs npm 11.5.1 or later; the npm bundled with
# Node 22 is older.
- name: Update npm for trusted publishing
run: npm install -g npm@latest

- name: Build + test
shell: bash
run: |
Expand All @@ -598,7 +608,6 @@ jobs:
- name: Idempotent publish
shell: bash
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
VERSION: ${{ needs.release-context.outputs.version }}
run: |
set -euo pipefail
Expand Down
22 changes: 12 additions & 10 deletions RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,17 @@ The pipeline is idempotent — re-run is safe.

### Temporarily disabling npm publishing

If the npm token can't publish (npm now rejects classic automation tokens with
`403 ... two-factor authentication ... required`), set the repo variable
`SKIP_NPM=true` (`gh variable set SKIP_NPM --body true`). `publish-npm` is then
cleanly **skipped** (gray, not failed) and `verify-publish` records npm as
`skipped` — the release goes green on every other registry. **Re-enable** by
clearing it (`gh variable delete SKIP_NPM`) once `NPM_TOKEN` is a *granular*
access token with publish permission (these bypass 2FA), or after configuring
npm OIDC trusted publishing for each package (the workflow already grants
`id-token: write`).
npm publishing uses **trusted publishing** (OIDC): no token secret, nothing to
rotate. Each package on npmjs.com lists this repository and `release.yml` as its
trusted publisher (package page > Settings > Trusted Publisher > GitHub Actions:
user `us`, repository `crw`, workflow filename `release.yml`, no environment).
The packages are `crw-mcp`, `crw-mcp-darwin-arm64`, `crw-mcp-darwin-x64`,
`crw-mcp-linux-arm64`, `crw-mcp-linux-x64` and `crw-sdk`. A new platform
package needs that entry once before its first release. If npm publishing has
to be paused, set the repo variable `SKIP_NPM=true`
(`gh variable set SKIP_NPM --body true`): `publish-npm` and `publish-npm-sdk` are
then cleanly **skipped** (gray, not failed) and `verify-publish` records npm as
`skipped`. Re-enable with `gh variable delete SKIP_NPM`.

### A version was published with broken metadata (e.g. wrong npm optionalDeps)

Expand All @@ -77,7 +79,7 @@ These tags were cut while the release pipeline silently failed (cargo publish ou
| -------------------- | -------------------------------- | -------------------------------------------- |
| `CARGO_REGISTRY_TOKEN` | `publish-crates` | crates.io account → API tokens → revoke + create new with `publish-update` scope |
| `PYPI_TOKEN` | `publish-pypi` | pypi.org account → API tokens → scoped to project `crw` |
| `NPM_TOKEN` | `publish-npm` | npmjs.com → access tokens → automation token |
| npm (no secret) | `publish-npm`, `publish-npm-sdk` | trusted publishing, configured per package on npmjs.com; nothing to rotate |
| `GH_DISPATCH_PAT` | `dispatch-release`, `update-apt`, `update-homebrew` | GitHub fine-grained PAT with `actions:write` on this repo + `us/apt-crw` + `us/homebrew-crw` |

`GITHUB_TOKEN` is auto-provisioned and does not need rotation.
Expand Down
Loading