Implements a new yarn version - #682
Merged
Merged
Conversation
arcanis
added a commit
that referenced
this pull request
Jan 13, 2020
* Implements a new version of "yarn version" * Updates the documentation * Fixes tests
zkochan
added a commit
to pnpm/rfcs
that referenced
this pull request
Jul 12, 2026
- cite the 2019 request and the catalog change-detection gap in the motivation, and make the coverage check catalog-aware (a catalog entry change touches every package referencing it) - record Yarn's nextVersion-in-manifest rewrite (yarnpkg/berry#682) as a third case for per-change intent files, and lerna-lite's chase of pnpm-native semantics as an argument for the native approach - new open questions from the threads: rebase-i-style interactive UX, a conventional-commits bridge, and Lerna's two-phase atomic publish Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
zkochan
added a commit
to pnpm/rfcs
that referenced
this pull request
Jul 13, 2026
* RFC: Native monorepo versioning Propose built-in, changesets-file-format-compatible release management: recording change intents, workspace version bumping with dependent propagation and fixed/linked groups, changelog generation, and per-package prerelease lines (the capability changesets' global pre mode cannot express), configured in pnpm-workspace.yaml. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): registry-backed changelog storage mode Add a changelog.storage option: "repository" keeps the appended, committed CHANGELOG.md; "registry" commits only the newest release's section and composes the full history at publish time by extending the previously published tarball's changelog. Previous-version selection is semver-based so concurrent release lines chain on their own ancestry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): registry changelog mode commits no prose at all Reviewing the composed section in the release PR duplicates text already reviewed in the intent files. Instead of committing the newest section, keep the consumed intent files through the tag, track them in a small consumed-ids ledger, compose the section at publish time, and delete the files on the next version run. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): gate intent GC on registry-confirmed publication Before publish, the intent file is the only copy of the changelog prose in registry storage mode, so deletion must wait until the ledgered version is confirmed published — which also self-heals releases that were versioned and tagged but never published. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): registry changelog storage is the default, repository the opt-out Document the preconditions as opt-out guidance (foreign publishers, Renovate/Dependabot visibility via GitHub releases, byte-reproducibility for attested builds), harden intent GC to verify the published tarball actually contains the composed section, and have the migration codemod set repository mode when committed changelogs exist. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): committed changelogs duplicate git history The intent files' prose survives in git history after deletion, so a committed changelog records nothing the repository doesn't already hold; the browsability trade-off is a convenience, not a loss of information. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): adopt Yarn's diff-derived coverage check Add pnpm change check: every package touched by the branch diff must be named in a pending intent or explicitly declined via a none strategy (an additive extension to the changesets format), with ignore patterns for files that never warrant a release. Expand the Yarn prior-art entry and raise its transitive dependent-decision rule as an open question. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): adopt Rush's bump cap for maintenance branches Add versioning.maxBump (from Rush's lockedMajor version policy): a per-branch cap that makes a cherry-picked minor/major intent fail the version run on a patch-only maintenance branch instead of silently shipping a feature release. Credit rush change --verify as the original diff-derived coverage enforcement and expand the Rush prior-art entry. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): add Bit's soft tags to prior art Bit converges on recorded-intent versioning independently (soft tags persisted by CI), validating the file-per-intent format by counterexample (.bitmap conflicts on concurrent PRs) and the mechanical dependent propagation default (bit auto-tags dependents with an opt-out). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): learn from pnpm/pnpm#2225 and pnpm/pnpm#1098 - cite the 2019 request and the catalog change-detection gap in the motivation, and make the coverage check catalog-aware (a catalog entry change touches every package referencing it) - record Yarn's nextVersion-in-manifest rewrite (yarnpkg/berry#682) as a third case for per-change intent files, and lerna-lite's chase of pnpm-native semantics as an argument for the native approach - new open questions from the threads: rebase-i-style interactive UX, a conventional-commits bridge, and Lerna's two-phase atomic publish Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): reuse the changed-since filter machinery for the check pnpm change check needs no new configuration: the touched-package computation is the detection behind --filter="[<ref>]", and changed-files-ignore-pattern / test-pattern already express which files never warrant a release. Landing catalog-aware attribution in the shared machinery gives filtered builds and tests the same awareness. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): use -r/--filter instead of a --workspace flag pnpm has no --workspace convention for whole-workspace operations; the recursive form of pnpm version (bare, no bump argument) consumes pending intents, the explicit-bump form keeps its npm-style meaning, and --filter selects a subset of the pending plan (with fixed-group companions and invalidated dependents pulled in), enabling single-product releases from multi-product repositories. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): never rewrite dependency ranges; require workspace: protocol The version step touches only version fields. Internal dependencies must use the workspace: protocol, whose concrete ranges pnpm already materializes at pack time, so range-rewrite machinery doesn't exist here at all and dependent propagation derives from the protocol modifier (* → any bump, ~ → minor+, ^ → major) instead of range matching. Plain-range or catalog-declared internal deps fail loudly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): keep fixed and ignore, defer linked Explain what the grouping keys do and right-size them: fixed groups are a real need (pnpm ships pacquet + napi in lockstep); ignore shrinks to freezing releasable packages because auto-exclusion of versionless private packages covers changesets' main use case; linked is deferred — rare, surprising jump-to-highest semantics, purely additive later. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): add epics — version bands tied to a lead package Native support for the scheme pnpm's monorepo enforces via a meta-updater plugin: member majors live in the lead's major × 100 band (pnpm 11 → 1100-1199), move independently inside it (including their own breaking changes, unlike a fixed group), and re-base to the band floor when the lead reaches a new stable major, waiting out prerelease lines. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): epic membership uses package selectors, conflicts fail A name glob is the wrong membership primitive: pnpm's own repo hosts products outside the TS epic that share the @pnpm scope (@pnpm/napi, @pnpm/pnpr, @pnpm/pnpr.client). Epics select members with pnpm's existing --filter selector language (name globs, directory selectors, negations), and a package matched by an epic while belonging to a fixed group or prerelease line outside it is a configuration error, so an over-broad glob cannot silently re-base an unrelated product. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): absorb the release-branch ledger into the core lifecycle The consumed-intent ledger is mode-independent, not a registry-storage detail: pending intents are files whose id is not ledgered on any line, which natively absorbs the .changeset-released mechanism pnpm's repo built on top of changesets — cherry-picked intents release once per line, merge-backs cannot re-apply them, and merge-time file resurrection/deletion becomes harmless by construction. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): address review — materialized-range propagation, plan-level maxBump, per-package ledger - propagation evaluates the materialized semver range instead of a per-modifier rule, keeping 0.x caret semantics correct - maxBump is enforced on the final assembled plan (propagation, fixed groups, epic re-base can raise a bump above declared intents) - ledger consumption is scoped per package, with the explanation of why merge-carried entries cannot suppress a needed bump - the ledger is the single authoritative consumption record for half-consumed intents; deletion follows one rule in both storage modes - language identifiers on the command code fences Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): drop the pre enter/exit commands — prerelease-line membership is declared directly in pnpm-workspace.yaml Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): rename the prerelease-line commands to pnpm version stable/unstable The bare "pre" token sits in npm's bump-keyword slot, where it is itself a valid node-semver increment type, so a mode-toggling "pre enter/exit" sub-verb both reads oddly and shadows a real increment. stable/unstable name the state the packages move to. The commands remain convenience editors for versioning.prereleases in pnpm-workspace.yaml, which stays the reviewable source of truth. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): prerelease lines become release lanes under a root pnpm lane command Rename the concept to lanes (Bit's name for the same idea) and move the command out of pnpm version's bump-keyword slot to a root command: pnpm lane alpha --filter <pkg>... # move packages onto the alpha lane pnpm lane main --filter <pkg>... # return them to the main lane pnpm lane # show lane membership main is the reserved default lane, as in Bit. The config key becomes versioning.lanes and stays the reviewable source of truth; the command is a convenience editor for it. Freeing the word "line" also removes an overload — it now refers only to maintenance release lines (11.x). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): specify package identity as the project directory, names as aliases Two workspace projects can publish the same npm name — pnpm's own repo is heading there with the TS CLI (pnpm11/pnpm, 11.x) and the Rust CLI (pnpm/npm/pnpm, 12.x) releasing concurrently from one branch. Every serialized format gets a collision rule: intent files accept directory path references (the single additive extension to the changesets format), the ledger records the directory, versioning.lanes keys accept paths, and an ambiguous bare name is a listed-candidates error, never a silent pick. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): snapshots feed registry lanes; batch publish settles atomicity for capable registries Snapshot releases are the producer for the proposed bit-registry lanes (automatic branch publishing): snapshot with the branch name, --batch publish so the lane lands atomically, discard — nothing is consumed or ledgered, so nothing can double-release after merge. The stated hard requirement is registry-side isolation: lane versions must stay out of the main packument, or previous-version changelog chaining and ledger GC confirmation both misbehave. New unresolved questions: basing lane snapshots on the plan target instead of 0.0.0-*, and defaulting the dist-tag / registry lane to the versioning-lane name. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): move --snapshot from version to publish Snapshot is a publish concern: it mutates nothing durable, and the only work it needs — deriving target versions and rewriting version/workspace: fields — is a pack-time in-memory manifest transform, the same category exportable-manifest already owns. pnpm publish -r --snapshot calls the shared assembler and packs against the derived versions without dirtying the working tree, eliminating the version --snapshot -> publish -> git checkout dance. pnpm version -r is now strictly the durable half. The registry-lane flow collapses to one command: pnpm publish -r --batch --snapshot <branch>. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): trim registry-side prescriptions from the snapshot section The RFC is about the client half. Snapshots emit 0.0.0-* prereleases through the ordinary publish path with a dist-tag; ephemeral/branch distribution and retention of throwaway versions are the registry's concern and out of scope. Drop the 'versions must stay outside the main packument' isolation requirement (a single packument is fine) and the registry-lane unresolved questions; keep the client-side atomic-publish question. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * rfc(versioning): address review — multi-epic conflict validation, list pnpm change check - A package matched by two different epics (overlapping selectors) now fails validation naming the conflicting epics, closing the ambiguous- band gap the epic + fixed-group / epic + lane rules left open. - Add pnpm change check to the implementation CLI command list. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What's the problem this PR addresses?
The current implementation of the new
yarn versionworkflow causes a huge amount of merge conflicts and makes things hard to review, which goes against the express goal of the feature.Fixes #586
How did you fix it?
The workflow is the same, but the implementation is very different. Instead of storing the versions inside the
nextVersionfield, they are now stored inside a file within the.yarn/releasesfolder. Each branch will have its own file (we generate them with a random name, and reuse them by checking which file in.yarn/releasesgot created sincemaster).