test: hermetic package-manager caches — squash of #142/#143/#144 + review fixes + hosted-e2e unblock - #146
Merged
Mikola Lysenko (mikolalysenko) merged 2 commits intoAug 5, 2026
Conversation
#142 + #143 + #144, plus review fixes) Squashes jdalton's cache-isolation stack — #142 (setup-matrix per-case HOME), #143 (cache_env::isolate() across the Rust integration suites), #144 (hosted production suite) — and folds in the fixes from a 13-agent adversarial review of the stack: - e2e_hosted_production.rs: widen the gem leg's known-defect matcher to the post-depscan#23630 registry signature (compact index 404s as not_built; the /api/v1/dependencies fallback serves an empty 200 body, which dies as "marshal data too short" under bundler 2.x classic Marshal and as "undefined method 'bytes' for nil" under SafeMarshal rubies). This unblocks the hosted-e2e required check, red on every branch since the 2026-08-02 deploy. Verified live: the leg passes against the current production registry. Also isolate the has_command probe (the corepack-download leak the stack closes everywhere else). - e2e_npm.rs: partial COREPACK_HOME/npm_config_cache pin on the binary runner — the macOS global auto-discovery test spawns the CLI, whose yarn/pnpm prefix probes downloaded ~900 corepack files into the real home (full isolate() would defeat the test; same trade-off as global_packages_e2e.rs). - e2e_vendor_gem_build.rs, e2e_vendor_pypi_build.rs: isolate the bundler/ruby/python/uv availability probes so probe and fixture install answer for the same environment. - run-case.sh: export MAVEN_OPTS=-Duser.home so maven actually follows the case home (the JVM derives user.home from passwd, not $HOME — mvn kept writing the real ~/.m2 while the verify helper scanned the empty fake one); preserve rbenv/pyenv/nvm/volta/asdf/sdkman roots and copy ~/.tool-versions so --host runs still launch their toolchains. - cache_env.rs: document why GEM_HOME/GEM_PATH are deliberately not pinned and the --install-dir/BUNDLE_PATH invariant that keeps that safe. Co-authored-by: jdalton <john.david.dalton@gmail.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
Bugbot Autofix is ON. A cloud agent has been kicked off to fix the reported issue.
Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit f8cc6e5. Configure here.
Wenxin Jiang (Wenxin-Jiang)
approved these changes
Aug 5, 2026
Mikola Lysenko (mikolalysenko)
enabled auto-merge (squash)
August 5, 2026 19:02
…ROOTS mirror Bugbot caught the gap: the run-case.sh seed loop claimed to mirror cache_env.rs TOOLCHAIN_ROOTS but omitted FNM_DIR, MISE_DATA_DIR and MISE_CONFIG_DIR. Since the block copies ~/.tool-versions (a mise file) and redirects XDG_DATA_HOME/XDG_CONFIG_HOME into the empty case home, a mise user under --host would have had shims that resolve no toolchains. Same only-if-unset + dir-exists semantics as the rest. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Mikola Lysenko (mikolalysenko)
deleted the
test/cache-isolation-squashed
branch
August 5, 2026 19:04
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

