fix(config/reader): don't warn when packageManager and devEngines.packageManager match#12287
Conversation
Code Review by Qodo
1. Unsanitized warning values
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughParses packageManager specifiers including semver build-metadata hashes and compares name, version, and hash to emit precise warnings only for true divergences between ChangesHash-aware packageManager conflict detection
Sequence DiagramsequenceDiagram
participant ConfigReader as Config Reader
participant Parser as parsePackageManager
participant Splitter as splitPackageManagerVersion
participant Detector as getPackageManagerConflictWarning
participant Warnings as warnings
ConfigReader->>Parser: parse legacy `packageManager` spec
Parser->>Splitter: split version and +hash
Splitter-->>Parser: return name, version, hash
ConfigReader->>Parser: parse `devEngines.packageManager` spec
ConfigReader->>Detector: pass legacyParsed, devEnginesParsed
Detector->>Detector: compare name, version, hash
alt identical name+version+hash
Detector-->>Warnings: no warning
else name mismatch
Detector-->>Warnings: "specify different package managers"
else version mismatch
Detector-->>Warnings: "specify different versions of pnpm"
else hash mismatch
Detector-->>Warnings: "different integrity hashes"
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Updates pnpm/config-reader to treat packageManager and devEngines.packageManager as identical when they pin the same PM version including the same integrity hash, and improves the resulting conflict warnings.
Changes:
- Preserve/compare the integrity hash (semver build metadata) when parsing
packageManagerreferences. - Emit more specific conflict warnings (different package manager vs different version vs different hash).
- Expand CLI/config-reader test coverage for the new warning behaviors.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| pnpm/test/packageManagerCheck.test.ts | Updates/adds CLI tests for new warning strings and hash-aware matching. |
| config/reader/test/index.ts | Adds config-reader tests covering hash-aware equality and the new specific warning messages. |
| config/reader/src/index.ts | Adds hash-aware parsing and introduces getPackageManagerConflictWarning to generate specific warnings. |
| .changeset/devengines-package-manager-same-hash.md | Documents the behavior change and its motivation for a patch release. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
PR Summary by QodoFix spurious packageManager/devEngines.packageManager warnings when hashes match WalkthroughsDescription• Parse and compare package manager version *and* integrity hash to avoid false conflict warnings. • Emit more specific conflict warnings for differing managers, versions, or contradictory hashes. • Add unit/integration tests and a changeset covering the new warning behavior. Diagramgraph TD
U["pnpm command"] --> R["getWantedPackageManager()"]
R --> A["parsePackageManager()"] --> S["splitPackageManagerVersion()"] --> W["getPackageManagerConflictWarning()"] --> O["warnings (or none)"]
R --> B["parseDevEnginesPackageManager()"] --> W
High-Level AssessmentThe following are alternative approaches to this PR: 1. Normalize both specs by stripping build metadata (hash)
2. Compare the raw strings for equality (no structured parse)
Recommendation: Keep the PR’s structured comparison (name + semver part + optional hash). It fixes the false-positive warning while preserving safety (warn on any divergence) and improves UX via specific diagnostics for manager/version/hash mismatches. File ChangesBug fix (1)
Tests (2)
Documentation (1)
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@config/reader/src/index.ts`:
- Around line 801-804: The split in parsePackageManager misparses scoped
package-manager specs like "`@scope/pm`@1.2.3" because packageManager.split('@')
splits at every '@'; change the logic in parsePackageManager to locate the last
'@' (or treat leading '@' specially) and split on that last occurrence so the
name retains the scope (e.g., "`@scope/pm`") and pmReference becomes the trailing
reference; update any comments referring to "pmReference is semantic versioning"
accordingly and ensure the returned shape ({ name, version, hash }) continues to
derive version/hash from the pmReference.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: eaa74afa-8c96-41ea-a649-d0c787352e16
📒 Files selected for processing (4)
.changeset/devengines-package-manager-same-hash.mdconfig/reader/src/index.tsconfig/reader/test/index.tspnpm/test/packageManagerCheck.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Compile & Lint
- GitHub Check: Analyze (javascript)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Use Standard Style with trailing commas, prefer functions over classes, declare functions after they are used (relying on hoisting), limit functions to no more than two or three arguments, and use a single options object for functions needing more parameters
Follow import order: standard libraries first, then external dependencies (sorted alphabetically), then relative imports
Do not write comments that restate what the code already says; rename variables, split helpers, or move checks to more obvious places instead
Do not repeat documentation at call sites that already lives on the callee; update the JSDoc once and let every call site benefit
Use JSDoc for the function's contract (preconditions, postconditions, edge cases, why the function exists), not for re-narrating the function body
Do not record past implementation shape, refactor history, or removed code in comments; use git log and git blame for that information instead
Write comments only when the reason for code is non-obvious, a hidden invariant exists, a workaround for a known bug is needed, or an exception to surrounding pattern is deliberate
Files:
config/reader/test/index.tsconfig/reader/src/index.tspnpm/test/packageManagerCheck.test.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Do not use
instanceof Errorfor checking if a caught error is an Error object in Jest tests; useutil.types.isNativeError()instead to work across realms
Files:
pnpm/test/packageManagerCheck.test.ts
🧠 Learnings (5)
📚 Learning: 2026-05-26T21:01:06.666Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11966
File: .changeset/require-tarball-integrity.md:6-6
Timestamp: 2026-05-26T21:01:06.666Z
Learning: In pnpm lockfile-related release notes/docs (especially changeset markdown), preserve URL hostnames exactly as they appear in pnpm-lock.yaml tarball resolution entries—keep hosts like `codeload.github.com`, `bitbucket.org`, and `gitlab.com` in lowercase. Do not “correct” them to title-case/preserve brand capitalization (e.g., LanguageTool rules like `GITHUB` capitalization) because these are literal URL fragments, not platform brand names.
Applied to files:
.changeset/devengines-package-manager-same-hash.md
📚 Learning: 2026-05-14T09:04:00.133Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11622
File: resolving/npm-resolver/test/publishedBy.test.ts:350-354
Timestamp: 2026-05-14T09:04:00.133Z
Learning: In the pnpm/pnpm repository, ESLint is the authoritative style linter. Do not raise review findings for missing trailing commas in multiline function calls (e.g., `fs.writeFileSync(...)`) when this repo’s ESLint configuration does not report them and lint passes. Prefer deferring to the ESLint results for this specific trailing-comma rule rather than enforcing it manually in code review.
Applied to files:
config/reader/test/index.tsconfig/reader/src/index.tspnpm/test/packageManagerCheck.test.ts
📚 Learning: 2026-06-05T13:47:05.929Z
Learnt from: vsumner
Repo: pnpm/pnpm PR: 12190
File: installing/deps-installer/test/install/frozenStore.ts:2-17
Timestamp: 2026-06-05T13:47:05.929Z
Learning: In the pnpm/pnpm repository, the shared Jest preset keeps `injectGlobals` at its default (`true`), so `test` and `expect` are available as Jest globals. Therefore, reviewers should not flag (or treat as TypeScript/compilation errors) missing `import { test, expect } from 'jest/globals'` when a test file uses `test`/`expect` without importing them. Importing from `jest/globals` may still be used for consistency with sibling files, but it is not required for execution in this repo unless a Jest preset is explicitly configured with `injectGlobals: false`.
Applied to files:
config/reader/test/index.tspnpm/test/packageManagerCheck.test.ts
📚 Learning: 2026-06-05T13:47:26.046Z
Learnt from: vsumner
Repo: pnpm/pnpm PR: 12190
File: installing/deps-installer/src/install/index.ts:2337-2343
Timestamp: 2026-06-05T13:47:26.046Z
Learning: In the pnpm/pnpm codebase, `PnpmError` automatically prefixes `err.code` with `ERR_PNPM_` when you pass a code that does not already start with `ERR_PNPM_` (it normalizes `this.code` via `code.startsWith('ERR_PNPM_') ? code : `ERR_PNPM_${code}``). Therefore, during code review you should NOT flag `new PnpmError(...)` call sites for passing a bare error code (e.g., `new PnpmError('FROZEN_STORE_INCOMPATIBLE_WITH_PNPR', ...)`); the resulting `err.code` will still be `ERR_PNPM_FROZEN_STORE_INCOMPATIBLE_WITH_PNPR`.
Applied to files:
config/reader/test/index.tsconfig/reader/src/index.tspnpm/test/packageManagerCheck.test.ts
📚 Learning: 2026-05-24T08:18:00.622Z
Learnt from: zkochan
Repo: pnpm/pnpm PR: 11895
File: pnpm/test/deploy.ts:91-95
Timestamp: 2026-05-24T08:18:00.622Z
Learning: In pnpm/pnpm integration tests that intentionally hit the real npm registry (registry.npmjs.org)—for example when the test passes `--config.registry=https://registry.npmjs.org/` to `execPnpm` and simply increases the timeout—do not request adding a runtime environment-variable gate (e.g., `PNPM_RUN_PUBLIC_REGISTRY_TESTS`). This is the established pattern for those tests (see files like `pnpm/test/install/pacquet.ts` and `pnpm/test/deploy.ts`).
Applied to files:
pnpm/test/packageManagerCheck.test.ts
🔇 Additional comments (3)
.changeset/devengines-package-manager-same-hash.md (1)
1-9: LGTM!config/reader/test/index.ts (1)
210-271: LGTM!pnpm/test/packageManagerCheck.test.ts (1)
509-565: LGTM!Also applies to: 581-583, 599-601
3301ab5 to
f782957
Compare
|
Code review by qodo was updated up to the latest commit f782957 |
f782957 to
7010003
Compare
|
Code review by qodo was updated up to the latest commit 7010003 |
7010003 to
f363f62
Compare
|
Code review by qodo was updated up to the latest commit f363f62 |
The conflict warning between the legacy "packageManager" field and "devEngines.packageManager" fired even when both pinned the same package manager at the same version, because the integrity hash was stripped from the legacy field but not from devEngines, so identical specifications compared unequal. Parse the hash out of both sides and compare the semver parts plus the hashes: keeping the two fields in sync, hash included, is now quiet, while two contradictory hashes for the same version are still reported. Each conflict now also names its specific cause — a different package manager, a different version, or contradictory integrity hashes — instead of a single generic message. Closes pnpm#12028 Signed-off-by: C. Spencer Beggs <spencer@beggs.codes>
f363f62 to
d784ac7
Compare
|
Code review by qodo was updated up to the latest commit d784ac7 |
…flict warnings The legacy "packageManager" and "devEngines.packageManager" conflict warnings interpolate package.json-controlled name and version values into text printed to the terminal. Strip ANSI escape sequences and other control characters first so a malicious manifest cannot forge or rewrite terminal/CI log output. Signed-off-by: Zoltan Kochan <z@kochan.io>
|
Code review by qodo was updated up to the latest commit 125c2e5 |
|
Congrats on merging your first pull request! 🎉🎉🎉 |
When
package.jsonsets bothpackageManageranddevEngines.packageManagerto the same pnpm version with the same integrity hash pnpm prints a spurious warning on every command. For example, apackage.jsonfile that looks like:{ "packageManager": "pnpm@11.5.1+sha512.93f7b57422ea7068257235b4c16eb60762eb68e1dc23723199cc739043ea9be2c4143274a399d8c6defa2b1176226d9ca1c4b63482d6200c1a8fbaa78c1d1485", "devEngines": { "packageManager": { "name": "pnpm", "version": "11.5.1+sha512.93f7b57422ea7068257235b4c16eb60762eb68e1dc23723199cc739043ea9be2c4143274a399d8c6defa2b1176226d9ca1c4b63482d6200c1a8fbaa78c1d1485", "onFail": "ignore" }, "runtime": [ { "name": "node", "version": "26.3.0", "onFail": "ignore" } ] } }Issues a warning on every
pnpmcommand:Root cause
getWantedPackageManagercompares the two fields to decide whether to warn, but the two sides were normalized differently:parsePackageManagerstrips the integrity hash from the legacypackageManagerfield →11.5.1devEngines.packageManagerversion was compared with its hash intact →11.5.1+sha512.93f7b57…So,
"11.5.1" !== "11.5.1+sha512…"was always true and the warning fired, even for identical specs. An earlier fix in #11307 only suppressed the warning when neither side carried a hash.Fix
parsePackageManagernow also returns the hash (via a sharedsplitPackageManagerVersion), andgetPackageManagerConflictWarningcompares the fields structurally. The warning is suppressed only when the two specifiers are identical (name + version + hash, both-absent counts as equal):A hash on only one side is still a divergence — dropping the ignored
packageManagerfield would lose that hash — so it warns with the original generic message. Two contradictory hashes for one version (a likely wrong-hash mistake) get a dedicated message. The generic single message is otherwise replaced by one tailored to each conflict, each ending with"packageManager" will be ignored.Closes #12028.
Summary by CodeRabbit
Bug Fixes
packageManageranddevEngines.packageManagerspecify the same manager, version, and integrity hash.Tests
Documentation