Skip to content

refactor: serialize manifests through one shared helper - #405

Merged
prisis merged 2 commits into
fix/pnpm-prepare-single-writefrom
refactor/shared-manifest-serializer
Aug 20, 2026
Merged

refactor: serialize manifests through one shared helper#405
prisis merged 2 commits into
fix/pnpm-prepare-single-writefrom
refactor/shared-manifest-serializer

Conversation

@prisis

@prisis prisis commented Aug 19, 2026

Copy link
Copy Markdown
Member

Follow-up to #403 and #404based on #404's branch, so review it last; the base retargets automatically as those land.

Problem

Three packages each had their own "write a manifest back preserving its formatting" code, and two of them rewrote a CRLF manifest as LF — a whole-file diff in a release commit:

package indent trailing newline line endings
multi-semantic-release (recognizeFormat + writeFileSync) ❌ LF
semantic-release-clean-package-json (writeJson({ detectIndent: true })) ❌ LF
semantic-release-pnpm (after #404)

Three implementations meant fixing one fixed none of the others.

Fix

shared/serialize-manifest.ts holds the pnpm behaviour as a pure function — manifest in, string out — and all three packages call it. No new npm package: the folder is plain source that packem inlines into each dist at build time (verified: serializeManifest appears in the bundle of all three, with detect-indent and @visulima/fs/eol staying external).

Being pure also makes it usable from multi-semantic-release's synchronous updateManifestDeps, which the async writeJson-based approach could not be.

Fallout:

  • recognizeFormat, its test, and the FileFormat / RecognizeFormatFunction types go with their only caller, as does the detect-newline dependency.
  • detect-indent is added to semantic-release-clean-package-json (the other two already had it). Each package keeps declaring what the inlined code imports.
  • The root manifest gains detect-indent and @visulima/fs so the shared file resolves its own imports under pnpm's isolated node_modules — without them tsc --noEmit fails on shared/serialize-manifest.ts.
  • lint:prettier:root now also checks shared/*.ts. ESLint runs per package and does not reach the folder.

Behaviour change

multi-semantic-release previously appended the file's dominant newline whether or not the original ended with one; it now appends one only if the original did. That is the point of the helper — leave the file as it was found.

Tests

  • packages/multi-semantic-release/__tests__/utils/serialize-manifest.test.ts — 8 cases covering indent, trailing newline, CRLF/LF and the no-original fallback. It replaces recognize-format.test.ts and covers the helper on behalf of all three packages, since the folder has no test project of its own.
  • semantic-release-clean-package-json gains a CRLF round-trip test over publish — it fails on the old writeJson path.
  • update-deps.test.ts 101/101, serialize-manifest 8/8, clean-package-json 6/6, semantic-release-pnpm 12/12. tsc --noEmit clean in all three; all three build.

multi-semantic-release.test.ts (23) and bin/cli.test.ts (2) fail in my sandbox — the fixture repos die on git fetch --tags with "couldn't find remote ref HEAD". I re-ran them against the base commit with the base dependency set: identical 23 failures, so they are environmental and not from this change.

🤖 Generated with Claude Code

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
@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: de529af7-18f4-4bce-9df3-721781706364

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

Thank you for following the naming conventions! 🙏

@codecov

codecov Bot commented Aug 19, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.04%. Comparing base (cc3f5c1) to head (10ae82e).

Additional details and impacted files
@@                        Coverage Diff                        @@
##           fix/pnpm-prepare-single-write     #405      +/-   ##
=================================================================
+ Coverage                          84.37%   86.04%   +1.67%     
=================================================================
  Files                                 21       44      +23     
  Lines                                448     1362     +914     
  Branches                             108      356     +248     
=================================================================
+ Hits                                 378     1172     +794     
- Misses                                69      178     +109     
- Partials                               1       12      +11     
Flag Coverage Δ
multi-semantic-release 87.64% <100.00%> (?)
semantic-release-clean-package-json 77.27% <100.00%> (?)
semantic-release-pnpm 84.30% <100.00%> (-0.08%) ⬇️
Files with missing lines Coverage Δ
packages/multi-semantic-release/src/update-deps.ts 90.38% <100.00%> (ø)
...s/semantic-release-clean-package-json/src/index.ts 97.36% <100.00%> (ø)
packages/semantic-release-pnpm/src/prepare.ts 100.00% <100.00%> (ø)

... and 21 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@prisis
prisis merged commit 5ba5c46 into fix/pnpm-prepare-single-write Aug 20, 2026
20 of 21 checks passed
@prisis
prisis deleted the refactor/shared-manifest-serializer branch August 20, 2026 07:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant