fix(semantic-release-pnpm): bump the version without invoking npm - #403
Conversation
On pnpm >= 10 `prepare` bumped the version by shelling out to
`npm pkg set version=…`. npm >= 10.9 validates `devEngines` on every
invocation, so a package declaring
`devEngines.packageManager: { name: "pnpm", onFail: "error" }` — the
standard way to enforce pnpm — made that call exit with EBADDEVENGINES.
`prepare` aborted, `publish` never ran, and nothing was released.
Write the manifest directly instead: read it with `readJson` (BOM-safe,
and it names the file on malformed input), set `version`, and write it
back preserving indentation, trailing newline and CRLF line endings.
`pnpm version` stays in place on pnpm < 10 for its side-effects; on
pnpm >= 10 the `preversion`/`version`/`postversion` lifecycle scripts do
not run, as was already the case with `npm pkg set`.
Known limits of the direct write, unchanged behaviour otherwise: a
symlinked `package.json` is replaced rather than followed, the file mode
is not preserved, and a mixed-EOL manifest normalises to its majority
line ending.
Fixes #375
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MqVjBDe8SkgMK7LpDpgjJ7
|
Warning Review limit reached
Next review available in: 58 minutes Limit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?Wait for the limit to reset, then comment An organization admin can change what happens after included review limits in Billing. How do review limits work?CodeRabbit enforces per-developer PR review limits within each organization. For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (14)
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthrough
Changespnpm prepare versioning
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to The change is narrowly scoped to version handling and includes focused regression coverage; no actionable merge-blocking risk remains beyond normal checks and review. Sequence Diagram(s)sequenceDiagram
participant SemanticRelease
participant prepare
participant PackageManifest
participant pnpm
SemanticRelease->>prepare: prepare(version, pluginConfig)
alt pnpm v10+
prepare->>PackageManifest: load and update package.json
PackageManifest-->>prepare: preserve BOM and line endings
else pnpm below v10
prepare->>pnpm: version version --no-git-tag-version --allow-same-version
pnpm-->>prepare: return command output
end
prepare-->>SemanticRelease: complete version preparation
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
📝 Generate docstrings
🧪 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 |
|
Thank you for following the naming conventions! 🙏 |
…e pass The version bump wrote `package.json` twice on CRLF manifests: once via `writeJson`, which always emits LF, then again to restore the line endings. Between the two writes the manifest sat on disk with the wrong line endings, and it cost an extra read and write per release. Serialize the manifest ourselves instead — `detect-indent` for the indentation, the detected EOL for the line endings, the trailing newline only if the original had one — and write the result exactly once. Adds `detect-indent` (catalog:prod), already used by `multi-semantic-release` for the same purpose. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MqVjBDe8SkgMK7LpDpgjJ7
Three packages each had their own "write a manifest back preserving its
formatting" code, and two of them rewrote a CRLF manifest as LF:
- multi-semantic-release kept indent and trailing newline via
recognizeFormat, but serialized the body with LF;
- semantic-release-clean-package-json kept only the indent, through
writeJson({ detectIndent: true });
- semantic-release-pnpm kept indent, trailing newline and line endings.
Move the pnpm behaviour into shared/serialize-manifest.ts and use it in
all three. The folder is plain source that packem inlines into each
package at build time, so nothing new is published; the packages keep
declaring detect-indent and @visulima/fs themselves, and the root
manifest declares them too so the shared file type-checks in place.
recognizeFormat and the FileFormat/RecognizeFormatFunction types go
away with their only caller, as does the detect-newline dependency.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MqVjBDe8SkgMK7LpDpgjJ7
…pare-single-write
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #403 +/- ##
==========================================
- Coverage 86.67% 86.04% -0.63%
==========================================
Files 47 44 -3
Lines 1426 1362 -64
Branches 387 371 -16
==========================================
- Hits 1236 1172 -64
- Misses 178 179 +1
+ Partials 12 11 -1
🚀 New features to boost your workflow:
|
…izer refactor: serialize manifests through one shared helper
refactor(semantic-release-pnpm): write the bumped manifest in a single pass
@anolilab/multi-semantic-release
@anolilab/rc
@anolilab/semantic-release-clean-package-json
@anolilab/semantic-release-pnpm
@anolilab/semantic-release-preset
commit: |
Fixes #375.
Problem
On pnpm >= 10 the
preparestep bumped the version by shelling out tonpm pkg set version=…. npm >= 10.9 validatesdevEngineson every invocation, so a package declaring{ "devEngines": { "packageManager": { "name": "pnpm", "onFail": "error" } } }made that call exit with
EBADDEVENGINES.prepareaborted,publishnever ran, and nothing was released — for exactly the projects this plugin exists for.Fix
preparewrites the manifest itself on pnpm >= 10: read withreadJson, setversion, write back. No package manager binary is involved in the version bump any more (verified by the test assertingexecais never called on that path).Formatting is preserved as
npm pkg setdid it: indentation (writeJson({ detectIndent: true })), trailing newline, and CRLF line endings (restored via@visulima/fs/eol).readJsonrather thanJSON.parsealso means a BOM-prefixed manifest still parses, and a malformed manifest reports which file is broken — both of which the raw-JSON.parseversion I first wrote got wrong.pnpm versionstays in place on pnpm < 10 for its side-effects (npm-shrinkwrap sync, version lifecycle scripts). On pnpm >= 10 thepreversion/version/postversionscripts do not run — that was already true withnpm pkg set, it is now documented in the JSDoc.Tests
__tests__/unit/prepare.test.ts, 11 tests, all passing; full package unit suite 96/96.New coverage: no shell-out on v10+ with a
devEngines-enforcing manifest (the regression guard), BOM manifest, malformed manifest naming the file,pkgRoot. Duplicate v9/v10 scenarios were merged and the repeated context literal pulled into arunPreparehelper.Known limits of the direct write
Behaviour that differs from in-place
npm pkg set, all judged acceptable and none of them new failure modes for normal setups:package.jsonis replaced rather than followed (the temp-file + rename write);Reviewed but not done
pnpm versionbranch entirely. It would delete the fork, but pnpm < 10 users would silently lose the version lifecycle scripts. Out of scope for a bug fix.multi-semantic-releaseandsemantic-release-clean-package-jsoneach have their own; the latter has no EOL handling and still clobbers CRLF manifests. Worth its own issue rather than a cross-package refactor here.detect-indentto this package to build the output in one pass. Each write is atomic on its own, so the extra pass buys correctness nothing.🤖 Generated with Claude Code
https://claude.ai/code/session_01MqVjBDe8SkgMK7LpDpgjJ7
Summary by CodeRabbit
New Features
Bug Fixes