发布

  • fix(core): degrade cooldown-blocked dist-tags within their own channel (#35967)

    frostbyte_neo 发布于 2026-06-11 20:48:14 +00:00

    Current Behavior

    When a package manager's minimum-release-age (cooldown) policy is
    active, nx migrate resolves dist-tags through per-package-manager
    emulation, and degrading a too-new tag produced inconsistent, often
    nonsensical results. nx migrate next could resolve to an internal
    pr.* preview build or a years-old release candidate; the npm path
    diverged from what npm itself installs; and yarn errored outright. Each
    of npm, pnpm, yarn, and bun carried its own tag-degrade implementation.

    Expected Behavior

    Dist-tag degrade is unified into a single rule across all four package
    managers. When the resolved tag target is within the cooldown window,
    the candidate pool is every version at or below it that is stable, in
    the target's own prerelease channel, or on a lower rung of an explicit
    channel ladder (alpha < beta < rc). That pool is ordered, and the
    first compliant version wins:

    • Prereleases of the target's exact major.minor.patch come first — own
      channel, then lower ladder rungs.
    • Then everything else, ordered by most recently published.

    So latest (or any stable tag) lands on the newest compliant stable. A
    prerelease tag keeps a compliant prerelease of the release it points at:
    every same-line release candidate is exhausted first, and a blocked
    rc.0 with no older rc sibling falls to a same-line beta.x rather
    than skipping back to the previous stable. A newer-published cross-line
    backport can't outrank the same-line beta, and the degrade never climbs
    the ladder upward. Channels with no place on the ladder (such as the
    internal pr builds, or canary) stay walled off entirely. next is
    deliberately left off the ladder: it is pre-rc in some ecosystems
    (Angular) but a rolling dev snapshot in others — exactly the class of
    build a degrade must never land on. The channel is derived generically
    from a version's prerelease identifier, so it works for any package's
    naming convention.

    Implementation Details

    A shared degradeTagToCompliant helper replaces npm's <=tagTarget
    recursion, pnpm's same-major degrade (and its deprecation tie-break
    machinery), yarn's latest-only walk-down, and bun's channel walk. It
    builds the pool, orders it (same-line own-channel, then same-line
    lower-rung, then by publish date), and returns the first version that
    passes the caller's maturity test; each package manager supplies only
    that test and its own violation shape. The helper guards against
    non-semver dist-tag targets and registry version entries
    (semver.compare previously threw, and the migrate consumer swallows
    unknown errors into a real-install fallback).

    The cleanup also drops the now-dead latestTagDegrade behavior axis and
    the redundant pnpm 10.20 behavior row, along with the tests that pinned
    the old version-specific behavior. The npm policy-reader specs are
    isolated from the host's real ~/.npmrc and reuse the real .npmrc
    parser (parseNpmrcContent) instead of a hand-copied mirror, and npm's
    tag-path ENOVERSIONS branch is now covered.


    View session information


    Co-authored-by: FrozenPandaz jasonjean1993@gmail.com

    下载附件