One reviewable unit combining John-David Dalton (@jdalton)'s cache-isolation stack (#142, #143, #144) with the fixes from a 13-agent adversarial review, plus the change that turns the
hosted-e2erequired check green again. If we merge this, the three original PRs can be closed as superseded — their commits are credited viaCo-authored-by. If the team prefers merging jdalton's stack as-is instead, the review-fix commits here can be rebased into a small follow-up; either path works.What's in here
The stack, squashed (unchanged in substance):
HOMEunderWORKDIR(host-mode runs no longer install into the developer's real home).tests/common/cache_env.rs+isolate()across ~24 CLI integration suites (3,601 leaked files → 0, per jdalton's measurements, which we independently spot-checked).e2e_hosted_production.rs.Review fixes on top (each from a finding that survived adversarial verification):
hosted-e2eunblock — the required check has been red on every branch since 2026-08-02, including branches with none of these changes. Root cause is server-side: depscan#23630 (merged 07-31, deployed in the 08-01→08-02 window) made the gem patch-registry's compact-index routes fail closed (404 {"error":"not_built"}) until a re-queued per-package rebuild completes — and that rebuild hasn't completed for the activestorage patch. Bundler then falls back to/api/v1/dependencies, which serves HTTP 200 with a zero-byte body, and unmarshalling dies. The gem leg's known-defect matcher only accepted the oldAPIResponseMismatchErrorsignature, so it flagged this as a new regression. This PR widens the matcher with a tight conjunction (Retrying dependency api due to errorand the unmarshal error) covering both bundler generations:marshal data too short(bundler 2.x classic Marshal — what CI runs) andbytes' for nil(SafeMarshal, ruby 3.4+/bundler 4). Verified live: the leg passes against the current production registry with this change (took the known-defect branch; all redirect hard-assertions still enforced;SOCKET_PATCH_HOSTED_E2E_GEM_STRICT=1still promotes to hard failure).e2e_npm.rsmacOS auto-discovery leak — the test spawns the CLI withscan -g; the binary'syarn global dir/pnpm root -gprobes downloaded ~900 corepack files into the real home. Fixed with the same partialCOREPACK_HOME/npm_config_cachepinglobal_packages_e2e.rsuses (fullisolate()would defeat real-prefix resolution, which is the test's point).user.homefrom passwd, not$HOME, somvnkept writing the real~/.m2whileresolve_target's maven arm scanned the always-empty fake home (silent assertion weakening; if maven apply ever starts working the matrix could never observe it). Fixed withMAVEN_OPTS=-Duser.home=$WORKDIR/home.run-case.shtoolchain roots — test(setup-matrix): give each case its own home directory #142 preserved onlyRUSTUP_HOME; on a--hostmachine using rbenv/pyenv/nvm/volta/asdf/sdkman the redirectedHOMEmade those shims unable to find their roots. Now seeded from the real home (only-if-unset + dir-exists, mirroringcache_env.rs'sTOOLCHAIN_ROOTS), plus the~/.tool-versionscopy.bundler_version(), therubyAPI probe, andfind_python/find_uvwere the only spawns in the stack not isolated; a version-manager setup could make the probe and the real install disagree (silent SKIP or spurious run). Now isolated, matchinghas_commandeverywhere else — including ine2e_hosted_production.rs, which test(hosted): isolate package-manager caches in the production e2e suite #144 missed.GEM_HOME/GEM_PATHinvariant documented incache_env.rs— deliberately not pinned (rvm/chruby resolvebundleitself through them); safe today because every gem/bundle install in the suites passes--install-dir/BUNDLE_PATH.Review provenance
Five parallel reviewers (helper internals, both halves of the call sites, the shell change, CI-interplay) + live forensics on the red check, with adversarial verification of every critical/major finding. Verdict on the stack itself: no breakage of existing testing infrastructure — Docker e2e/coverage suites untouched, CI setup-matrix containers unaffected, the e2e
--ignoredmatrix legs re-pin their env afterisolate()(last-write-wins, self-tested), Windows sandbox paths stay within MAX_PATH, and no CI job restores caches into locationsisolate()bypasses (noactions/cacheinto$HOMEpackage-manager paths). Notable refuted candidates (checked, not real): the shared persistent yarn cache masking the berry tampered-tarball negative control; container legs losing pre-baked corepack pins.Verified
cargo check -p socket-patch-cli --tests,cargo clippy --tests(no new warnings; the few pre-existing ones reproduce onmain),bash -n+ touched-filerustfmton the pinned 1.93.1 toolchain.cache_envself-tests pass (5/5).main.Known residuals (deliberately out of scope, same as jdalton's deferrals)
in_process_cargo_apply/in_process_remote_ecosystems_applystill leak (~900 files each): in-processapplyshells out from the test process itself; fixing means mutating process env, which this repo has had races with (test: fix hostile-decoy env race flaking the setup-matrix and e2e suites #135/test: exclude crawler-e2e siblings from #[serial] env swaps via #[parallel] #136).corepack prepare --activatewarm step now warms the wrong (real)COREPACK_HOME— dead weight, ~seconds of re-download per run; workflow-side follow-up.package_gem_index_depspopulates, and make/api/v1/dependenciesstop serving zero-byte 200s. Once the index rebuilds with deps, the leg's success branch prints its loud NOTE to delete the tolerance entirely.Supersedes #142, #143, #144 (author credited).
🤖 Generated with Claude Code
Note
Low Risk
Changes are confined to test harnesses and setup-matrix shell env; production CLI behavior is unchanged aside from hosted-e2e tolerance for a known registry defect.
Overview
Adds
tests/common/cache_env.rswithisolate()to redirect package-manager caches (npm, pnpm, yarn, corepack, GoGOCACHE/GOMODCACHE, cargo, pip/uv, gem, composer, nuget, etc.) into a shared temp sandbox, preserve version-manager roots when needed, and ship self-tests so critical env vars stay pinned.Wires
cache_env::isolatethrough shared helpers (has_command,run_toolchain,cargo_run) and ~24 CLI integration suites so real installs and corepack probes no longer write to the developer’s home. Tests that must see real global prefixes (global_packages_e2e, parts ofe2e_npm) only pinCOREPACK_HOME/npm_config_cache. Several yarn helpers fix scrub-then-isolate ordering so private cache overrides are not wiped.tests/setup_matrix/run-case.shredirects each case’sHOMEand tool caches underWORKDIR, seedsRUSTUP_HOMEand other VM roots from the real home, copies.tool-versions, and setsMAVEN_OPTS=-Duser.homeso Maven’s~/.m2follows the case home.e2e_hosted_production: isolates toolchain probes/installs; widens the gem leg’s known production defect matcher for post–depscan#23630 bundler failures (empty dependency API + marshal errors) so the required check can pass while redirect assertions stay strict.Reviewed by Cursor Bugbot for commit f8cc6e5. Configure here.