Skip to content

Implements a new yarn version - #682

Merged
arcanis merged 3 commits into
masterfrom
mael/version-2
Jan 12, 2020
Merged

Implements a new yarn version#682
arcanis merged 3 commits into
masterfrom
mael/version-2

Conversation

@arcanis

@arcanis arcanis commented Jan 12, 2020

Copy link
Copy Markdown
Member

What's the problem this PR addresses?

The current implementation of the new yarn version workflow 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 nextVersion field, they are now stored inside a file within the .yarn/releases folder. Each branch will have its own file (we generate them with a random name, and reuse them by checking which file in .yarn/releases got created since master).

@arcanis
arcanis merged commit a49673a into master Jan 12, 2020
arcanis added a commit that referenced this pull request Jan 13, 2020
* Implements a new version of "yarn version"

* Updates the documentation

* Fixes tests
@arcanis
arcanis deleted the mael/version-2 branch January 17, 2020 11:06
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>
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.

[Feature] Improve how future releases numbers are stored

1 participant