Skip to content

feat: support devEngines.packageManager for pnpm version management#10932

Merged
zkochan merged 6 commits intomainfrom
dev-engines-pm
Mar 11, 2026
Merged

feat: support devEngines.packageManager for pnpm version management#10932
zkochan merged 6 commits intomainfrom
dev-engines-pm

Conversation

@zkochan
Copy link
Copy Markdown
Member

@zkochan zkochan commented Mar 11, 2026

Summary

  • Support specifying the pnpm version via devEngines.packageManager in package.json, as an alternative to the packageManager field
  • Unlike packageManager, devEngines.packageManager supports semver ranges — the resolved version is stored in pnpm-lock.env.yaml and reused if it still satisfies the range
  • The onFail field determines behavior: download (auto-download), error (default), warn, or ignore
  • devEngines.packageManager takes precedence over packageManager when both are present (with a warning)
  • For array notation, default onFail is ignore for non-last elements and error for the last
  • For the legacy packageManager field, onFail is derived from existing config settings (managePackageManagerVersions, packageManagerStrict, packageManagerStrictVersion), so main.ts uses onFail as the single source of truth
  • Reuses EngineDependency type from @pnpm/types instead of a custom WantedPackageManager type

Test plan

  • 10 tests in switchingVersions.test.ts — version switching with packageManager field, devEngines.packageManager with onFail=download (exact + range), env lockfile reuse, corrupt binary
  • 15 tests in packageManagerCheck.test.ts — version checks with engines.pnpm, packageManager field, devEngines.packageManager with all onFail values, array notation, range matching, precedence

close #8153

Support specifying the pnpm version via `devEngines.packageManager` in
`package.json`. Unlike the `packageManager` field, this supports version
ranges. The `onFail` field determines behavior on mismatch:
- `download`: auto-download the matching pnpm version
- `error`: fail with an error (default for single entry, last array element)
- `warn`: warn but continue
- `ignore`: skip check (default for non-last array elements)

When both `packageManager` and `devEngines.packageManager` are present,
`devEngines.packageManager` takes precedence and a warning is emitted.

The resolved version is stored in `pnpm-lock.env.yaml` and reused if it
still satisfies the range.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 11, 2026 14:03
@zkochan zkochan added this to the v11.0 milestone Mar 11, 2026
Copy link
Copy Markdown
Contributor

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

Adds support for managing the pnpm CLI version via devEngines.packageManager (including semver ranges) and unifies package-manager enforcement/switching behavior through an onFail policy shared between pnpm and @pnpm/config.

Changes:

  • Parse devEngines.packageManager (incl. array form) and prefer it over packageManager, emitting warnings and deriving onFail for legacy packageManager.
  • Update CLI startup logic to use onFail as the single source of truth for switching (download) vs. checking (error/warn/ignore), and allow semver ranges for pnpm version switching.
  • Expand test coverage for devEngines-based switching and checking; add semver dependency to @pnpm/config.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
pnpm/test/switchingVersions.test.ts Updates existing switching tests and adds devEngines-based version switching/range reuse scenarios.
pnpm/test/packageManagerCheck.test.ts Adds devEngines onFail behavior tests and precedence over packageManager.
pnpm/src/switchCliVersion.ts Resolves exact pnpm version from ranges via env lockfile and switches accordingly.
pnpm/src/main.ts Routes switching/checking decisions through wantedPackageManager.onFail and uses semver range matching.
config/config/src/index.ts Introduces getWantedPackageManager() + devEngines parsing; derives legacy packageManager onFail.
config/config/src/Config.ts Replaces WantedPackageManager with EngineDependency for wantedPackageManager.
config/config/package.json Adds semver + @types/semver deps for version/range validation.
pnpm-lock.yaml Lockfile updates reflecting new semver dependencies.
.changeset/dev-engines-package-manager.md Changeset documenting the new devEngines packageManager support.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

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

zkochan and others added 3 commits March 11, 2026 15:26
- Add explicit type annotation for pmEngine variable
- Close store controller on early return when version resolution fails
- Expand version mismatch hint to mention devEngines.packageManager.onFail
- Assert non-zero exit status in onFail=error test

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
`self-update` is an explicit user command, so it should always update the
`packageManager` field when it points to pnpm, regardless of
`managePackageManagerVersions` (which only controls automatic version switching).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a project uses devEngines.packageManager instead of packageManager,
pnpm self-update now updates that field (both object and array forms)
rather than incorrectly writing to packageManager.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ockfile writes

- Add skipPackageManagerCheck = true so self-update is not blocked by
  BAD_PM_VERSION when the project specifies a different pnpm version
- Only call resolvePackageManagerIntegrities for devEngines.packageManager
  (ranges need a lockfile); packageManager field doesn't need it

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@zkochan zkochan requested a review from Copilot March 11, 2026 16:54
@zkochan zkochan changed the title feat: support devEngines.packageManager for pnpm version management feat: support devEngines.packageManager for pnpm version management Mar 11, 2026
Copy link
Copy Markdown
Contributor

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

Copilot reviewed 13 out of 14 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

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

You can also share your feedback on Copilot code review. Take the survey.

- Add early return in parseDevEnginesPackageManager when array is empty
  to avoid accessing engines[0] / engines[-1] on an empty array
- Fix misleading JSDoc in updateVersionConstraint: complex ranges that
  no longer satisfy the new version fall back to ^<newVersion>, not
  "left unchanged"

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@zkochan zkochan merged commit bb17724 into main Mar 11, 2026
13 checks passed
@zkochan zkochan deleted the dev-engines-pm branch March 11, 2026 17:49
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.

Support devEngines field

2 participants