Skip to content

Keep YarnEnv unit tests off the host yarn env - #2065

Open
Mikola Lysenko (mikolalysenko) wants to merge 2 commits into
mainfrom
ci-janitor/yarn-env-scrub
Open

Mikola Lysenko (mikolalysenko) wants to merge 2 commits into
mainfrom
ci-janitor/yarn-env-scrub

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Nov 13, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

CI was healthy on this run: the merge queue was empty, the last 28 merge_group runs (since 11-12 18:56 UTC) all passed, main's latest push run (43324491043) and today's nightly (43373720347) are green, nothing was queued, and no PR run since 11-09 failed on a flake. So this run takes a priority-4 robustness target in the same class as #2054–#2057, #2063 and #2064: tests that pass only because CI's env is clean.

#2054 moved the pkg_managers/pnpm_layout detector tests onto a hermetic detector. But every crawler, vendor and vex path below it still builds YarnEnv from the host's YARN_* vars and ~/.yarnrc.yml. On origin/main (de81f1b):

host env before after
clean 7720/7720 pass 7721/7721 pass (incl. 1 new test)
YARN_NODE_LINKER=node-modules 2 failed: npm_crawler::tests::global_scope_reads_a_yarn_store_configured_above_the_repository, test_yarn4_pnpm_linker_relocated_store_transitive_packages_are_found all pass
HOME with .yarnrc.yml = nodeLinker: node-modules 10 failed: vendor::lock_inventory (3), vendor::npm_flavor (5), vendor::refusals::tests::vlt (1), vendor::yarn_berry_lock (1) all pass
YARN_NODE_LINKER=pnp yarn_node_linker=node-modules YARN_PNPM_STORE_FOLDER=… YARN_RC_FILENAME=… YARN_INJECT_ENVIRONMENT_FILES=… (crawlers::) – 801/801 pass

(Counts are cargo test -p socket-patch-core --lib.)

Root cause

YarnEnv::current / for_project (crates/socket-patch-core/src/crawlers/pkg_managers.rs) read std::env::vars_os() and utils::fs::home_dir() directly, with no test seam.

Fix

Under cfg(test) only, YarnEnv reads the YARN_* vars, HOME/USERPROFILE and ${NAME} expansion variables through test_env::guarded_var, i.e. only values a live EnvGuard sets. That is the pattern utils::go_env already uses for Go (#2057). Tests that set these vars via EnvGuard still see them (the existing HOME-guarded npm_crawler test passes). Non-test builds are unchanged, including the CLI integration tests, which link the non-test core.

New test yarn_env_sees_only_guarded_variables (#[serial]) pins both halves: guarded values are seen, and nothing is seen once the guard drops.

Proof

  • Table above. At 3007a1c the full core lib passes 7721/7721 both clean and with HOME-yarnrc + YARN_NODE_LINKER=node-modules + YARN_RC_FILENAME=.nope.yml combined.
  • New test looped 50x: 50/50 pass.
  • cargo clippy --locked -p socket-patch-core --all-features -- -D warnings (the CI clippy invocation) is clean. --all-targets reports pre-existing lints in other files only, none in this file. rustfmt --check is clean on the touched file.

Review (/code-review high + Bugbot)

Fixed in 3007a1c: ${NAME} expansion (base_var) still read the host env; Windows key-case matching (also Bugbot's finding); env read once per YarnEnv::current; the test now covers YARN_RC_FILENAME and ${NAME}.

Not changed, and why:

  • Inject the env instead of cfg(test) forks. This is the same seam utils::go_env uses (Keep Go unit tests off the host's Go env #2057). The non-test bodies are one-line std::env::vars_os() / home_dir() / std::env::var. Threading an env through every crawler, vendor and vex caller is a much larger change.
  • Move the filter into test_env.rs. Open Keep composer unit tests off the host's env #2064 edits that file. Sharing the helper can follow once it merges.
  • BerryRegistrySettings::read (patch/redirect/upstream/npm.rs) still reads YARN_RC_FILENAME/HOME/YARN_NPM_REGISTRY_SERVER from the host. That's the redirect restore path, a separate follow-up below. No core test failed under the hostile envs above.

Not in this PR (left for #1919)

  • BerryRegistrySettings::read host env reads (see above).

  • VIRTUAL_ENV set to a real venv still fails 5 vendor::pypi tests (pdm/pipenv stale-install). That's a different code path (python site discovery).

  • A /tmp/.npmrc (an ancestor of the test tempdir) still fails pnpm_layout::tests::every_reader_finds_a_store_in_the_configured_modules_dir through the unbounded .npmrc ancestor walk.

Where tests run

No test was removed or moved. One unit test was added; it runs wherever the core lib tests already run.

https://claude.ai/code/session_011f9aeSopYBBeiUVSewPUqN


Generated by Claude Code

YarnEnv::current reads YARN_NODE_LINKER, YARN_PNPM_STORE_FOLDER,
YARN_RC_FILENAME and YARN_INJECT_ENVIRONMENT_FILES from the process
env and the rc file in the home folder. #2054 moved the detector tests
onto a hermetic variant, but every crawler, vendor and vex path below
it still built YarnEnv from the host, so on origin/main:

- YARN_NODE_LINKER=node-modules fails 2 npm_crawler tests (yarn 4
  pnpm-linker relocated store);
- HOME with a .yarnrc.yml setting nodeLinker: node-modules fails 10
  vendor tests (lock_inventory, npm_flavor, refusals, yarn_berry_lock).

Under cfg(test), read only the YARN_* vars and HOME/USERPROFILE a live
EnvGuard sets, the same way utils::go_env reads Go vars through
test_env::guarded_var. Production builds (and the CLI integration
tests, which link the non-test core) keep reading the real env.

Refs #1919.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011f9aeSopYBBeiUVSewPUqN
@mikolalysenko Mikola Lysenko (mikolalysenko) added the ci-janitor Opened by the CI janitor routine (flakes, redundant tests, CI perf) label Nov 13, 2026
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

bugbot run


Generated by Claude Code

@cursor

cursor Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

PR Summary

Low Risk
Test-only cfg(test) seams; non-test code paths unchanged, so CLI and production behavior are unaffected.

Overview
YarnEnv no longer reads the real host process environment during unit tests. YarnEnv::current, for_project, and ${NAME} expansion now go through yarn_process_vars, yarn_process_var, and yarn_home, which under cfg(test) only expose values set by a live EnvGuard (same idea as utils::go_env).

Production builds still use std::env and the normal home directory; only the test build is isolated so developer YARN_* settings and ~/.yarnrc.yml cannot flip crawler/vendor tests.

Adds serial test yarn_env_sees_only_guarded_variables to assert guarded values are visible and host env is ignored once the guard is dropped.

Reviewed by Cursor Bugbot for commit 3007a1c. Configure here.

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stale Bugbot comment from a previous run.

Review follow-ups on the YarnEnv test seam:

- base_var fell back to std::env::var under cfg(test), so a host
  variable named in a fixture's ${NAME} reference still leaked. It
  now reads only guarded variables in unit tests.
- Windows keeps a key's existing spelling when a guard sets it in
  another case, so match the upper-case spelling there too.
- Read the process env once per YarnEnv::current, not three times.
- Cover YARN_RC_FILENAME and the ${NAME} lookup in the new test.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011f9aeSopYBBeiUVSewPUqN
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

bugbot run


Generated by Claude Code

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 3007a1c. Configure here.

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

Labels

ci-janitor Opened by the CI janitor routine (flakes, redundant tests, CI perf)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants