@gerdloos/npm-trusts-github-skill 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish.yml +22 -0
- package/README.md +15 -0
- package/package.json +10 -0
- package/skills/npm-trusts-github/SKILL.md +65 -0
- package/skills/npm-trusts-github/defaults.json +17 -0
- package/skills/npm-trusts-github/references/example-hello.md +78 -0
- package/skills/npm-trusts-github/references/publish.yml +22 -0
- package/skills/npm-trusts-github/references/quick-start.md +102 -0
- package/skills/npm-trusts-github/references/setup-guide.md +137 -0
- package/skills/npm-trusts-github/references/troubleshooting.md +109 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: Publish to npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
id-token: write
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
publish:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-node@v4
|
|
18
|
+
with:
|
|
19
|
+
node-version: '22'
|
|
20
|
+
registry-url: 'https://registry.npmjs.org'
|
|
21
|
+
- run: npm install -g npm@latest
|
|
22
|
+
- run: npm publish --access public
|
package/README.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# setup-npm-trusts-github-skill
|
|
2
|
+
|
|
3
|
+
A skill that teaches an LLM how to set up npm trusted publishing (OIDC) with GitHub Actions.
|
|
4
|
+
|
|
5
|
+
## Install on Pi
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pi install npm:@gerdloos/npm-trusts-github-skill
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
In Pi: `/skill:npm-trusts-github`
|
|
14
|
+
|
|
15
|
+
The agent will guide you through setting up automated npm publishing — no tokens, no 2FA prompts, just git tags → GitHub Actions → npm.
|
package/package.json
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gerdloos/npm-trusts-github-skill",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A skill that teaches an LLM how to set up npm trusted publishing with GitHub Actions",
|
|
5
|
+
"keywords": ["pi-package", "npm", "publish", "workflow"],
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"pi": {
|
|
8
|
+
"skills": ["./skills"]
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: npm-trusts-github
|
|
3
|
+
description: >
|
|
4
|
+
Set up npm trusted publishing (OIDC) with GitHub Actions — no tokens, no 2FA
|
|
5
|
+
prompts. Teaches the agent how to create package.json, write publish.yml,
|
|
6
|
+
configure trusted publisher on npmjs.com, wire git-tag-driven releases, and
|
|
7
|
+
troubleshoot common failures. Trigger when a user asks to publish an npm
|
|
8
|
+
package automatically from GitHub, set up CI/CD for npm, use OIDC to avoid
|
|
9
|
+
npm tokens, or wire a GitHub repo to auto-publish on every git tag.
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# npm trusts GitHub — Trusted Publishing Setup
|
|
13
|
+
|
|
14
|
+
Wires a GitHub repo to auto-publish to npm on every git tag via OIDC trusted
|
|
15
|
+
publishing. No long-lived tokens, no 2FA prompts, no manual rotation.
|
|
16
|
+
|
|
17
|
+
## Before starting
|
|
18
|
+
|
|
19
|
+
Read `defaults.json` in this skill directory. It contains the user's preferred
|
|
20
|
+
npm scope, npm org, and GitHub account. If a field is empty or contains a
|
|
21
|
+
placeholder (`<Fill default here ... or leave empty>`), ask the user for that
|
|
22
|
+
value. The user can edit `defaults.json` at any time.
|
|
23
|
+
|
|
24
|
+
- **npmScope**: your npm username with `@` (e.g. `@alice`). Scope and org are
|
|
25
|
+
alternatives — fill one, leave the other empty. If both are empty, packages
|
|
26
|
+
are unscoped.
|
|
27
|
+
- **npmOrg**: an optional npm organization name (e.g. `mycompany`). Creates
|
|
28
|
+
packages under `@mycompany/` instead of `@yourname/`.
|
|
29
|
+
- **githubAccount**: your GitHub username for repo URLs and trusted publisher.
|
|
30
|
+
|
|
31
|
+
Prefer values the user provides in conversation over the config file.
|
|
32
|
+
|
|
33
|
+
## Reference documents
|
|
34
|
+
|
|
35
|
+
All in `references/` relative to this SKILL.md. Load on demand.
|
|
36
|
+
|
|
37
|
+
| File | When to load |
|
|
38
|
+
|---|---|
|
|
39
|
+
| `references/quick-start.md` | User wants the full step-by-step with placeholders filled in |
|
|
40
|
+
| `references/publish.yml` | User needs the GitHub Actions workflow template |
|
|
41
|
+
| `references/setup-guide.md` | User needs detailed explanations of each step |
|
|
42
|
+
| `references/troubleshooting.md` | User hits an error |
|
|
43
|
+
| `references/example-hello.md` | User wants a worked example (the hello-world package) |
|
|
44
|
+
|
|
45
|
+
## Core concept
|
|
46
|
+
|
|
47
|
+
The pipeline:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
git push --follow-tags → GitHub Action detects v* tag → npm publish via OIDC
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
No npm login, no token secrets, no 2FA codes. The GitHub Action exchanges a
|
|
54
|
+
short-lived OIDC identity token for publish rights. Provenance is signed
|
|
55
|
+
automatically.
|
|
56
|
+
|
|
57
|
+
## Troubleshooting quick reference
|
|
58
|
+
|
|
59
|
+
| Error | Cause | Fix |
|
|
60
|
+
|---|---|---|
|
|
61
|
+
| `ENEEDAUTH` | npm too old (< 11.5.1) | `npm install -g npm@latest` in workflow |
|
|
62
|
+
| `E404` | Trusted publisher config typo OR package never manually published | Re-check fields on npmjs.com; do one manual publish |
|
|
63
|
+
| `EOTP` | Token-based path is being used instead of OIDC | Remove `NODE_AUTH_TOKEN` and `--provenance` |
|
|
64
|
+
|
|
65
|
+
Full guide: `references/troubleshooting.md`.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "==========================================================\n DEFAULTS CONFIG — setup-npm-publish skill\n Fill in your values below. Leave a field empty (empty string)\n or keep its placeholder, and the LLM will ask you for it\n when needed.\n==========================================================",
|
|
3
|
+
|
|
4
|
+
"npmScope": "<Fill default here like @your-username or leave empty>",
|
|
5
|
+
|
|
6
|
+
"_npmScope_explanation": "Your npm scope is just the @account part — not the full\n package name. Example: in @alice/utils, the scope is @alice,\n and 'utils' is the project name (chosen at npm init time).\n Every npm account automatically gets a scope matching its\n username.\n\n When you publish with a scope, your package name only needs\n to be unique within that scope — @alice/utils and @bob/utils\n can both exist without conflict.\n\n If you also fill in npmOrg, leave this empty. The org name\n becomes the scope instead.\n\n If both are empty, packages are unscoped (global namespace,\n e.g. 'utils' instead of '@alice/utils'). Unscoped names\n must be globally unique — first come, first served.\n\n Fill in like: @your-username",
|
|
7
|
+
|
|
8
|
+
"_scopeOrOrg_note": "npmScope and npmOrg are alternatives, not layers. If you fill in npmOrg, leave npmScope empty (and vice versa). The org name becomes the scope. If both are empty, packages are unscoped (global namespace).",
|
|
9
|
+
|
|
10
|
+
"npmOrg": "<Fill default here like org-name without @ or leave empty>",
|
|
11
|
+
|
|
12
|
+
"_npmOrg_explanation": "An npm organization is a shared namespace you create at\n npmjs.com/org/create. It's free. The org gets its own scope\n (e.g. @mycompany). Multiple people can publish under it.\n\n This field is OPTIONAL. Leave empty if you don't have an org\n or don't want to publish under one.\n\n When to use an org:\n - You want packages under @mycompany/ instead of @yourname/\n - Multiple maintainers need publish access\n - You want organizational branding separate from your\n personal account\n\n If you set this, the LLM uses @<npmOrg>/ as the scope\n instead of your personal scope. Your personal account must\n own or be a member of the org.\n\n Fill in like: mycompany (no @ prefix — just the name)",
|
|
13
|
+
|
|
14
|
+
"githubAccount": "<Fill default here like account-name or leave empty>",
|
|
15
|
+
|
|
16
|
+
"_githubAccount_explanation": "Your GitHub username. Used for:\n - Repo URLs: git@github.com:<account>/<repo>.git\n - Trusted publisher config on npmjs.com\n\n Fill in like: alice"
|
|
17
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Worked Example — @gerdloos/pi-skill-hello
|
|
2
|
+
|
|
3
|
+
This is the real package that this skill's setup was battle-tested against.
|
|
4
|
+
Follow this walkthrough to see the full flow in action.
|
|
5
|
+
|
|
6
|
+
## Final state
|
|
7
|
+
|
|
8
|
+
| Piece | Value |
|
|
9
|
+
|---|---|
|
|
10
|
+
| npm package | `@gerdloos/pi-skill-hello` ([view](https://www.npmjs.com/package/@gerdloos/pi-skill-hello)) |
|
|
11
|
+
| GitHub repo | `<github-account>/pi-skill-hello` (private) |
|
|
12
|
+
| Workflow | `.github/workflows/publish.yml` |
|
|
13
|
+
| Trusted publisher | Configured on npm package settings |
|
|
14
|
+
| npm org (available) | `<org-name>` under your npm account |
|
|
15
|
+
|
|
16
|
+
## Package contents
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
pi-skill-hello/
|
|
20
|
+
├── package.json # name: @gerdloos/pi-skill-hello
|
|
21
|
+
├── README.md
|
|
22
|
+
├── .github/workflows/
|
|
23
|
+
│ └── publish.yml # triggers on v* tags, id-token: write
|
|
24
|
+
├── skills/
|
|
25
|
+
│ └── hello/
|
|
26
|
+
│ ├── SKILL.md # Agent Skills spec — says "Hello npm! 🎉"
|
|
27
|
+
│ └── scripts/
|
|
28
|
+
│ └── hello.sh
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Errors we hit and how we fixed them
|
|
32
|
+
|
|
33
|
+
### 1. `EOTP` — one-time password required
|
|
34
|
+
**When:** First attempt with a "Publish" type granular token.
|
|
35
|
+
**Why:** The token required 2FA for every publish. GitHub Actions can't enter OTPs.
|
|
36
|
+
**Fix:** Switched to trusted publishing (OIDC). Deleted the token entirely.
|
|
37
|
+
|
|
38
|
+
### 2. `E404` — package not in registry (after trusted publisher config)
|
|
39
|
+
**When:** After configuring the trusted publisher on npmjs.com.
|
|
40
|
+
**Why:** Had `--provenance` flag and `NODE_AUTH_TOKEN` in the workflow.
|
|
41
|
+
These triggered the old token-based code path, which overrode the OIDC flow.
|
|
42
|
+
**Fix:** Removed `--provenance` flag and `NODE_AUTH_TOKEN` env var.
|
|
43
|
+
|
|
44
|
+
### 3. `ENEEDAUTH` — need auth
|
|
45
|
+
**When:** After removing token and flags.
|
|
46
|
+
**Why:** npm version on the runner was too old (< 11.5.1). OIDC wasn't recognized.
|
|
47
|
+
**Fix:** Added `npm install -g npm@latest` step before `npm publish`.
|
|
48
|
+
|
|
49
|
+
### 4. `E404` again — trusted publisher mismatch
|
|
50
|
+
**When:** After all workflow fixes.
|
|
51
|
+
**Why:** The `registry-url` in `setup-node` was creating an `.npmrc` with an
|
|
52
|
+
empty `_authToken` line, which blocked the OIDC flow.
|
|
53
|
+
**Fix:** Moved to passing `--registry https://registry.npmjs.org` in the
|
|
54
|
+
publish command instead of relying on `setup-node`'s `registry-url`.
|
|
55
|
+
(Later re-added `registry-url` once we understood that the issue was npm version,
|
|
56
|
+
not the registry config.)
|
|
57
|
+
|
|
58
|
+
### 5. Final working state
|
|
59
|
+
- `registry-url` in setup-node (creates registry config)
|
|
60
|
+
- No `NODE_AUTH_TOKEN` env var (OIDC handles auth)
|
|
61
|
+
- No `--provenance` flag (automatic with trusted publishing)
|
|
62
|
+
- `npm install -g npm@latest` (ensures npm ≥ 11.5.1)
|
|
63
|
+
- `id-token: write` at root permissions level
|
|
64
|
+
- Bare `npm publish --access public`
|
|
65
|
+
|
|
66
|
+
## The exact publish.yml that works
|
|
67
|
+
|
|
68
|
+
See `references/publish.yml` in this skill directory.
|
|
69
|
+
|
|
70
|
+
## How to replicate for your own project
|
|
71
|
+
|
|
72
|
+
1. Copy the `publish.yml` into your project
|
|
73
|
+
2. Replace `@gerdloos` with your scope in `package.json`
|
|
74
|
+
3. Create the GitHub repo, push code
|
|
75
|
+
4. Manually publish once: `npm login && npm publish --access public`
|
|
76
|
+
5. Configure trusted publisher on npmjs.com
|
|
77
|
+
6. `npm version patch && git push --follow-tags`
|
|
78
|
+
7. Watch `github.com/your-username/your-repo/actions`
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: Publish to npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
id-token: write
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
publish:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-node@v4
|
|
18
|
+
with:
|
|
19
|
+
node-version: '22'
|
|
20
|
+
registry-url: 'https://registry.npmjs.org'
|
|
21
|
+
- run: npm install -g npm@latest
|
|
22
|
+
- run: npm publish --access public
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Quick Start
|
|
2
|
+
|
|
3
|
+
Follow these steps to wire up your first package. Replace `<npmScope>`,
|
|
4
|
+
`<githubAccount>`, and `<my-pkg>` with values from `defaults.json` or user
|
|
5
|
+
answers.
|
|
6
|
+
|
|
7
|
+
## 1. Create the package
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
mkdir <my-pkg> && cd <my-pkg>
|
|
11
|
+
npm init --scope=<npmScope>
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## 2. Write code
|
|
15
|
+
|
|
16
|
+
Add your source files. Create a README.
|
|
17
|
+
|
|
18
|
+
## 3. Add the GitHub Actions workflow
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
mkdir -p .github/workflows
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Copy the workflow template from `references/publish.yml` into
|
|
25
|
+
`.github/workflows/publish.yml`. The template is ready to use — it includes
|
|
26
|
+
the correct permissions, npm upgrade step, and bare publish command.
|
|
27
|
+
|
|
28
|
+
## 4. Commit and push to GitHub
|
|
29
|
+
|
|
30
|
+
Create a repo on GitHub (public or private — Actions works on both).
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
git init
|
|
34
|
+
git add -A
|
|
35
|
+
git commit -m "Initial commit"
|
|
36
|
+
git remote add origin git@github.com:<githubAccount>/<my-pkg>.git
|
|
37
|
+
git branch -M main
|
|
38
|
+
git push -u origin main
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## 5. Publish manually once
|
|
42
|
+
|
|
43
|
+
This establishes the package on npm. The trusted publisher can publish new
|
|
44
|
+
versions of an existing package, but cannot create a brand-new one.
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm login
|
|
48
|
+
npm publish --access public
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Verify: `https://www.npmjs.com/package/<npmScope>/<my-pkg>`
|
|
52
|
+
|
|
53
|
+
## 6. Configure trusted publisher on npm
|
|
54
|
+
|
|
55
|
+
1. Go to `https://www.npmjs.com/package/<npmScope>/<my-pkg>/access`
|
|
56
|
+
2. Scroll to **Trusted Publisher** → click **GitHub Actions**
|
|
57
|
+
3. Fill in:
|
|
58
|
+
|
|
59
|
+
| Field | Value |
|
|
60
|
+
|---|---|
|
|
61
|
+
| Organization or user | `<githubAccount>` |
|
|
62
|
+
| Repository | `<my-pkg>` |
|
|
63
|
+
| Workflow filename | `publish.yml` |
|
|
64
|
+
| Environment name | leave empty |
|
|
65
|
+
| Allowed actions | `npm publish` |
|
|
66
|
+
|
|
67
|
+
**Warning:** npm does NOT validate this form on save. Triple-check every field.
|
|
68
|
+
|
|
69
|
+
4. Click **Save**
|
|
70
|
+
|
|
71
|
+
## 7. Restrict token access (recommended)
|
|
72
|
+
|
|
73
|
+
On the same page, under **Publishing access**, select:
|
|
74
|
+
**"Require two-factor authentication and disallow tokens"**.
|
|
75
|
+
|
|
76
|
+
Trusted publishers bypass this restriction. This blocks any leaked API tokens
|
|
77
|
+
from publishing to your package.
|
|
78
|
+
|
|
79
|
+
## 8. Push a tag and publish
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
npm version patch
|
|
83
|
+
git push --follow-tags
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Watch the workflow run: `https://github.com/<githubAccount>/<my-pkg>/actions`
|
|
87
|
+
|
|
88
|
+
Once green, the package is live on npm with cryptographic provenance.
|
|
89
|
+
|
|
90
|
+
## Releasing future versions
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Make changes, commit, push
|
|
94
|
+
git add -A && git commit -m "changes"
|
|
95
|
+
git push
|
|
96
|
+
|
|
97
|
+
# When ready to release:
|
|
98
|
+
npm version patch # or minor, or major
|
|
99
|
+
git push --follow-tags
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
No login. No tokens. No npm CLI on release day. The Action handles everything.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Setup Guide — npm Trusted Publishing with GitHub Actions
|
|
2
|
+
|
|
3
|
+
## What you're building
|
|
4
|
+
|
|
5
|
+
A pipeline where `git push --follow-tags` on your machine triggers a GitHub
|
|
6
|
+
Action that publishes your package to npm — with cryptographic provenance,
|
|
7
|
+
no long-lived tokens, no 2FA prompts.
|
|
8
|
+
|
|
9
|
+
## Prerequisites
|
|
10
|
+
|
|
11
|
+
- npm account (creates personal scope `@your-username`)
|
|
12
|
+
- GitHub account
|
|
13
|
+
- Node.js ≥ 22 and npm ≥ 11.5.1 on your local machine
|
|
14
|
+
|
|
15
|
+
## Step 1: Create the npm package locally
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
mkdir my-package && cd my-package
|
|
19
|
+
|
|
20
|
+
# With personal scope:
|
|
21
|
+
npm init --scope=@your-username
|
|
22
|
+
|
|
23
|
+
# Or with org scope (if you created an org on npmjs.com):
|
|
24
|
+
npm init --scope=@your-org
|
|
25
|
+
|
|
26
|
+
# Or unscoped:
|
|
27
|
+
npm init
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The `name` field in `package.json` now reads `@your-username/my-package`.
|
|
31
|
+
This is what users will `npm install`.
|
|
32
|
+
|
|
33
|
+
Write your code. Add a README.
|
|
34
|
+
|
|
35
|
+
## Step 2: Add the GitHub Actions workflow
|
|
36
|
+
|
|
37
|
+
Create `.github/workflows/publish.yml`. The template is in `references/publish.yml`
|
|
38
|
+
in this skill directory. Copy it verbatim — it has the correct permissions,
|
|
39
|
+
npm upgrade step, and a bare `npm publish` command (no `--provenance`, no auth token).
|
|
40
|
+
|
|
41
|
+
Key requirements in the workflow:
|
|
42
|
+
- `permissions: id-token: write` at root level (not per-job)
|
|
43
|
+
- `npm install -g npm@latest` before publish (trusted publishing needs ≥ 11.5.1)
|
|
44
|
+
- `npm publish --access public` — bare, no extra flags
|
|
45
|
+
- Triggers on tags matching `v*`
|
|
46
|
+
|
|
47
|
+
## Step 3: Create the GitHub repo and push
|
|
48
|
+
|
|
49
|
+
Create a repo on GitHub (public or private — Actions works on both, 2,000 free
|
|
50
|
+
minutes/month for private repos).
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
git init
|
|
54
|
+
git add -A
|
|
55
|
+
git commit -m "Initial commit"
|
|
56
|
+
git remote add origin git@github.com:your-username/my-package.git
|
|
57
|
+
git branch -M main
|
|
58
|
+
git push -u origin main
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Step 4: Publish the package manually ONCE
|
|
62
|
+
|
|
63
|
+
This establishes the package on npm. The trusted publisher needs a package to
|
|
64
|
+
publish *to* — it can't create a new package from scratch.
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npm login # prompts for username, password, 2FA if enabled
|
|
68
|
+
npm publish --access public
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Verify: `https://www.npmjs.com/package/@your-username/my-package`
|
|
72
|
+
|
|
73
|
+
## Step 5: Configure the trusted publisher on npm
|
|
74
|
+
|
|
75
|
+
1. Go to `https://www.npmjs.com/package/@your-username/my-package/access`
|
|
76
|
+
2. Scroll to **Trusted Publisher**
|
|
77
|
+
3. Click **GitHub Actions**
|
|
78
|
+
4. Fill in:
|
|
79
|
+
|
|
80
|
+
| Field | Value |
|
|
81
|
+
|---|---|
|
|
82
|
+
| Organization or user | Your GitHub username (case-sensitive) |
|
|
83
|
+
| Repository | Your repo name (case-sensitive) |
|
|
84
|
+
| Workflow filename | `publish.yml` (filename only, no path) |
|
|
85
|
+
| Environment name | Leave empty |
|
|
86
|
+
| Allowed actions | `npm publish` |
|
|
87
|
+
|
|
88
|
+
**Critical:** npm does NOT validate this form on save. Every field must match
|
|
89
|
+
exactly — a single typo produces an opaque `E404` error later.
|
|
90
|
+
|
|
91
|
+
5. Click **Save**
|
|
92
|
+
|
|
93
|
+
## Step 6: Restrict token access (optional, recommended)
|
|
94
|
+
|
|
95
|
+
On the same page, under **Publishing access**, select:
|
|
96
|
+
**"Require two-factor authentication and disallow tokens"**
|
|
97
|
+
|
|
98
|
+
Trusted publishers bypass this check. It blocks any leaked API tokens from
|
|
99
|
+
publishing to your package.
|
|
100
|
+
|
|
101
|
+
## Step 7: Push a tag and watch it publish
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npm version patch # bumps version, creates git tag v1.x.x
|
|
105
|
+
git push --follow-tags # pushes code + tag, triggers the Action
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Watch the workflow run: `https://github.com/your-username/my-package/actions`
|
|
109
|
+
|
|
110
|
+
Once green, your package is live on npm with provenance.
|
|
111
|
+
|
|
112
|
+
## Releasing future versions
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# Make changes, commit, push as usual
|
|
116
|
+
git add -A && git commit -m "changes"
|
|
117
|
+
git push
|
|
118
|
+
|
|
119
|
+
# When ready to release:
|
|
120
|
+
npm version patch # or minor, or major
|
|
121
|
+
git push --follow-tags
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
That's it. No login, no tokens, no npm CLI on release day. The Action handles
|
|
125
|
+
everything.
|
|
126
|
+
|
|
127
|
+
## Organization-scoped packages
|
|
128
|
+
|
|
129
|
+
If publishing under an org (`@myorg/pkg`):
|
|
130
|
+
|
|
131
|
+
1. Create the org at `npmjs.com/org/create` (free)
|
|
132
|
+
2. Publish the first version manually as org owner
|
|
133
|
+
3. Configure trusted publisher on the org package's settings page
|
|
134
|
+
4. The GitHub repo can be under your personal account or the org — no coupling
|
|
135
|
+
|
|
136
|
+
Multiple maintainers: add them as org members on npm, and as repo collaborators
|
|
137
|
+
on GitHub. Anyone who pushes a tag can trigger a publish.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Troubleshooting — npm Trusted Publishing
|
|
2
|
+
|
|
3
|
+
## Error: `ENEEDAUTH` — "need auth"
|
|
4
|
+
|
|
5
|
+
**Full message:**
|
|
6
|
+
```
|
|
7
|
+
npm error code ENEEDAUTH
|
|
8
|
+
npm error need auth This command requires you to be logged in
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**Cause:** npm version too old for OIDC trusted publishing, or OIDC environment
|
|
12
|
+
not detected.
|
|
13
|
+
|
|
14
|
+
**Fix:** Add a step BEFORE `npm publish`:
|
|
15
|
+
```yaml
|
|
16
|
+
- run: npm install -g npm@latest
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Trusted publishing requires npm ≥ 11.5.1. The default npm on `ubuntu-latest`
|
|
20
|
+
runners is older and doesn't support OIDC.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Error: `E404` — "not in this registry"
|
|
25
|
+
|
|
26
|
+
**Full message:**
|
|
27
|
+
```
|
|
28
|
+
npm error code E404
|
|
29
|
+
npm error 404 Not Found - PUT https://registry.npmjs.org/@scope%2fpackage
|
|
30
|
+
npm error 404 '@scope/package@x.y.z' is not in this registry.
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Causes (check both):**
|
|
34
|
+
|
|
35
|
+
1. **Typo in trusted publisher config.** The GitHub owner, repo name, or workflow
|
|
36
|
+
filename on npmjs.com doesn't match exactly (case-sensitive). npm doesn't
|
|
37
|
+
validate this form on save — it only fails at publish time.
|
|
38
|
+
|
|
39
|
+
Fix: go to npmjs.com → package → Settings → Access → Trusted Publisher.
|
|
40
|
+
Re-enter all fields carefully. Check:
|
|
41
|
+
- GitHub username case (e.g., `my-github-user` not `My-Github-User`)
|
|
42
|
+
- Repo name exactly as on GitHub
|
|
43
|
+
- Workflow filename is just `publish.yml`, not `.github/workflows/publish.yml`
|
|
44
|
+
|
|
45
|
+
2. **Package never manually published.** The trusted publisher can publish new
|
|
46
|
+
versions of an existing package, but can't create a brand-new package.
|
|
47
|
+
|
|
48
|
+
Fix: `npm login && npm publish --access public` from your laptop once.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Error: `EOTP` — "one-time password required"
|
|
53
|
+
|
|
54
|
+
**Full message:**
|
|
55
|
+
```
|
|
56
|
+
npm error code EOTP
|
|
57
|
+
npm error This operation requires a one-time password from your authenticator.
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Cause:** The workflow is using an old token-based publish path instead of
|
|
61
|
+
OIDC trusted publishing. This happens when `NODE_AUTH_TOKEN` is set or when
|
|
62
|
+
`--provenance` is passed as a flag.
|
|
63
|
+
|
|
64
|
+
**Fix:**
|
|
65
|
+
- Remove `NODE_AUTH_TOKEN` env var from the workflow
|
|
66
|
+
- Remove `--provenance` flag from `npm publish` (provenance is automatic with OIDC)
|
|
67
|
+
- The workflow's `npm publish` line should be bare: `npm publish --access public`
|
|
68
|
+
|
|
69
|
+
Background: `--provenance` triggers the old provenance code path which expects
|
|
70
|
+
a token. With trusted publishers, provenance signing is automatic — the flag
|
|
71
|
+
is not only unnecessary but harmful.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Symptom: Provenance signed successfully but package not published
|
|
76
|
+
|
|
77
|
+
**What you see:** The workflow log shows "Provenance statement published to
|
|
78
|
+
transparency log" followed by a publish error.
|
|
79
|
+
|
|
80
|
+
**Cause:** Same as EOTP above — `--provenance` flag was passed, which signs the
|
|
81
|
+
provenance but then routes publish auth through the token path. The token isn't
|
|
82
|
+
set (or is wrong), so the publish fails even though provenance worked.
|
|
83
|
+
|
|
84
|
+
**Fix:** Remove `--provenance` from the `npm publish` command.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Symptom: Workflow never triggers
|
|
89
|
+
|
|
90
|
+
**Check:**
|
|
91
|
+
- Tag format: must match `v*` (e.g., `v1.0.0`, `v1.0.1`). `npm version patch`
|
|
92
|
+
creates these automatically.
|
|
93
|
+
- Did you push with `--follow-tags`? `git push` alone doesn't push tags.
|
|
94
|
+
- Run `git tag -l` to see local tags. Run `git ls-remote --tags origin` to see
|
|
95
|
+
remote tags.
|
|
96
|
+
|
|
97
|
+
## Symptom: Actions tab shows no workflow at all
|
|
98
|
+
|
|
99
|
+
The workflow file must be exactly at `.github/workflows/publish.yml` (not
|
|
100
|
+
`.github/workflows/publish.yaml`, not `.github/publish.yml`).
|
|
101
|
+
|
|
102
|
+
## General debugging
|
|
103
|
+
|
|
104
|
+
1. Go to `github.com/you/repo/actions` → click the failing run → expand the
|
|
105
|
+
`publish` step → read the full log
|
|
106
|
+
2. Check the trusted publisher config on npmjs.com for typos
|
|
107
|
+
3. Verify `npm --version` in the workflow log is ≥ 11.5.1
|
|
108
|
+
4. Try a manual publish from your laptop to confirm the package is healthy:
|
|
109
|
+
`npm publish --access public`
|