test(install): give each long-label bun patch test its own install cache
Problem
test/cli/install/bun-patch.test.tsfails on main on the Windows lanes (x64 and aarch64), in thepackages whose label is longer than 1024 bytesblock added by #37469: thebun installstep exits 1, asexpect(exitCode).toBe(0)atinstall()(builds 94812, 94844; about half of the runs, so it usually passes on a retry and fails outright on PRs whose retries all lose).- The child's stderr is one of
error: failed to verify cache dir for "bar": ENOENT,ENOENT: failed opening cache/package/version dir for package barorENOENT: failed copying files from cache to destination for package bar. - Cause: the three tests are
test.concurrent, and two of them installbarfrom the identical spec. They spawn with plainbunEnv, so in CI they inherit theBUN_INSTALL_CACHE_DIRthe test runner exports (scripts/runner.node.mjs), whichfetch_cache_directory_path(src/install/PackageManager/PackageManagerDirectories.rs:379) consults before theinstall.cachethatcreateTestDirwrites tobunfig.toml. So both installs extract and publish the same cache entry (@T@<hash of the spec>) into one shared cache at the same time. - On Windows the install that publishes second cannot rename over the existing entry, and the retry arm in
move_to_cache_directory(src/install/extract_tarball.rs:576) moves the first install's entry out of the cache and deletes it before publishing its own, while the first install is still opening or copying from it. The first install exits 1 with one of the messages above. This is #28062 (fix in flight in #33884); the POSIX arm swaps atomically, which is why only the Windows lanes see this.
Fix
VerdaccioRegistry.createTestDir()now also returnsenv:bunEnvplusBUN_INSTALL_CACHE_DIRpointing at the same<project>/.bun-cacheit already writes tobunfig.toml. The long-label tests run every command (install,patch,patch --commit) with their project'senv, so the two installs no longer share a cache and have nothing to race on.- This is the right layer for this failure: the test is about formatting labels longer than the stack buffers and nothing about it needs two projects to share a cache. The bun commands and their arguments are unchanged, so the code paths #37469 covers are exercised exactly as before.
- Returning the env from the harness rather than pinning it in this file: the harness already intends per-project caches (that is what it writes to
bunfig.toml), and the same re-pin is currently copied by hand inbun-workspaces.test.ts,bun-install-lifecycle-scripts.test.ts,bun-install-registry.test.ts,bun-install-native-binlink.test.tsandisolated-install.test.ts; the othercreateTestDircallers are unaffected by the extra property (they destructure or readpackageDir/packageJson) and can switch over when they go concurrent. Those existing copies are left alone here to keep this a small fix for the red lane. - The install's stderr is attached to the exit code assertion (
expect(exitCode, stderr)), so a failing install reports why; in the CI failures above it did not, and the reason had to be dug out of the job log. - No change under
src/; the Windows eviction itself is #28062 / #33884, after which the isolation here is still correct, just no longer load-bearing. - Verified on Windows Server 2019 x64 with the current canary, mirroring CI by exporting a fresh shared
BUN_INSTALL_CACHE_DIRper run: unfixed test 5/10 runs fail, fixed test 0/20; the full file passes there. On Linux the full file passes with the debug build (34/34),hoist.test.tsandcatalogs.test.ts(othercreateTestDircallers) pass, and the three tests still fail withpanic: unreachable: Erroron a canary from before #37469, so they still cover what they did. The first CI run of this PR had the file passing first try on both Windows lanes.
Background
BUN_INSTALL_CACHE_DIRis the env override for bun's package cache. It wins overinstall.cacheinbunfig.toml, and the test runner exports one per test-file invocation, so a test that wants a cache of its own has to set the env var; setting it in bunfig is not enough in CI.- The cache entry for a tarball dependency is named after a hash of its spec, so two projects installing the same spec into one cache read and write the same entry.
bun installextracts a package into a temp dir and then renames that dir into the cache. On POSIX a collision with an entry another process published is resolved with an atomic swap, so the entry never disappears; the Windows arm instead renames the existing entry away and deletes it before retrying, which is the window the first process falls into (#28062).
Probe: concurrent installs sharing a cache on Windows (no test involved)
N project dirs with {"dependencies":{"bar":"<long ./x/../... spec>/bar-0.0.2.tgz"}} and the tarball, bun install spawned in all of them at once, repeated. bun 1.4.0-canary.1+18059646e, Windows Server 2019 x64.
shared BUN_INSTALL_CACHE_DIR, 3 installs x 30 iterations: 9 of 90 installs exit 1
ENOENT: failed copying files from cache to destination for package bar (4)
ENOENT: failed opening cache/package/version dir for package bar (5)
(always the process that finished extracting first)
shared BUN_INSTALL_CACHE_DIR, 2 installs x 10 iterations: 2 of 20 exit 1
one BUN_INSTALL_CACHE_DIR per project, 2 x 30 iterations: 0 of 60
The test itself under the same CI-like env (fresh shared BUN_INSTALL_CACHE_DIR per bun test run): unfixed 5/10 runs fail, always at install(); fixed 0/20.
Earlier revision
The first revision pinned BUN_INSTALL_CACHE_DIR inside bun-patch.test.ts only (the same local wrapper the files listed above have). Self-review pointed out that this would be the sixth copy of that wrapper and that the harness is where the intent already lives, so the pin moved into createTestDir; the test-side behavior is identical.
no test proof · iteration 0 · Platform-specific test-only change; deferring to CI.