Skip to content

test(install): run overrides.test.ts against the local registry - #39022

Open
robobun wants to merge 1 commit into
mainfrom
farm/41d1e44f/overrides-test-local-registry
Open

robobun wants to merge 1 commit into
mainfrom
farm/41d1e44f/overrides-test-local-registry

Conversation

@robobun

@robobun robobun commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator

Problem

  • test/cli/install/overrides.test.ts installed express@4.18.2 (68 packages) or lodash from the public npm registry in 6 of its 7 tests, then ran three more installs per test (install, --frozen-lockfile, --force; the last one re-fetches the tree).
  • It was the only file in test/cli/install not using the local registry. Build 97275 measured it at 26s on the Windows arm64 lane and between 0.4s and 3.3s elsewhere, the spread being network and cache warmth; setDefaultTimeout(5 minutes) at the top of the file hid that.
  • The install() helper inherited stdout/stderr, so nothing bun printed was asserted; each test checked one version field.
  • The frozen-lockfile test passed for the wrong reason: it changed the override to bytes@1.0.1, a version that does not exist on npm, so the non-zero exit it checked came from error: No version matching "1.0.1" found for specifier "bytes", not from the frozen-lockfile check (output below).
  • ensureLockfileDoesntChangeOnBunI read bun.lock only after an extra bun install, so a lockfile rewritten by that install would not have been noticed.

Fix

  • The file starts one VerdaccioRegistry in beforeAll and uses fixtures that already exist in test/cli/install/registry/packages, so no fixtures are added: no-deps (1.0.0, 1.0.1, 1.1.0, 2.0.0) plays bytes/lodash, one-dep (depends on no-deps@1.0.1) and one-range-dep (no-deps@^1.0.0) play express, a-dep is the npm: alias target and the package an override must leave alone.
  • All 7 scenarios are kept (direct dependency, transitive dependency through two parents, override added after the first install, npm: specifier, changed override vs --frozen-lockfile, override removed, workspaces) and run as test.concurrent. Each test owns its directory and its BUN_INSTALL_CACHE_DIR (CI exports that variable, so the per-test bunfig cache alone would leave concurrent tests sharing one cache).
  • Assertions, checked before the exit code:
    • stdout and stderr of the install under test as normalizeBunSnapshot inline snapshots (the two progress lines are stripped; their task count is not what the file tests).
    • The installed tree via the harness nodeModulesPackages, one snapshot per state, covering the overridden package and the packages that must not move (e.g. node_modules/no-deps/a-dep@1.0.1 next to node_modules/one-dep/one-dep@1.0.0).
    • The frozen-lockfile test now switches between two published versions and asserts the exact stderr (error: lockfile had changes, but lockfile is frozen plus the overrides in package.json changed since bun.lock was saved note), and that bun.lock and node_modules were left alone.
    • Removing the override resolves no-deps back to 1.0.1 (the version one-dep asks for) and drops "overrides" from bun.lock.
    • The workspace test asserts that node_modules/pkg1 is the 1.1.1 workspace and snapshots the whole bun.lock: pkg1@workspace:packages/pkg1, override recorded, no pkg2 entry.
  • expectLockfileStable captures the bun.lock text right after the install under test, then requires --frozen-lockfile to pass with empty stderr, a plain bun install to print nothing to stderr (no Saved lockfile), and the text to be unchanged (toBe on the text, so a failure prints a line diff). The --force step is dropped: it was the re-download, and the re-resolution it exercised is what the "set later" and "reset when removed" scenarios assert directly.
  • The 5 minute setDefaultTimeout is gone. The file is also removed from test/no-validate-leaksan.txt: it passes with the CI LeakSanitizer settings (BUN_DESTRUCT_VM_ON_EXIT=1, detect_leaks=1, test/leaksan.supp), and a LSAN_OPTIONS=verbosity=1 probe confirmed LSAN runs inside the spawned installs.
  • Why the small fixtures are enough: bun applies an override per dependency edge while enqueueing it (src/install/PackageManager/PackageManagerEnqueue.rs:709-747), so each scenario needs one package with several published versions plus a parent depending on it; the express tree only added network traffic.
  • Verified with bun bd test test/cli/install/overrides.test.ts: 7 pass, 26 snapshots. Timings on this machine (public registry reachable through a proxy):
