Skip to content
Merged
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
69 changes: 63 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
# - Creates a GitHub Release with an auto-generated changelog
# - Pushes to the homebrew-tap repo (if HOMEBREW_TAP_TOKEN is set)
# - Pushes to the scoop-bucket repo (if SCOOP_BUCKET_TOKEN is set)
# 4. Publish the nodeup-cli npm wrapper via OIDC Trusted Publishing.
# GitHub Actions exchanges its built-in OIDC token for a one-hour
# publish token scoped to the `nodeup-cli` package. No NPM_TOKEN
# secret, no rotation, no leak surface.
#
# Required secrets (configured per-repo):
# - HOMEBREW_TAP_TOKEN: fine-grained PAT with `contents:write` on
Expand All @@ -18,11 +22,13 @@
# - GITHUB_TOKEN: provided automatically by GitHub Actions, used by
# GoReleaser to create the Release.
#
# Optional secrets:
# - NPM_TOKEN: if set, release.yml will additionally publish the
# `nodeup` npm wrapper. Configure the publish step after the GoReleaser
# step (currently a placeholder; full npm wrapper lives in
# nodeup-npm/ in Phase 7).
# npm publish uses OIDC Trusted Publishing — no secret required. The
# trust is registered on the npmjs.com side at
# https://www.npmjs.com/package/nodeup-cli/access
# under "Trusted Publisher", pointing at this workflow by filename
# (release.yml). If the publish job ever fails with ENEEDAUTH, the
# first thing to check is that the trust entry on npmjs.com still
# matches this workflow's filename, repo name, and GitHub user/org.

name: Release

Expand Down Expand Up @@ -64,4 +70,55 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
SCOOP_BUCKET_TOKEN: ${{ secrets.SCOOP_BUCKET_TOKEN }}
SCOOP_BUCKET_TOKEN: ${{ secrets.SCOOP_BUCKET_TOKEN }}

publish-npm:
name: Publish nodeup-cli to npm (OIDC)
runs-on: ubuntu-latest
needs: goreleaser
# OIDC Trusted Publishing — the trust is registered on the npmjs.com
# side at https://www.npmjs.com/package/nodeup-cli/access under
# "Trusted Publisher", pointing at this workflow by filename. No
# NPM_TOKEN secret is needed; the runner mints an OIDC token,
# npmjs.com exchanges it for a one-hour publish token scoped to
# the nodeup-cli package.
#
# IMPORTANT: OIDC only kicks in when npm sees NO `_authToken` line
# in .npmrc for the target registry. The actions/setup-node action
# writes `//registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN}` to
# .npmrc when given `registry-url`, and an empty-expanded value
# still counts as "auth configured" — npm then tries classic auth
# with empty creds and never initiates the OIDC exchange (issue
# npm/documentation#1960). So we deliberately:
# 1. Don't set `registry-url` on setup-node.
# 2. Don't set NODE_AUTH_TOKEN in the env.
# 3. Write a clean .npmrc with only the registry URL.
if: startsWith(github.ref, 'refs/tags/v')
permissions:
id-token: write # required for OIDC trusted publishing
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node
uses: actions/setup-node@v4
with:
# Node 24 ships npm 11.x, which is the minimum for OIDC
# trusted publishing (npm >= 11.5.1, Node >= 22.14.0).
# Deliberately no `registry-url` here — see the comment on
# the publish-npm job above.
node-version: '24'

# Write a clean .npmrc that contains only the registry URL, no
# _authToken line. Without this, npm won't see the
# ACTIONS_ID_TOKEN_REQUEST_* env vars and won't initiate the
# OIDC token exchange.
- name: Configure registry (clean .npmrc for OIDC)
run: |
mkdir -p ~/.npm
printf 'registry=https://registry.npmjs.org/\n' > ~/.npmrc

- name: Publish nodeup-cli
working-directory: ./nodeup-npm
run: npm publish --access public
Loading