diff --git a/.github/instructions/workflows.instructions.md b/.github/instructions/workflows.instructions.md index 4b0a9d0b..cd4be3ad 100644 --- a/.github/instructions/workflows.instructions.md +++ b/.github/instructions/workflows.instructions.md @@ -2,6 +2,42 @@ applyTo: ".github/workflows/**" --- +# npm Publishing via OIDC (Trusted Publishing) + +This repository publishes the CLI package to npm using GitHub Actions OIDC trusted publishing — no `NPM_TOKEN` secret is required. + +## Required setup + +1. **Job permission:** `id-token: write` must be set on the publish job. +2. **setup-node:** Use `registry-url: 'https://registry.npmjs.org'` so npm is configured for the registry. +3. **Publish command:** Always include `--provenance` so npm exchanges the OIDC token automatically: + +```yaml +- name: Publish to npm + run: npm publish --provenance --access public +``` + +## Common mistake to avoid + +Do **not** set `NODE_AUTH_TOKEN` to an empty string: + +```yaml +# ❌ WRONG — explicitly clears the token and causes ENEEDAUTH +run: NODE_AUTH_TOKEN="" npm publish + +# ❌ ALSO WRONG — requires a secret that isn't needed +run: npm publish +env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + +# ✅ CORRECT — OIDC token is exchanged automatically via --provenance +run: npm publish --provenance --access public +``` + +Setting `NODE_AUTH_TOKEN=""` overrides the auth that `setup-node` configures and causes `ENEEDAUTH` failures even though `id-token: write` is set. + +--- + # Workflow Security: Validating Untrusted User Input ## Overview diff --git a/.github/workflows/cli-publish.yml b/.github/workflows/cli-publish.yml index 20f2ef6c..4c5b8175 100644 --- a/.github/workflows/cli-publish.yml +++ b/.github/workflows/cli-publish.yml @@ -125,11 +125,11 @@ jobs: - name: Publish to npm if: ${{ !inputs.dry_run && steps.check_published.outputs.already_published != 'true' }} - run: NODE_AUTH_TOKEN="" npm publish + run: npm publish --provenance --access public - name: Dry run publish if: ${{ inputs.dry_run }} - run: NODE_AUTH_TOKEN="" npm publish public --dry-run + run: npm publish --provenance --access public --dry-run - name: Commit version bump and create PR if: ${{ !inputs.dry_run && steps.check_published.outputs.already_published != 'true' && steps.trigger_type.outputs.is_tag != 'true' }}