Skip to content

fix(ci): packed consumer installs keep same-day dependency bumps on every Bun release - #6059

Merged
miguel-heygen merged 2 commits into
mainfrom
fix/bun-min-release-age-package-name
Oct 22, 2026
Merged

miguel-heygen merged 2 commits into
mainfrom
fix/bun-min-release-age-package-name

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

What

Packed consumer installs keep same-day dependency bumps working on every Bun release, and CI stops picking up a new Bun mid-day.

Why

installConsumer retries an install that Bun refused under --minimum-release-age, excluding the refused packages. It read the package name as the first quoted token of Bun's error. Bun 1.4.4 (released 2026-10-22) swapped the two tokens:

  • 1.4.3: No version matching "fake-dep" found for specifier "^1.1.0" (blocked by minimum-release-age: 86400 seconds)
  • 1.4.4: No version matching "^1.1.0" found for specifier "fake-dep" (blocked by minimum-release-age: 86400 seconds)

On 1.4.4 the retry excluded ^1.1.0, stayed blocked, and failed. verify-packed-manifests.test.mjs "installs a same-day dependency bump whose only matching version is an hour old" went red ("allowed: ^1.1.0"), so every PR's Test (support) fails from the first run that downloaded 1.4.4. A release's packed consumer install of any same-day dependency bump would fail the same way.

CI picked up 1.4.4 without a change in this repo because no setup-bun step pins a version, and with none given the action installs the latest release.

Related work

Supersedes the one-line flip in #6058, which made the release-age regex capture the second quoted token. That fits Bun 1.4.4's message order only, breaks on the other order, and leaves Bun unpinned. This PR pairs the tokens structurally (ageBlockedPackages), so either order works, and pins Bun with engines.bun. Rebased onto main with the conflict resolved in favour of ageBlockedPackages.

How

  • scripts/verify-packed-manifests.mjs: ageBlockedPackages(stderr) reads both quoted tokens and takes as the package the one that Bun's <name>@<range> failed to resolve line pairs with the other. Both versions print that line (captured from 1.4.3 and 1.4.4 against the test's fake registry). If no such line pairs the tokens, it returns null and the original install error is rethrown, so an unknown future format fails visibly instead of excluding the wrong name.
  • package.json: "engines": { "bun": "1.4.4" }. With no bun-version input, oven-sh/setup-bun at the pinned commit 0c5077e5 reads the root package.json (src/index.ts:27-29, packageManager bun@X or engines.bun, src/utils.ts:124), so this one field pins Bun for every setup-bun step that does not set a version. packageManager: "bun@..." would do the same for setup-bun but makes Corepack's pnpm refuse the repo, and CI and publish run corepack enable + pnpm from the root (ci.yml:325-326, publish.yml:119-120). canary-sunset.yml still asks for latest explicitly and is left as is.

Test plan

  • Unit tests added: ageBlockedPackages with both Bun message orders and a scoped name, plus two messages that must name nothing.
  • Red on main: with only the test file changed, the file fails to load (does not provide an export named 'ageBlockedPackages'); main's code under Bun 1.4.4 fails the same-day install test (allowed: ^1.1.0).
  • Green: node --test scripts/verify-packed-manifests.test.mjs 22/22, 3 runs each under Bun 1.4.4 and 1.4.3.
  • bun install --frozen-lockfile with the new engines field; corepack pnpm@10.17.1 --version from the repo root still runs; check:workspace-contracts, oxfmt --check, oxlint clean.
  • Documentation updated (if applicable): n/a
  • Comments follow CONTRIBUTING.md "Comments"

Size

Under 100 lines on purpose: it unblocks Test (support) on main for every open PR, so it ships alone rather than riding a larger change.

@github-actions

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 271 (base branch 271), smooth 155 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (0)

Unstable (1)

  • seqheldtwice-tlhold-px-r0-root-z100: tracking 120.32, pressJump 312.3, drop 0, reload 0, render 0.02, renderKey -, undo true, teleport false / tracking 0.08, pressJump 0.11, drop 0.35, reload 0.35, render 0.02, renderKey -, undo true, teleport true / tracking 0.08, pressJump 0.11, drop 0.35, reload 0.35, render 0.02, renderKey -, undo true, teleport true

@vanceingalls vanceingalls left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at 063e74ed (two commits on f5873b80).

