chore(ci): migrate workflows to pnpm/setup#11589
Conversation
📝 WalkthroughWalkthroughFive GitHub Actions workflow files are updated to use the ChangesGitHub Actions pnpm setup action migration
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
On Windows, `pnpm self-update` lands the new pnpm into PNPM_HOME/bin as either `.exe`, `.cmd`, or extensionless `pnpm` depending on version and shim mechanism. Hardcoding `pnpm.exe` and spawning under shell:true caused cmd.exe to report "not recognized" when the extension didn't match. Drop the extension and let PATHEXT resolve. Also bump the test workflow's pnpm version from 11.0.4 (which matches the bootstrap, making self-update a no-op) to 11.0.7, so the self-update + runtime install path is actually exercised in CI on every OS. Caught by the pnpm/pnpm migration in pnpm/pnpm#11589.
## Summary When the user pins a runtime via the action's `runtime` input, that runtime has already been installed and put on `PATH` by the time the action's auto-`pnpm install` runs. If the project's `package.json` also declares a different `devEngines.runtime` with `onFail: download`, pnpm install would fetch that second runtime and silently swap the active one — defeating matrix-style or explicit pins. This PR appends `--no-runtime` to the auto-`pnpm install` invocation whenever the `runtime` input is set. The flag (pnpm ≥ 11.1.0) tells pnpm install to skip the runtime fetch entirely. The lockfile and frozen-install behavior are untouched. When `runtime` is omitted (and the action read it from `devEngines.runtime` instead), `pnpm install` runs unmodified — the devEngines runtime is the only source of truth and install should honor it. ## What changed - `src/pnpm-install/index.ts` — append `--no-runtime` to the install args when `inputs.runtime` is defined. - `.github/workflows/test.yaml` — bump pnpm pin to `11.1.0` everywhere (required for `--no-runtime`). Add a new `runtime-overrides-devengines` job that pins `node@22` in the action input, declares `^20.0.0` in `devEngines.runtime`, and asserts node 22 is still active after install. - `README.md` — documents the new auto-flag behavior and the pnpm ≥ 11.1.0 requirement under "How it works". ## Why this is opt-in by input, not by config The two interesting cases: | `runtime` input | `devEngines.runtime` | Behavior | |---|---|---| | set | set, different | **--no-runtime** — explicit input wins, install doesn't shadow | | set | unset | --no-runtime — harmless no-op | | unset | set | normal install — devEngines.runtime is the only source | | unset | unset | normal install — no runtime to worry about | The "set + different" case is the only one that previously misbehaved. ## Test plan - [ ] All matrix jobs in `Test Action` pass, including the new `runtime-overrides-devengines` job - [ ] `pr-check / check-dist` passes - [ ] After merge, follow up on `pnpm/pnpm#11589` to drop the manual `env: npm_config_runtime: 'false'` workaround <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **New Features** * Enhanced runtime configuration support during dependency installation to prevent conflicts with existing configurations. * **Documentation** * Updated guidance on pnpm version compatibility requirements and installation behavior when providing runtime inputs. * **Tests** * Expanded test coverage for runtime configuration override scenarios. * **Chores** * Updated pnpm to version 11.1.0. [](https://app.coderabbit.ai/change-stack/pnpm/setup/pull/2) <!-- end of auto-generated comment: release notes by coderabbit.ai -->
pnpm/setup installs pnpm and the JS runtime in one step, replacing the separate `pnpm/action-setup` + `pn runtime -g set node …` + `pn install` trio. `pnpm install` now happens inside the action, so the per-workflow install step is gone. - test.yml: replaced with `pnpm/setup` (runtime: node@<inputs.node>); Verify-npm step retained as a sanity check (npm comes from the runner image, not the pnpm-installed runtime). - ci.yml, release.yml, benchmark.yml: same migration with pinned node versions. - audit.yml: only needs pnpm, no runtime input. - update-lockfile.yml: migrated with a note flagging that the action's auto-install is wasted work for this job (it then deletes the lockfile and regenerates with --lockfile-only). - update-latest.yml: untouched — it doesn't use pnpm. This commit pins to the `init-action` branch of pnpm/setup. Pin to a SHA or tag before merging.
The init-action branch was deleted after pnpm/setup#1 was merged. v0 is the moving major-zero ref published from pnpm/setup; v0.0.1 is the immutable tag it currently points at.
Picks up the fix from pnpm/setup#2: - Drops the buggy patchPnpmEnv that shadowed the self-updated pnpm on Windows-standalone. - Auto-appends --no-runtime to pnpm install when a runtime input is set and the running pnpm is >= 11.1.0. The manual `env: npm_config_runtime: 'false'` workaround in test.yml is no longer needed — the action handles it.
Other setup actions (actions/setup-node, setup-python, oven-sh/setup-bun, denoland/setup-deno) install the toolchain only and leave dependency installation to the caller. Match that convention instead of providing an opt-out for cases like `pnpm audit` or lockfile-only regeneration jobs (see pnpm/pnpm#11589) that don't want the install.
* feat: do not run pnpm install automatically Other setup actions (actions/setup-node, setup-python, oven-sh/setup-bun, denoland/setup-deno) install the toolchain only and leave dependency installation to the caller. Match that convention instead of providing an opt-out for cases like `pnpm audit` or lockfile-only regeneration jobs (see pnpm/pnpm#11589) that don't want the install. * test: add explicit pnpm install steps in tests Two test jobs (`runtime-from-devengines` and `runtime-overrides-devengines`) asserted that the action runs `pnpm install` automatically. Now that the action no longer does that, add the install as an explicit caller step and update comments. For the override case, pass `--no-runtime` since the caller — not the action — owns suppressing the devEngines runtime fetch.
pnpm/setup no longer auto-runs `pnpm install`, so add explicit `pn install` steps in the workflows that need node_modules.
`devEngines.runtime` in package.json already pins node@24.6.0 with `onFail: download`, so pnpm will fetch the same version on first use.
Re-add the post-install Node version check that asserts the matrix `inputs.node` survives `pn install`. Pass `--no-runtime` so devEngines runtime (24.6.0, onFail: download) doesn't swap the matrix-installed Node out from under the canary.
pnpm/setup now runs `pnpm install` by default again (with auto `--no-runtime` when `runtime:` is set), so the explicit install steps are no longer needed. Set `install: false` in jobs that don't want the install — audit and lockfile-only regeneration.
There was a problem hiding this comment.
Pull request overview
Migrates GitHub Actions workflows from pnpm/action-setup plus manual pnpm runtime set node … / pnpm install steps to the new consolidated pnpm/setup action, relying on its built-in runtime installation and auto-install behavior to simplify CI.
Changes:
- Replace
pnpm/action-setupwithpnpm/setupacross CI-related workflows. - Remove explicit
pnpm installsteps wherepnpm/setupwill auto-install. - Configure
pnpm/setupwithruntime: node@…in workflows that need a pinned Node version, and disable auto-install where it’s intentionally redundant.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| .github/workflows/update-lockfile.yml | Switches to pnpm/setup and disables auto-install during lockfile regeneration. |
| .github/workflows/test.yml | Uses pnpm/setup to install pnpm + a specified Node runtime; relies on action auto-install and keeps an npm canary check. |
| .github/workflows/release.yml | Uses pnpm/setup to install pnpm + Node runtime and removes explicit install steps. |
| .github/workflows/ci.yml | Switches to pnpm/setup and relies on auto-install instead of an explicit install step. |
| .github/workflows/benchmark.yml | Uses pnpm/setup to install pnpm + Node runtime and removes explicit dependency install step. |
| .github/workflows/audit.yml | Switches to pnpm/setup while disabling auto-install for an audit-only job. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
Migrates CI workflows from
pnpm/action-setup+ manualpn runtime set node …+pn installto the new combinedpnpm/setupaction (see pnpm/setup#1).pnpm/setupinstalls pnpm and the JS runtime in one step. It also runspnpm installautomatically when apackage.jsonis present, so per-workflow install steps are dropped. When theruntimeinput is set, the action passes--no-runtimetopnpm installso the matrix-selected Node version isn't shadowed by a differentdevEngines.runtimepin.What changed
test.ymlpnpm/setupwithruntime: node@${{ inputs.node }}. Verify-Node step asserts the matrix version stayed active. Verify-npm step retained as canary (npm comes from the runner image, not the pnpm-installed runtime).ci.ymlpnpm/setup(noruntimeinput —devEngines.runtimein package.json handles the Node pin).release.ymlpnpm/setupwithruntime: node@26.0.0.benchmark.ymlpnpm/setupwithruntime: node@26.0.0.audit.ymlpnpm/setupwithinstall: false— audit only needs pnpm itself, notnode_modules.update-lockfile.ymlpnpm/setupwithinstall: false— the job deletespnpm-lock.yamland regenerates it via--lockfile-only, so the action's auto-install would be wasted.update-latest.ymlCaveats / things to watch
pnpm runtime set nodedoes not extract npm. The runner image's pre-installed Node toolchain providesnpmon PATH; if a future runner image change removes that, dlx-style git-hosted dependency tests intest.ymlwill fail. TheVerify npmstep intest.ymlis the canary.Related upstream change
installinput so callers likeaudit.ymlandupdate-lockfile.ymlcan opt out of the action's auto-install.Test plan
ci.yml) passes — compile + lint withpnpm/setuptest.ymlmatrix passes across node versions and platformsaudit.ymlpassesbenchmark.yml(workflow_dispatch) — optional, only if the perf path needs verifyingSummary by CodeRabbit
PR description updated by an agent (Claude Code, claude-opus-4-7).