go-tokenless 0.1.0 → 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/README.md CHANGED
@@ -1,33 +1,56 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/Continuous-Actions/go-tokenless/main/docs/assets/header.png" alt="go-tokenless: removes NODE_AUTH_TOKEN from a release workflow and adds id-token: write" width="100%">
3
+ </p>
4
+
1
5
  # go-tokenless
2
6
 
3
- **Delete your `NPM_TOKEN`.** One command switches your GitHub Actions release workflow to [npm trusted publishing](https://docs.npmjs.com/trusted-publishers) (OIDC), so no long-lived npm token has to be stored anywhere.
7
+ [![CI](https://github.com/Continuous-Actions/go-tokenless/actions/workflows/ci.yml/badge.svg)](https://github.com/Continuous-Actions/go-tokenless/actions/workflows/ci.yml)
8
+ [![npm](https://img.shields.io/npm/v/go-tokenless?logo=npm)](https://www.npmjs.com/package/go-tokenless)
9
+ [![MCP Registry](https://img.shields.io/badge/MCP_Registry-go--tokenless-blue)](https://registry.modelcontextprotocol.io/v0/servers?search=go-tokenless)
10
+ [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/Continuous-Actions/go-tokenless/badge)](https://scorecard.dev/viewer/?uri=github.com/Continuous-Actions/go-tokenless)
11
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
12
+
13
+ **Delete your `NPM_TOKEN`.** One command switches npm publishing in GitHub Actions to [trusted publishing](https://docs.npmjs.com/trusted-publishers) (OIDC). No long-lived token is stored anywhere, and every release gets a provenance badge.
14
+
15
+ > npm is retiring token publishing: from **January 2027** a token can no longer publish on its own ([npm docs](https://docs.npmjs.com/about-access-tokens/)).
16
+
17
+ ## Quick start
18
+
19
+ From the root of the repository that publishes to npm:
4
20
 
5
21
  ```bash
6
- npx go-tokenless # show what would change (writes nothing)
7
- npx go-tokenless apply # make the changes
22
+ npx go-tokenless # 1. preview: lists every change and shows a diff, writes nothing
23
+ npx go-tokenless apply # 2. edit the workflow and package.json files
8
24
  ```
9
25
 
10
- npm is retiring direct publishing with tokens: from **January 2027** a granular token with "bypass 2FA" can no longer publish on its own ([npm docs](https://docs.npmjs.com/about-access-tokens/)). Trusted publishing is the replacement for CI. It also adds a provenance badge to every release.
26
+ Then follow the **Next** steps it prints: commit the change, connect the package to the workflow on npm, and delete the old secret. Needs Node 22.14+.
11
27
 
12
- ## What it does
28
+ ## What it changes
13
29
 
14
- It reads your workflows and `package.json` files, then:
30
+ Only the lines that need to change are touched: comments, quoting and layout in your workflows are kept, and in `package.json` only the `repository` field is edited. Before writing, go-tokenless re-reads both versions and refuses if anything other than the migration would change.
15
31
 
16
- | Problem | Fix it makes |
32
+ | Problem in your release workflow | What go-tokenless does |
17
33
  |---|---|
18
- | `NODE_AUTH_TOKEN` / `NPM_TOKEN` passed to the publish step or job | Removes it (a token, even an empty one, stops npm from using OIDC) |
19
- | Job can't request an OIDC token | Adds `permissions: id-token: write` (keeping the permissions the job already had) |
20
- | Node 22 or older ships npm < 11.5.1 | Adds an `npm install -g npm@^12` step (pinned to one major, see [npm version](#npm-version)), or moves Node < 22 to 24 |
34
+ | `NODE_AUTH_TOKEN` / `NPM_TOKEN` on the publish job (or the workflow) | Removes it, so the secret can be deleted. npm prefers OIDC but falls back to a configured token, which would keep the old token in use |
35
+ | Job can't request an OIDC token | Adds `permissions: id-token: write`, keeping the permissions it had |
36
+ | npm older than 11.5.1 (Node 22 and below) | Adds `npm install -g npm@^12`, or moves Node < 22 to 24 |
21
37
  | `actions/setup-node` without `registry-url` | Adds `registry-url: https://registry.npmjs.org` |
22
- | `changesets/action@v1`, `JS-DevTools/npm-publish@v3` | Updates to the version that supports trusted publishing |
23
- | Script writes `_authToken` into `.npmrc` | Removes those lines |
24
- | `repository` missing or in the wrong form in `package.json` | Adds `git+https://github.com/<owner>/<repo>.git` (with `directory` in monorepos) |
38
+ | `JS-DevTools/npm-publish` below v4 | Updates it to v4, which no longer requires a token |
39
+ | A script writes `_authToken` to `.npmrc` | Removes those lines |
40
+ | `repository` missing or in the wrong form in `package.json` | Sets `git+https://github.com/<owner>/<repo>.git` (with `directory` in monorepos) |
41
+
42
+ It stops with exit code `1` and writes nothing when a person needs to decide:
25
43
 
26
- It also prints the exact `npm trust github …` command for every package and the remaining manual steps.
44
+ - **Publishing reachable by outsiders:** a publish job in a workflow started by `pull_request_target`, `issue_comment`, `workflow_run` and similar triggers. Granting it OIDC would let a fork publish.
45
+ - **Self-hosted runners**, which npm doesn't accept for trusted publishing.
46
+ - **`repository` pointing at another repo.**
47
+ - **YAML anchors.** Edits could leak into other jobs.
48
+ - **A hidden publish command:** an npm token is passed but the publish command can't be found.
27
49
 
28
- It **refuses** (exit code 1) rather than guessing when trusted publishing can't work: self-hosted runners, or a `repository` field pointing at another repo. It leaves jobs that publish to GitHub Packages alone.
50
+ Dry runs (`npm publish --dry-run`) never count as publishing. Steps that publish to GitHub Packages, and `GITHUB_TOKEN` values, are left alone.
29
51
 
30
- ## Example
52
+ <details>
53
+ <summary><b>Example output</b></summary>
31
54
 
32
55
  ```text
33
56
  $ npx go-tokenless
@@ -46,88 +69,103 @@ Next:
46
69
  2. Add a trusted publisher for each package. With npm 11.15+ logged in with 2FA, run:
47
70
  npm trust github widgets --repo acme/widgets --file release.yml --allow-publish --yes
48
71
  3. Merge, then let the release workflow publish once. Check the new version shows a provenance badge.
49
- 4. Delete the old secret (`gh secret delete NPM_TOKEN`) and revoke the token on npmjs.com.
72
+ 4. Delete the old publish token secret (`gh secret delete NPM_TOKEN`) and revoke the token on npmjs.com.
50
73
  ```
51
74
 
52
- The default command also prints a unified diff. Your file's comments, quoting and layout are kept: only the lines that need to change are touched.
75
+ </details>
53
76
 
54
77
  ## Supported release setups
55
78
 
56
- | Setup | Supported | Notes |
57
- |---|---|---|
58
- | `npm publish` (incl. workspaces) | ✓ | |
59
- | pnpm `publish` / `-r publish` | ✓ | pnpm 10 hands off to npm; pnpm 11 needs 11.1.3+ |
60
- | Yarn Berry `yarn npm publish` | ✓ | Yarn 4.10.3+; remove `npmAuthToken` from `.yarnrc.yml` |
61
- | changesets (`changesets/action`) | ✓ | updated to v2 |
62
- | semantic-release | ✓ | needs @semantic-release/npm 13.1.0+ (semantic-release 25+) |
63
- | release-please + `npm publish` | ✓ | |
64
- | Lerna / Nx release | ✓ | Lerna 9+ |
65
- | JS-DevTools/npm-publish | ✓ | updated to v4 |
66
- | release-it | ✓ | also set `npm.skipChecks: true` |
67
- | Yarn 1 `yarn publish`, `bun publish` | warns | not supported by those tools yet; switch the command to `npm publish` |
68
- | Reusable workflows (`workflow_call`) | ✓ | npm checks the *calling* workflow's file name; the plan uses it |
69
-
70
- Version floors are checked against your `package.json` where possible.
79
+ | Setup | Notes |
80
+ |---|---|
81
+ | `npm publish` (incl. workspaces) | |
82
+ | pnpm `publish` / `-r publish` | pnpm 10 hands off to npm; pnpm 11 needs 11.1.3+ |
83
+ | Yarn Berry `yarn npm publish` | Yarn 4.10.3+; remove `npmAuthToken` from `.yarnrc.yml` |
84
+ | changesets (`changesets/action`) | Works as is; if the first tokenless release can't authenticate, update to v2 |
85
+ | semantic-release | Needs @semantic-release/npm 13.1.0+ (semantic-release 25+) |
86
+ | release-please + `npm publish` | |
87
+ | Lerna / Nx release | Lerna 9+ |
88
+ | JS-DevTools/npm-publish | Updated to v4 |
89
+ | release-it | Also set `npm.skipChecks: true` |
90
+ | Reusable workflows (`workflow_call`) | npm checks the *calling* workflow's file name; a trust command is printed for every caller |
91
+ | Publishing inside scripts | Follows package.json scripts, `./scripts/*.sh`, `make <target>` and local composite actions (`uses: ./.github/actions/...`), including `working-directory` |
92
+ | Yarn 1 `yarn publish`, `bun publish` | Flagged: those tools can't use trusted publishing yet, so switch to `npm publish` |
93
+
94
+ ## Private packages
95
+
96
+ If your installs need private packages from your npm org, give the install steps a **read-only** token. Publish steps stay token-free:
71
97
 
72
- ## Things only you can do
98
+ ```bash
99
+ npx go-tokenless apply --read-token NPM_READ_TOKEN
100
+ ```
73
101
 
74
- The tool never touches your npm account. After applying:
102
+ ```diff
103
+ - run: npm ci
104
+ + env:
105
+ + NODE_AUTH_TOKEN: ${{ secrets.NPM_READ_TOKEN }}
106
+ - run: npm publish
107
+ ```
75
108
 
76
- 1. **Add a trusted publisher** for each package: the printed `npm trust github …` commands (npm 11.15+, needs your 2FA), or npmjs.com → package → **Settings → Trusted publishing**.
77
- 2. **Brand-new packages** must be published once by hand first; npm can only attach a trusted publisher to a package that exists. The plan flags these.
78
- 3. **Delete the secret** and revoke the token once a release has gone out.
109
+ Every install step in the release workflow gets it, including separate build and test jobs. Create a granular token on npmjs.com with read-only access to your packages and save it with `gh secret set NPM_READ_TOKEN`.
79
110
 
80
- ## Use it from an AI coding agent
111
+ ## Use it with AI agents
81
112
 
82
- Agents can run the CLI with `--json` (stable shape, `status` field, exit codes), or use the MCP server:
113
+ go-tokenless is built to be run by coding agents: `--json` output, clear exit codes, an MCP server and an Agent Skill. Ask your agent: *"Move our npm publishing to trusted publishing."*
83
114
 
84
- ```bash
85
- claude mcp add go-tokenless -- npx -y go-tokenless mcp
86
- ```
115
+ | Client | Setup |
116
+ |---|---|
117
+ | Claude Code (plugin: skill + MCP) | `/plugin marketplace add Continuous-Actions/go-tokenless` then `/plugin install go-tokenless@continuous-actions` |
118
+ | Claude Code (MCP only) | `claude mcp add go-tokenless -- npx -y go-tokenless mcp` |
119
+ | Gemini CLI | `gemini extensions install https://github.com/Continuous-Actions/go-tokenless` |
120
+ | Cursor, VS Code, others | Add the MCP config below |
121
+ | Any agent with skills | `npx skills add Continuous-Actions/go-tokenless` |
87
122
 
88
123
  ```json
89
124
  { "mcpServers": { "go-tokenless": { "command": "npx", "args": ["-y", "go-tokenless", "mcp"] } } }
90
125
  ```
91
126
 
92
- Tools: `plan_trusted_publishing` (read-only) and `apply_trusted_publishing` (writes files, no git or network writes). There is also an [Agent Skill](skills/go-tokenless/SKILL.md):
93
-
94
- ```bash
95
- npx skills add Continuous-Actions/go-tokenless
96
- ```
97
-
98
- Just ask: *"Move our npm publishing to trusted publishing."*
127
+ MCP tools: `plan_trusted_publishing` (read-only) and `apply_trusted_publishing` (writes files; no git or network writes). It is listed in the [MCP Registry](https://registry.modelcontextprotocol.io/v0/servers?search=go-tokenless) as `io.github.Continuous-Actions/go-tokenless`. See also [llms.txt](llms.txt) and the [Agent Skill](skills/go-tokenless/SKILL.md).
99
128
 
100
129
  ## Options
101
130
 
102
131
  ```text
103
- npx go-tokenless [plan|apply|mcp] [--json] [--diff] [--repo owner/repo] [--cwd dir] [--offline]
104
- [--npm-version <range>] [--npm-args "<args>"]
132
+ npx go-tokenless [plan | apply | mcp] [options]
105
133
  ```
106
134
 
107
- | Option | Meaning |
135
+ | Option | Description |
108
136
  |---|---|
109
- | `--json` | Print the full plan as JSON |
110
- | `--diff` | Include the diff (always on for `plan`) |
111
- | `--repo` | GitHub `owner/repo`, when the `origin` remote isn't GitHub |
112
- | `--offline` | Skip the npm registry lookup that checks each package already exists |
113
- | `--npm-version <range>` | npm version for the inserted upgrade step. Default `^12` |
114
- | `--npm-args "<args>"` | Extra arguments appended to every npm command it generates: the upgrade step and the `npm trust` commands (for example `--registry=…` or `--loglevel=warn`) |
137
+ | `--json` | Print the full plan as JSON (`status`, `changes`, `diff`, `findings`, `trust`, `nextSteps`) |
138
+ | `--diff` | Include the diff in text output (always on for `plan`) |
139
+ | `--repo <owner/repo>` | GitHub repository, when `origin` isn't GitHub |
140
+ | `--cwd <dir>` | Repository root (default: current directory) |
141
+ | `--offline` | Skip the npm registry check that each package already exists |
142
+ | `--read-token <SECRET>` | Give install steps a read-only token from this secret ([private packages](#private-packages)) |
143
+ | `--npm-version <range>` | npm for the inserted upgrade step. Default `^12`, pinned to one major so releases don't change under you. Other versions show a warning; below 11.5.1 is refused |
144
+ | `--npm-args "<args>"` | Extra arguments for every npm command it generates (upgrade step and `npm trust`) |
145
+
146
+ Exit codes: `0` ok · `1` blocked (needs a human fix) · `2` usage error · `3` unexpected error.
115
147
 
116
- Exit codes: `0` ok, `1` blocked (errors to fix by hand), `2` usage error, `3` unexpected error. Needs Node 22.14+.
148
+ ## What only you can do
117
149
 
118
- ### npm version
150
+ go-tokenless never touches your npm account, secrets or git history. After `apply`:
119
151
 
120
- When a publish job runs on a Node version whose bundled npm is too old, go-tokenless adds `npm install -g npm@^12`. It is pinned to one major on purpose: a new npm major can change how publishing behaves, and a release pipeline should not change under you. npm 12 needs Node 22.22.2+ or 24.15+; jobs pinned to an older exact Node 22 get a warning.
152
+ 1. **Connect each package to the workflow**: run the printed `npm trust github …` commands (npm 11.15+, asks for 2FA), or go to npmjs.com → package → **Settings → Trusted publishing**.
153
+ 2. **New packages** must be published once by hand first; npm can only connect a package that exists. The plan flags these.
154
+ 3. **Delete the old secret** and revoke the token after the first tokenless release.
121
155
 
122
- To use a different npm, pass `--npm-version` (for example `--npm-version ^11.6.0`). go-tokenless warns that an untested version may break the release, and refuses versions older than 11.5.1, which cannot use trusted publishing.
156
+ ## Troubleshooting
157
+
158
+ | Error | Usual cause |
159
+ |---|---|
160
+ | `npm error code ENEEDAUTH` | No `id-token: write`, npm older than 11.5.1, or the workflow file name doesn't match the trusted publisher exactly (case-sensitive, with `.yml`) |
161
+ | `npm error 404 Not Found - PUT https://registry.npmjs.org/...` | Same as above, an `environment` mismatch, or no trusted publisher yet |
162
+ | `npm error code E422` … `repository.url` | `package.json` `repository` doesn't match the GitHub repo. `apply` fixes the format |
163
+ | Publishing still uses the token | Something still sets `NODE_AUTH_TOKEN`, `NPM_TOKEN`, an `.npmrc` `_authToken` or `.yarnrc.yml` `npmAuthToken`. Run `npx go-tokenless` again to find it |
123
164
 
124
- ## Troubleshooting the errors people hit
165
+ ## Contributing
125
166
 
126
- - **`npm error code ENEEDAUTH`**: the job has no `id-token: write`, npm is older than 11.5.1, or the workflow file name doesn't match the trusted publisher exactly (case-sensitive, with `.yml`).
127
- - **`npm error 404 Not Found - PUT https://registry.npmjs.org/...`**: usually the same causes as ENEEDAUTH, an `environment` mismatch, or the package has no trusted publisher yet.
128
- - **`npm error code E422` … `repository.url`**: `package.json` `repository` doesn't match the GitHub repo. `go-tokenless apply` fixes the format; a different repo is reported as an error.
129
- - **Publishing still uses the token**: something still sets `NODE_AUTH_TOKEN`, `NPM_TOKEN`, an `.npmrc` `_authToken`, or `.yarnrc.yml` `npmAuthToken`. Run `npx go-tokenless` again; it reports leftovers.
167
+ Issues and pull requests are welcome. Run `corepack enable && yarn install && yarn check` (typecheck, build and end-to-end tests). See [AGENTS.md](AGENTS.md) for how the code is laid out, and [SECURITY.md](SECURITY.md) to report a vulnerability.
130
168
 
131
169
  ## License
132
170
 
133
- MIT
171
+ [MIT](LICENSE) © Continuous-Actions