What holds

  • The parser fixes the real failure, not only the test fixture. I ran bun install --minimum-release-age=86400 against a local fake registry under the released Bun 1.4.4 and 1.4.3 binaries. Three shapes were tested:

    • a fresh package pulled in through an old registry package;
    • two fresh packages (one scoped) pulled in through a file: tarball, which is the real packed consumer's shape;
    • the same two as direct dependencies.

    Both versions print the <name>@<range> failed to resolve line in every shape, including transitive ones, and only the quoted pair is swapped. ageBlockedPackages named exactly the blocked packages in all six runs, and installConsumer went on to finish the install each time.

  • It fails closed. If any match has no pairing line, it returns null and the original error is rethrown. A future format change can't turn into a wrong exclusion.

  • The Bun pin takes effect. At the pinned commit, oven-sh/setup-bun@0c5077e5 falls back to $GITHUB_WORKSPACE/package.json when no bun-version or file input is given (src/index.ts:27-29), reading packageManager bun@… first and then engines.bun (src/utils.ts:124). No setup-bun step in the repo sets a version except canary-sunset.yml (latest, as the body says), and none of them runs before checkout. The root package is private, so engines never ships.

  • Locally: under Bun 1.4.4, the ageBlockedPackages and packed consumer install suites pass 5/5.

Nit (non-blocking)

  • studio-drag-frames.yml checks out ${{ inputs.ref || 'main' }} before setup-bun, so a bench run against a ref older than this PR reads that ref's package.json and gets the latest Bun. It's a manual bench and not a gate, so it's fine as is. Worth knowing if a bench result ever moves along with a Bun release.

CI: green at 063e74ed. All 8 required checks pass (Build, Typecheck, Test, Test: runtime contract, Tests on windows-latest, Render on windows-latest, Semantic PR title, regression). Test (support), which runs the same-day install test, is green on this head under the newly pinned Bun.

Verdict: APPROVE
Reasoning: The parser now pairs the name with the range from Bun's own output and fails closed on anything else. I checked that pairing against the real 1.4.3 and 1.4.4 binaries, including transitive and scoped packages. The engines.bun pin is what the pinned setup-bun reads.

— Via

…very Bun release

Bun 1.4.4 swapped the quoted package and range in its minimum-release-age
error, so the retry excluded the range instead of the package and the
install failed again. The package is now the token that bun's
"<name>@<range> failed to resolve" line pairs with the other one, and an
unrecognised message fails visibly instead of excluding the wrong name.

CI installs the newest Bun when nothing pins it, which let the 1.4.4
release turn every PR's support tests red mid-day. engines.bun in the
root package.json pins it for every setup-bun step that does not set a
version (packageManager would make corepack's pnpm refuse the repo).
@miguel-heygen
miguel-heygen force-pushed the fix/bun-min-release-age-package-name branch from 063e74e to a9ec524 Compare October 22, 2026 11:07

@vanceingalls vanceingalls left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed at a9ec5247, which is the same two commits rebased onto 8d6ceb73. The push dropped my approval at 063e74ed (5613149370).

  • The content hasn't changed. scripts/verify-packed-manifests.mjs, its test and package.json have the same blob ids at a9ec5247 as at 063e74ed (fc6ea3a0, 06af0d7a, c332c9fc).
  • The rebase replaces #6058's flip. On main, #6058 (3a0caeeb) flipped BLOCKED_BY_AGE to capture the second token, which reads 1.4.4's order only. This PR swaps that for ageBlockedPackages, which pairs either order against the <name>@<range> failed to resolve line and fails closed. Everything I verified at 063e74ed still applies: the real 1.4.3/1.4.4 binaries, transitive, file:, scoped and multi-package blocks, and setup-bun reading engines.bun.

CI: green at a9ec5247. All 8 required checks pass in the first CI run on this head (39768186756 and its siblings), with Test (support) green on the pinned Bun. A second pull_request run on the same head skipped its jobs after Detect changes.

Verdict: APPROVE
Reasoning: This is a clean rebase with byte-identical files. The only change is that it now supersedes the one-direction flip that landed on main.

— Via

@miguel-heygen
miguel-heygen added this pull request to the merge queue Oct 22, 2026
Merged via the queue into main with commit 2faf660 Oct 22, 2026
115 checks passed
@miguel-heygen
miguel-heygen deleted the fix/bun-min-release-age-package-name branch October 22, 2026 11:43
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.

2 participants