-
Notifications
You must be signed in to change notification settings - Fork 18
Comparing changes
Open a pull request
base repository: pnpm/setup
base: fix
head repository: pnpm/setup
compare: main
- 12 commits
- 23 files changed
- 11 contributors
Commits on Aug 4, 2026
-
docs: reference v2 in examples; update pnpm to v12.0.0-beta.4 (#16)
Two docs/CI changes ahead of the next release. ## Reference `v2` in examples The upcoming release drops pnpm 10 and older, so it goes out as `v2` rather than moving the `v1` tag. The README examples now point at the new major. `v1` (`5d160c5`) installed pnpm by `npm ci`-ing `@pnpm/exe` and then running `pnpm self-update <version>`; `main` downloads the self-contained release binary from pnpm's GitHub releases and enforces `MIN_SUPPORTED_MAJOR = 11`. Reproducing v1's flow locally with its own bootstrap (`@pnpm/exe@11.7.0`) confirms pnpm 10 really did work there: ``` $ pnpm self-update 10.20.0 Switching pnpm from v11.7.0 to v10.20.0... Successfully updated $ <PNPM_HOME>/bin/pnpm --version 10.20.0 ``` So moving `v1` would hard-fail anyone on `packageManager: pnpm@10.x`. The input/output surface is otherwise compatible — nothing removed or renamed, `token` added with a default — but that's a real break, and `6bfbb82`'s `feat!` marker was right. The "v11 and newer only" note now spells out that v1 could set up pnpm 10, so a v1 user whose workflow breaks on the upgrade finds the explanation rather than a bare version requirement that contradicts their experience. ### Context This came out of a report of `@v1` failing with: ``` .../global/v11/…/node_modules/@pnpm/exe/pnpm: 1: This: not found Error: The process '.../node_modules/.bin/bin/pnpm' failed with exit code 127 ``` That is isolated to pnpm 11.13.0, whose `@pnpm/exe` npm artifact ships the unreplaced `This file intentionally left blank` placeholder instead of the platform binary (now deprecated on npm; `pnpm/action-setup` rejects it with `ERR_PNPM_BROKEN_PNPM_RELEASE`). The 11.13.0 *GitHub release* asset is fine — it extracts to a real ELF binary reporting `11.13.0` — which is why pinning `pnpm/setup` to a `main` commit fixes it, and why `v2` is immune by construction. `v2` also fails loudly rather than silently on a bad artifact: `runSelfInstaller` runs `pnpm --version` after extraction and compares against the requested version. ## Update pnpm to v12.0.0-beta.4 v12 moved from alpha to beta — `next-12` now resolves to `12.0.0-beta.4`. Bumps the CI pins (`12.0.0-alpha.21`), the README example (`12.0.0-alpha.19`), and the `action.yml` sample version (`12.0.0-alpha.17`). The release ships the full asset set, including the `darwin-x64` build v11 lacks. No `src/` or `dist/` changes in either commit. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Configuration menu - View commit details
-
Copy full SHA for c9883cc - Browse repository at this point
Copy the full SHA c9883ccView commit details
Commits on Aug 7, 2026
-
fix: normalize Windows cache store paths (#22)
* fix: normalize Windows cache store paths * test: disable persisted checkout credentials
Configuration menu - View commit details
-
Copy full SHA for 34ec361 - Browse repository at this point
Copy the full SHA 34ec361View commit details -
README: bump versions (node, actions/setup) (#20)
Smoke test: bump version of actions/setup to v7 Co-authored-by: Andreas Deininger <andreas@deininger.net>
Configuration menu - View commit details
-
Copy full SHA for 4700d73 - Browse repository at this point
Copy the full SHA 4700d73View commit details
Commits on Aug 9, 2026
-
feat: install pnpm from the npm registry, verified against npm's sign…
…ature (#24) ## Summary The action verified the release archive against the `digest` GitHub publishes for it. GitHub serves both the asset and the digest, so whoever can replace one can replace the other — that catches a corrupted download, not a tampered one. The npm registry carries the same executable, **byte for byte**, and npm signs `<name>@<version>:<integrity>` with a key `get-pnpm` pins. That signature can't be produced without npm's private key, and behind it sits the maintainer's approval of the staged publish. **Every version this action installs now comes from the registry**, and is refused unless the signature *and* the checksum both check out. I verified the executables are identical across both sources before relying on it: | v12.0.0-rc.1 | GitHub release | npm platform package | |---|---|---| | linux-x64 | `f58dff16…` | `f58dff16…` | | darwin-arm64 | `180f2c62…` | `180f2c62…` | | win32-x64 (`pnpm.exe`) | `290aac61…` | `290aac61…` | v11 was going to stay on the release asset, because the registry copy declares `@reflink/reflink` as a dependency where the tarball bundles it, and this action has no step that would install it. That reasoning did not survive testing — an A/B with the dependency present and absent clones either way, and the tarball's bundled copy carries no native binding at all — so v11 comes from the registry too. That is the more important half: `latest` resolves to v11, so until now the *common* case was the one verified only by GitHub's digest. ## Two things fall out of not touching the GitHub API at all - **`token` is unused.** It existed to lift the anonymous 60 requests/hour limit on the release lookup, which no longer happens. Kept as a deprecated input so workflows passing it keep working. - **Versions published to npm without a GitHub release now install**, instead of hitting the "Some prerelease versions are published to npm but not released as downloadable binaries" error this action used to raise. With no source left that needs it, the release lookup, the asset naming, the sha256 check and the archive extraction are all gone — `download.ts` loses about 200 lines. ## Testing Every spec form, end to end against the real registry, each one placed and executed: | input | resolves to | placed | |---|---|---| | `next-12` | 12.0.0-rc.1 | `dist, pn, pnpm, pnpx, pnx` | | `latest` | 11.20.0 | `dist, pn, pnpm, pnpx, pnx` | | `^11.0.0` | 11.20.0 | `dist, pn, pnpm, pnpx, pnx` | | `11.20.0` | 11.20.0 | `dist, pn, pnpm, pnpx, pnx` | The existing smoke matrix covers Ubuntu (x64 + arm), macOS and Windows. ## It uses `get-pnpm` rather than its own copy The verification first landed here as its own implementation, because the package that does the same thing wasn't published. It is now (`get-pnpm@0.0.1`, from [pnpm/get.pnpm.io](https://github.com/pnpm/get.pnpm.io/tree/main/get-pnpm)), so the second commit deletes ~140 lines and depends on it. `downloadPnpm` verifies and places the executable and nothing else — it exists precisely so a caller that manages its own directory can use it without the global install and shell-rc editing that `pnpm setup` does. The action keeps what is genuinely its own: version resolution with semver ranges, the alias hardlinks, and PATH. That also puts the pinned keys in one place. `get.pnpm.io` refreshes them for all three of its installers on a schedule, so a rotation reaches this action as a dependency bump rather than by someone noticing. `get-pnpm` is excluded from `minimumReleaseAge` in `pnpm-workspace.yaml` — pnpm added that itself when I installed a package published minutes earlier. Worth a look if you'd rather wait for it to age instead. --- Written by an agent (Claude Code, claude-opus-5).
Configuration menu - View commit details
-
Copy full SHA for ed0c46d - Browse repository at this point
Copy the full SHA ed0c46dView commit details -
fix: keep the installed runtime authoritative against context-aware s…
…hims (#25) * fix: keep the installed runtime authoritative against context-aware shims pnpm 12 links global runtime bins as context-aware shims: running `node` from `$PNPM_HOME/bin` inside a project switches to the version that project pins in `devEngines.runtime`, fetching it on demand. That defeats the runtime this action was asked to install — a matrix job asking for `node@22` runs the repository's pinned version instead — and even when the two versions agree pnpm materializes a second copy outside `$PNPM_HOME`. Whenever the action installs a runtime, export `PNPM_CONFIG_GLOBAL_SHIMS` with that runtime disabled (`{"node":false}`). The setting merges key-wise over pnpm's defaults, so the runtimes the action did not install keep theirs. A value the workflow set itself always wins, under either of the two names pnpm reads it from, so opting back into the switching behaviour stays possible. `pnpm install --no-runtime` already expresses this for the install step; the shims reintroduced the shadowing for every step after it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * test: cover both spellings of the globalShims environment variable pnpm reads the setting from PNPM_CONFIG_GLOBAL_SHIMS or pnpm_config_global_shims, whichever comes first, so honouring only one of them would let the action override a workflow that used the other. Drive the opt-out job from a matrix over both names. Also record why an empty value counts as unset: pnpm ignores an empty value, so stepping aside for one would leave the shim enabled while looking like the workflow had opted in. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for 84cb39b - Browse repository at this point
Copy the full SHA 84cb39bView commit details
Commits on Aug 28, 2026
-
fix: restore cache before installing runtime (#39)
* fix: restore cache before installing runtime * fix: key runtime caches by resolved version * fix: list direct global runtime dependency * fix: never save the cache under the provisional restore key The runtime-cache-hit job blocked nodejs.org to prove the runtime came from the store, but `pnpm runtime set` fetches SHASUMS256.txt(.sig) and index.json on every run, warm store or not. The runtime install failed, so finalizeCache never ran, and the post step fell back to the provisional key — publishing a store that `pnpm store prune` had just emptied under a key later runs match exactly. Cache keys are immutable, so that entry would shadow the versioned cache until it aged out. Drop the fallback and skip the save when no final key was recorded. Make the installed-version lookup non-fatal, falling back to the requested selector, so refining a cache key can never fail the run or collide with the provisional key. Assert the collision invariant in the key tests, and rewrite the regression job to check the key scheme rather than the network. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R7B41egL5GwZk1gw2DU7sY --------- Co-authored-by: Zoltan Kochan <z@kochan.io> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for 1dad155 - Browse repository at this point
Copy the full SHA 1dad155View commit details -
feat: install multiple runtimes from devEngines.runtime (#32)
* feat: install multiple runtimes from devEngines.runtime * fix: dedupe runtime versions * fix: report the runtime versions that actually landed `installRuntime` returns the selector it was handed, so `node@24` was published as `24` through `runtime-version` and `runtimes` even though `action.yml` and the README both promise a resolved version. The version lookup added for the cache key already reads what pnpm installed, so run it once and feed both the outputs and the key from it. It stays non-fatal: a runtime whose version can't be read falls back to its selector, which also keeps the final cache key distinct from the provisional one. Resolve the explicit-input version fallback through the same deduped list the manifest path uses, so `runtime: node` against a manifest declaring node twice picks the last declaration rather than the first. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R7B41egL5GwZk1gw2DU7sY --------- Co-authored-by: Zoltan Kochan <z@kochan.io> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for f2f7d5f - Browse repository at this point
Copy the full SHA f2f7d5fView commit details -
perf: cache pnpm's lockfile verification results (#30)
* **New Features** * Added caching for pnpm lockfile verification results alongside the pnpm store. * Cache entries are keyed by the lockfile, operating system, and architecture. * Added cross-platform support and verification for Linux, macOS, and Windows. * Verification caches are restored and saved automatically during workflow execution. * **Documentation** * Updated action and usage documentation to explain lockfile verification caching, cache keys, and behavior.
Configuration menu - View commit details
-
Copy full SHA for 0e9f373 - Browse repository at this point
Copy the full SHA 0e9f373View commit details -
feat: add
working-directory, deprecatingpackage-json-file(#27)* Run install in `package-json-file`'s directory * feat: add `working-directory`, deprecating `package-json-file` `package-json-file` was inherited from pnpm/action-setup, where it had one job: name the file holding `packageManager`. In v2 it also picks the manifest `devEngines` is read from and gates whether `pnpm install` runs — and the fix for a project outside the repository root needs a fourth meaning, the directory to install in. The name stopped describing it. `working-directory` says the one thing all four need: where the project is. Config is read from the manifest there, `pnpm install` runs there, and `cache-dependency-path` resolves relative to it — without that last part a subdirectory project with `cache: true` matches no lockfile and the restore throws. It follows ruby/setup-ruby and astral-sh/setup-uv, which both name this input the same and use it for the same job. `package-json-file` keeps working on its own, deprecated, with the directory holding the file becoming the working directory; setting both is an error. pnpm resolves the workspace root by walking up from wherever it starts, so this is only needed when a project's own root is not the repository root — at the root, an install exits 0 having installed nothing. Co-Authored-By: Andrew Haines <andrew@haines.org.nz> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R7B41egL5GwZk1gw2DU7sY * fix: keep `cache-dependency-path` relative to the repository root Rebasing the configured value onto the working directory broke every workflow that already pointed it into a subdirectory: with `package-json-file: web/package.json` and `cache-dependency-path: web/pnpm-lock.yaml`, it became `web/web/pnpm-lock.yaml`, matched nothing, and the restore threw. Only the default follows the working directory now, so a subdirectory project still finds its own lockfile without a workflow naming it twice, and the input keeps the meaning it has always been documented with. The pattern rewriting that existed only to serve the old behaviour is gone. Also resolve the manifest against the workspace with `path.resolve` rather than `path.join` — an absolute or `~`-expanded path silently lost the workspace prefix, so the existence check missed the manifest and the install was skipped. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R7B41egL5GwZk1gw2DU7sY --------- Co-authored-by: Zoltan Kochan <z@kochan.io> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for 3327d57 - Browse repository at this point
Copy the full SHA 3327d57View commit details -
feat: add a
require-lockfileinput (#23)A separate boolean rather than a value on `install`: the two are orthogonal — whether to install at all, and whether the install has to be described by a lockfile — and folding them together meant turning a boolean input into an enum, with an empty-value error to go with it. When set, the action looks for `pnpm-lock.yaml` in `working-directory` and above it, the way pnpm searches for the workspace root, and fails there and then if none exists. Running pnpm first only reaches the same conclusion later and through a worse message. The mode is narrower than the proposal it came from. Retested on the released 12.0.0 rather than the 12.0.0-rc.3 that PR was written against: an out-of-date lockfile now fails a plain `CI=true pnpm install` on 11 and 12 alike, so the divergence between the majors is gone. What the CI default still does not do is require a lockfile to exist — with none at all it resolves from the registry, writes one and exits 0 on both. That single case is what this closes. The `ci` mode from the proposal is dropped: `pnpm ci` adds a `pnpm clean` that only matters when `node_modules` survives between runs, and this action caches the store rather than `node_modules`. Failures now name the command actually run, and a process killed by a signal reports `status: null` with no `error` — a truthiness check on `status` alone let that pass as success. Claude-Session: https://claude.ai/code/session_01R7B41egL5GwZk1gw2DU7sY Co-authored-by: Zoltan Kochan <z@kochan.io> Co-authored-by: Sebastian <sebdanielsson@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for 0080eca - Browse repository at this point
Copy the full SHA 0080ecaView commit details -
ci: update dependencies with pnpm/update instead of Dependabot (#41)
Dependabot cannot open a passing pull request against this repository. `dist/index.js` is committed and pr-check rebuilds it and fails on any difference, but a bump only touches package.json and the lockfile — so every update lands with a bundle built by the previous dependency set. That is why #5 is red: esbuild 0.28 changed the CommonJS init helpers it emits, so a fresh build cannot match the committed one. It is not specific to esbuild either. All twelve runtime dependencies are inlined into that bundle. pnpm/update runs `pnpm run build` through its `post-update` hook, so the rebuilt bundle is committed alongside the bump and the pull request can go green. It also updates through pnpm itself, so workspace features the lockfile depends on are handled by the tool that owns them. `verify` typechecks and runs the unit tests before the commit is made; the pull request then gets the full matrix from test.yaml. Claude-Session: https://claude.ai/code/session_01R7B41egL5GwZk1gw2DU7sY Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for e02cd34 - Browse repository at this point
Copy the full SHA e02cd34View commit details -
chore: update dependencies (#42)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for 703c526 - Browse repository at this point
Copy the full SHA 703c526View commit details
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff fix...main
