Skip to content

fix: pnpm self-update binary shadowed by bootstrap on PATH#230

Merged
zkochan merged 3 commits intopnpm:masterfrom
oniani1:fix/version-selection-path-priority
Apr 18, 2026
Merged

fix: pnpm self-update binary shadowed by bootstrap on PATH#230
zkochan merged 3 commits intopnpm:masterfrom
oniani1:fix/version-selection-path-priority

Conversation

@oniani1
Copy link
Copy Markdown
Contributor

@oniani1 oniani1 commented Apr 15, 2026

Fixes #229

Problem

pnpm self-update installs the target version to PNPM_HOME/bin/pnpm, but the bootstrap binary at PNPM_HOME/pnpm has higher PATH precedence because addPath(pnpmHome) was called after addPath(pnpmHome/bin). @actions/core's addPath prepends, so the later call wins — the bootstrap version shadows the self-updated binary.

Fix

Swap the addPath call order so PNPM_HOME/bin (where self-update puts the target binary) has higher PATH precedence. The bootstrap pnpm is invoked via absolute path, so this doesn't affect the bootstrap step.

Verification

Reproduced locally by simulating the action flow:

Scenario Before After
version: 10 11.0.0-rc.0 10.33.0
No version (bootstrap) 11.0.0-rc.0 11.0.0-rc.0 (unchanged)

The bootstrap pnpm binary at PNPM_HOME shadows the self-updated
binary at PNPM_HOME/bin because addPath(pnpmHome) was called after
addPath(pnpmHome/bin), giving the bootstrap higher PATH precedence.

Swap the addPath order so the self-updated binary takes priority.
The bootstrap is invoked via absolute path, so this doesn't affect
the bootstrap step.

Also extract the version from the packageManager field and pass it
to self-update explicitly, instead of returning undefined and relying
on the bootstrap's auto-switching which can modify the lockfile.

Fixes pnpm#225, fixes pnpm#227, fixes pnpm#228
@peterdeme
Copy link
Copy Markdown

Please address this asap 🙏

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes pnpm/action-setup v6 using the bootstrap pnpm binary instead of the requested pnpm version, ensuring pnpm self-update results are honored (including when the requested version comes from packageManager in package.json).

Changes:

  • Adjust PATH setup ordering so the self-updated pnpm binary location takes precedence over the bootstrap binary location.
  • Parse packageManager: "pnpm@<version>" to extract an explicit target version for pnpm self-update.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/install-pnpm/run.ts
Comment on lines 126 to 128
if (typeof packageManager === 'string' && packageManager.startsWith('pnpm@')) {
return undefined
return packageManager.replace('pnpm@', '').split('+')[0]
}
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

readTargetVersion() now derives the version via packageManager.replace('pnpm@', '').split('+')[0]. For malformed values like "pnpm@" or "pnpm@+sha512...", this returns an empty string, which then causes runSelfInstaller() to skip self-update (because if (targetVersion) is falsey) and succeed using the bootstrap pnpm. Consider validating the extracted version (e.g., match ^pnpm@([^+]+) and ensure it’s non-empty after trimming) and throwing a clear error when the packageManager field is present but doesn’t contain a usable version.

Copilot uses AI. Check for mistakes.
Keep only the PATH ordering fix from the previous commit. The
packageManager field handling is a separate concern and needs more
discussion before being bundled with this fix.
@zkochan zkochan changed the title fix: respect requested pnpm version when bootstrap differs fix: pnpm self-update binary shadowed by bootstrap on PATH Apr 18, 2026
@zkochan
Copy link
Copy Markdown
Member

zkochan commented Apr 18, 2026

I will merge the fix related to PATH. I am not convinced the other change is needed. pnpm should be able to automatically switch versions.

The previous commit's dist/index.js was built with a stale
node_modules and didn't match a reproducible build, breaking the
check-dist CI job.
@zkochan zkochan merged commit 71c9247 into pnpm:master Apr 18, 2026
20 of 21 checks passed
zkochan added a commit that referenced this pull request Apr 18, 2026
The existing version tests only check output format via regex, which is
why the PATH-shadowing bug (#230) slipped through — the bootstrap pnpm's
version string matched the regex just as well as the requested version.

- test_version_respects_request: runs the action with `version: 9.15.5`
  and `version: 10.33.0` (both differ from the bootstrap) and asserts
  that `pnpm --version` matches exactly. Regression test for #225/#230.

- test_package_manager_field: writes a `packageManager: pnpm@<v>` entry
  into package.json, runs the action with no `version:` input, and
  asserts exact match. Reproduces #227; currently expected to fail
  since `packageManager` extraction was intentionally not added.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: self-updated pnpm binary shadowed by bootstrap due to PATH priority

4 participants