run before after
bun bd test (debug, ASAN), cold install cache 19.9s, 21.4s 6.0s to 7.5s over 4 runs
bun bd test, warm install cache 15.9s n/a, the cache is per test
release bun, cold install cache 12.0s and 65.2s (one express download stalled for 56s) 1.9s
public registry unreachable (HTTP(S)_PROXY pointed at a closed port) 6 of 7 fail: ConnectionRefused downloading package manifest express 7 pass
  • About 3.4s of the debug "after" number is the fixed cost of any verdaccio-backed file (a one-test file that only starts the registry takes that long under the debug build); the tests themselves take 1s to 2s each, concurrently. On the lane where the old file hit a warm shared cache (0.4s on linux x64 in test/expected-durations.json) the new file will be somewhat slower because of that fixed cost; the gain is on cold or slow-network lanes, and in not depending on the network at all.

Background

  • VerdaccioRegistry (test/harness.ts) forks a verdaccio server on a random port that serves the packages checked in under test/cli/install/registry/packages. Its verdaccio.yaml has the npm uplink proxy commented out, so a package missing from that directory is a 404, never a network request. createTestDir makes a tempDir whose bunfig.toml points install.registry at the server and install.cache inside the directory.
  • overrides (npm) / resolutions (yarn) in the root package.json replace the version that every dependency edge to a given name asks for. bun applies them while enqueueing each dependency, skipping workspace edges and explicit npm: aliases, and writes them into bun.lock so that --frozen-lockfile can tell when they changed.
  • nodeModulesPackages(dir) from the harness lists every package.json found under node_modules as path/name@version, so one snapshot shows what each name resolved to and whether any nested copies were installed.
Frozen-lockfile test on main: resolution error, not a frozen-lockfile error
bun install v1.4.0-debug (732491c9f)
error: No version matching "1.0.1" found for specifier "bytes" (but package exists)
error: bytes@3.1.2 failed to resolve
(pass) changing overrides makes the lockfile changed, prevent frozen install
Old file with the public registry unreachable
error: ConnectionRefused downloading package manifest lodash
(fail) overrides affect your own packages
error: ConnectionRefused downloading package manifest express
(fail) overrides affects all dependencies
(fail) overrides being set later affects all dependencies
(fail) overrides to npm specifier
(fail) changing overrides makes the lockfile changed, prevent frozen install
(fail) overrides reset when removed
(pass) overrides do not apply to workspaces
 1 pass
 6 fail

The file installed express and lodash from the public npm registry, four
installs per test, hidden behind a 5 minute default timeout, and only
asserted exit codes and one version number. It now uses the verdaccio
fixtures (no-deps, one-dep, one-range-dep, a-dep), runs the seven scenarios
concurrently with a per-test install cache, and asserts the install output,
the installed tree, the frozen-lockfile error text, the workspace
resolution and lockfile stability on the bun.lock text.

The frozen-lockfile scenario previously changed the override to bytes@1.0.1,
a version that does not exist, so its non-zero exit came from a resolution
failure rather than from the frozen-lockfile check. It now switches between
two published versions and checks the frozen-lockfile error itself.

The file no longer needs its LeakSanitizer exemption.
@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@robobun, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 27 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: aa660d32-e9f0-4aed-931a-371685791943

📥 Commits

Reviewing files that changed from the base of the PR and between 732491c and b3f8d24.

📒 Files selected for processing (2)
  • test/cli/install/overrides.test.ts
  • test/no-validate-leaksan.txt

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

@robobun

robobun commented Aug 15, 2026 •

Copy link
Copy Markdown
Collaborator Author

