Comparing fix...main · pnpm/setup · GitHub
Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: pnpm/setup
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: fix
Choose a base ref
...
head repository: pnpm/setup
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
Checking mergeability… Don’t worry, you can still create the pull request.
  • 12 commits
  • 23 files changed
  • 11 contributors

Commits on Aug 4, 2026

  1. 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)
    zkochan authored Aug 4, 2026
    Configuration menu
    Copy the full SHA
    c9883cc View commit details
    Browse the repository at this point in the history

Commits on Aug 7, 2026

  1. fix: normalize Windows cache store paths (#22)

    * fix: normalize Windows cache store paths
    
    * test: disable persisted checkout credentials
    zkochan authored Aug 7, 2026
    Configuration menu
    Copy the full SHA
    34ec361 View commit details
    Browse the repository at this point in the history
  2. README: bump versions (node, actions/setup) (#20)

    Smoke test: bump version of actions/setup to v7
    
    Co-authored-by: Andreas Deininger <andreas@deininger.net>
    urban-adeininger and deining authored Aug 7, 2026
    Configuration menu
    Copy the full SHA
    4700d73 View commit details
    Browse the repository at this point in the history

Commits on Aug 9, 2026

  1. 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).
    zkochan authored Aug 9, 2026
    Configuration menu
    Copy the full SHA
    ed0c46d View commit details
    Browse the repository at this point in the history
  2. 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>
    zkochan and claude authored Aug 9, 2026
    Configuration menu
    Copy the full SHA
    84cb39b View commit details
    Browse the repository at this point in the history

Commits on Aug 28, 2026

  1. 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>
    3 people authored Aug 28, 2026
    Configuration menu
    Copy the full SHA
    1dad155 View commit details
    Browse the repository at this point in the history
  2. 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>
    3 people authored Aug 28, 2026
    Configuration menu
    Copy the full SHA
    f2f7d5f View commit details
    Browse the repository at this point in the history
  3. 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.
    zkochan authored Aug 28, 2026
    Configuration menu
    Copy the full SHA
    0e9f373 View commit details
    Browse the repository at this point in the history
  4. feat: add working-directory, deprecating package-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>
    3 people authored Aug 28, 2026
    Configuration menu
    Copy the full SHA
    3327d57 View commit details
    Browse the repository at this point in the history
  5. feat: add a require-lockfile input (#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>
    4 people authored Aug 28, 2026
    Configuration menu
    Copy the full SHA
    0080eca View commit details
    Browse the repository at this point in the history
  6. 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>
    zkochan and claude authored Aug 28, 2026
    Configuration menu
    Copy the full SHA
    e02cd34 View commit details
    Browse the repository at this point in the history
  7. chore: update dependencies (#42)

    Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
    github-actions[bot] and github-actions[bot] authored Aug 28, 2026
    Configuration menu
    Copy the full SHA
    703c526 View commit details
    Browse the repository at this point in the history
Loading