Status: test-only change, ready for review.

  • Reproduced the network dependency locally: on main, bun bd test test/cli/install/overrides.test.ts takes 19.9s to 21.4s with a cold install cache (release bun: 12.0s and 65.2s, one express download stalled), and with the public registry unreachable 6 of its 7 tests fail with ConnectionRefused downloading package manifest express.
  • With this branch the same command passes in 5.8s to 7.5s across 10 runs (release bun: 1.9s), including with the public registry unreachable, and also passes with the CI LeakSanitizer settings, which is why the no-validate-leaksan.txt entry is dropped.

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM — test-only hermeticity refactor following the established VerdaccioRegistry pattern.

What was reviewed:

  • All 7 original scenarios are preserved with strictly stronger assertions (stdout/stderr/tree snapshots vs. a single version field); the frozen-lockfile test now asserts the actual frozen-lockfile error instead of a coincidental resolution failure.
  • Verified the referenced fixtures (no-deps 1.0.0/1.0.1/1.1.0/2.0.0, one-dep, one-range-dep, a-dep 1.0.1–1.0.10) exist in test/cli/install/registry/packages/ and that createTestDir/nodeModulesPackages in harness match the usage here.
  • test.concurrent isolation looks safe: each test gets its own tempDir and BUN_INSTALL_CACHE_DIR override, so concurrent installs don't share a cache even when CI exports that variable.
  • no-validate-leaksan.txt removal is a de-suppression (strictly safer); no production code touched.
Extended reasoning...

Overview

This PR rewrites test/cli/install/overrides.test.ts to use the local VerdaccioRegistry harness instead of hitting the public npm registry, and removes the file from test/no-validate-leaksan.txt. No production code is modified. All 7 existing test scenarios are kept, converted to test.concurrent, and re-expressed against small local fixtures (no-deps, one-dep, one-range-dep, a-dep) that already exist in the registry fixture directory. Assertions are upgraded from single version field reads to full stdout/stderr inline snapshots plus nodeModulesPackages tree snapshots, and the lockfile-stability helper now captures the lockfile before the follow-up install so a rewrite would actually be caught.

Security risks

None. This is a test-infrastructure change with no runtime, auth, crypto, or network-facing production code touched. It actually removes a public-network dependency from CI.

Level of scrutiny

Low-to-medium. Test-only, follows the exact pattern used by every other file in test/cli/install/ (VerdaccioRegistry + createTestDir + normalizeBunSnapshot + nodeModulesPackages). The main risks for a change like this are (a) losing coverage, (b) introducing flakiness via test.concurrent, or (c) snapshots that certify wrong behavior. I checked each: coverage is a strict superset (the frozen-lockfile test previously passed for the wrong reason and now asserts the real error message); concurrency is isolated per-test via separate tempDirs and an explicit BUN_INSTALL_CACHE_DIR override; and the snapshot contents in the diff match what the fixtures should produce (e.g. no-deps@1.0.0 under override, no-deps@1.0.1 when the override is removed since one-dep depends on 1.0.1).

Other factors

  • I verified the fixture packages and versions referenced in the PR exist on disk exactly as described.
  • The progressLine regex handles both LF and CRLF and is applied before normalizeBunSnapshot, so Windows output should normalize correctly.
  • Removing the file from no-validate-leaksan.txt re-enables LSAN for it — a de-suppression, so if it's wrong CI will simply flag it rather than hide anything.
  • The 5-minute setDefaultTimeout removal and dropping the --force re-download step are both justified in the PR description and consistent with the repo's test guidelines (default timeout, no public network).
  • No prior human reviews or outstanding comments on the PR.

@robobun

robobun commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator Author

Re-verified on main at d6af50f (633 commits after this branch's base). The file in this PR passes unchanged with bun bd test test/cli/install/overrides.test.ts: 7 pass, 26 snapshots, 4.0s and 4.3s over two runs. The file on main takes 7.8s and 8.1s on the same machine with a warm install cache, and 24.7s on the Windows arm64 lane in CI (test/expected-durations.json).

The failures on Buildkite build 98009 are in other files (bun-lock.test.ts, napi.test.ts, node cluster tests). The annotation marks each of them as flaky. #39403 carries this change as well, with lockfileVersion set to 1 for #38741.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant