Skip to content

Keep hatch unit tests off the host uv path - #2067

Merged
Mikola Lysenko (mikolalysenko) merged 2 commits into
mainfrom
ci-janitor/hatch-env-scrub
Nov 13, 2026
Merged

Mikola Lysenko (mikolalysenko) merged 2 commits into
mainfrom
ci-janitor/hatch-env-scrub

Conversation

@mikolalysenko

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

Copy link
Copy Markdown
Collaborator

Problem

CI was healthy this run: the merge queue is empty (no queued or in-progress runs), every merge_group run since 11-12 18:56 UTC passed, main's latest push run (43324491043) and today's nightly (43373720347) are green, and no run since 11-10 needed a re-run. The 11-12 nightly Windows failure (scan_hosted_paths_run_once_per_project_directory) was fixed by #2061. So this run takes a priority-4 robustness target from #1919, the same class as #2054–#2057 and #2063–#2066: core unit tests that pass only because CI's env is clean.

A hostile-env probe of cargo test --workspace --lib on origin/main (de81f1b) with ~20 vars the code reads set (MAVEN_REPO_LOCAL, DENO_DIR, PIPX_HOME, XDG_DATA_HOME, UV_EXCLUDE_NEWER, NUGET_PACKAGES, VIRTUAL_ENV, SSL_CERT_FILE, CI, every SOCKET_* config var, ...) found one remaining leak outside the open PRs' scope:

host env main this PR
clean 7720/7720 7721/7721 (1 new test)
HATCH_ENV_TYPE_VIRTUAL_UV_PATH=<any path> 18 failed all pass
every other var in the probe all pass all pass

Failing tests on main: 16 in vendor::pypi_hatch / vendor::pypi (hatch flavors, outage idempotence) and utils::hatch::tests::uv_sources_refuse_project_rewrites_under_the_uv_installer.

Root cause

HATCH_ENV_TYPE_VIRTUAL_UV_PATH is Hatch's documented switch to the uv installer. utils/hatch.rs (run_round) and vendor/pypi_hatch.rs (require_pip_installer) read it straight from the process, so a developer who sets it gets the uv refusals on every pip-installer fixture.

Fix

Both reads go through a new hatch::uv_path_override(). Non-test builds read std::env::var exactly as before (the CLI integration tests, e.g. mode_migration_pypi's UV_PATH case, link the non-test core and are unaffected). Under cfg(test) it reads only a value a live EnvGuard holds (test_env::guarded_var), the same seam as utils::go_env::process_env (#2057).

New test uv_path_env_hides_the_host_value (#[serial]) sets the var directly (no guard) and checks uv_path_override() stays false and a uv-sourced pyproject still rewrites. It deliberately never holds the key with an EnvGuard: the other utils::hatch tests aren't #[serial], and the first version of this test (which held a non-empty, then an empty, guarded value) made uv_sources_refuse_project_rewrites_under_the_uv_installer fail 2–3 times per 100 loops — even the empty guard leaked, because EnvGuard's drop restores the previous value before releasing the key. The uv branch itself stays covered by the direct uv_source_names(.., true) asserts. Fixed in the second commit.

Proof

  • Table above, both columns measured locally (full socket-patch-core --lib suite).
  • utils::hatch looped 300/300 on a clean env and 100/100 with HATCH_ENV_TYPE_VIRTUAL_UV_PATH=/host/uv.
  • cargo clippy --locked -p socket-patch-core --all-features -- -D warnings (CI's invocation) is clean; rustfmt on the two touched files only. --all-targets shows only pre-existing lints in files this PR doesn't touch.
  • No test removed or moved; no CI config change.

https://claude.ai/code/session_011f9aeR2MHrmJ9Fh9wmm3X1


Generated by Claude Code

utils::hatch and vendor::pypi_hatch read HATCH_ENV_TYPE_VIRTUAL_UV_PATH
from the process: a non-empty value switches every Hatch env to uv, so
the vendored-wheel and [tool.uv.sources] refusals fire with no file
setting. A developer who points Hatch at uv that way sees 18
socket-patch-core unit tests fail on a clean origin/main checkout
(`cargo test -p socket-patch-core --lib`); CI passes only because no
job sets the var.

Both reads now go through hatch::uv_path_override(). Production builds
read the process env as before; unit-test builds read only a value a
test holds with an EnvGuard (test_env::guarded_var), as go_env does
since #2057. A new test holds the var to cover the uv branch that the
unit tests never reached before, and checks a host value stays hidden.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011f9aeR2MHrmJ9Fh9wmm3X1
@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 env isolation for Hatch/uv detection; production reads the same env var through one helper with no behavior change outside tests.

Overview
Unit tests no longer treat a developer's host HATCH_ENV_TYPE_VIRTUAL_UV_PATH as switching Hatch to the uv installer. Hatch logic now reads that flag through uv_path_override() (and uv_path_env()) instead of calling std::env::var inline in run_round and vendored require_pip_installer.

Production builds behave the same as before: a non-empty path still forces the uv path. Under cfg(test), only values held by a live EnvGuard via test_env::guarded_var count, matching the seam used elsewhere (e.g. go_env). A new serial test, uv_path_env_hides_the_host_value, sets the var on the process without a guard and asserts overrides stay off so pip-installer fixtures still pass.

Reviewed by Cursor Bugbot for commit c76ed80. 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.

@mikolalysenko Mikola Lysenko (mikolalysenko) added the Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review label Nov 13, 2026
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Ready for review (burn-down agent).

  • Head: 52db0e1
  • CI: 50/50 checks settled green (31 success, 19 skipped); no main-wide failures.
  • Bugbot: reviewed 52db0e1, no findings; no open review threads.
  • Mergeable, no conflicts; test-only change (no CHANGELOG edits). Worth a look: the new test saves and restores the host HATCH_ENV_TYPE_VIRTUAL_UV_PATH by hand, so it relies on #[serial].
  • Slack announcement not sent: the Slack send tool was unavailable in this run; the next run should retry.

Generated by Claude Code

The first version of uv_path_env_counts_only_when_a_guard_holds_it held
HATCH_ENV_TYPE_VIRTUAL_UV_PATH with an EnvGuard. Other utils::hatch
tests are not #[serial], so while the guard was live they saw uv
switched on: uv_sources_refuse_project_rewrites_under_the_uv_installer
failed 2-3 times in 100 loops of `utils::hatch` on a clean env. Even an
empty-value guard leaked, because EnvGuard's drop restores the previous
value before it releases the key.

The test now only checks that an unguarded host value stays hidden; the
uv branch itself is covered by the direct uv_source_names(.., true)
asserts. utils::hatch now passes 300/300 loops clean and 100/100 with
the host var set.

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

Copy link
Copy Markdown
Collaborator Author

bugbot run

New head c76ed80 replaces 52db0e1: the first version of the new test held the uv var in an EnvGuard and made a parallel utils::hatch test flake (2–3/100 local loops). The test no longer holds the var; details in the PR body.


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 c76ed80. Configure here.

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Final review brief

What it does. Test-only change. Both reads of HATCH_ENV_TYPE_VIRTUAL_UV_PATH (Hatch's switch to the uv installer) go through a new hatch::uv_path_override(). In unit tests it sees only a value a live EnvGuard holds, so a developer who has the var set no longer fails 18 hatch/pypi tests (#1919).

Risk: low. The non-test path is std::env::var(..).ok().is_some_and(non-empty), the same as the old var(..).is_ok_and(non-empty) at both call sites, so production behavior is unchanged.

Look here

Verified

  • Read the full diff (2 files, +45/-5) and the description; they match. No other read of the var is left in core src/. No CHANGELOG change, no debug leftovers. The new test sets the real var without a guard on purpose (explained in its doc comment: a guard on the key would leak uv-on into the parallel, non-serial hatch tests); it would fail on main, where the set var makes the rewrite refuse.
  • Ran locally at c76ed80 with HATCH_ENV_TYPE_VIRTUAL_UV_PATH=/host/uv exported: cargo test -p socket-patch-core --lib -- hatch vendor::pypi 595/595.
  • CI green on head (ci-ok, clippy). Bugbot reviewed c76ed80, no open threads.

Changes I made. None.

Open questions. None. (Nit, not blocking: the new test restores the var by hand, so a failed assert would leave it set for the rest of the run; harmless because every read is seamed.)

Auto-merge is armed, so approving sends it straight to the merge queue.


Generated by Claude Code

Merged via the queue into main with commit 3b3f672 Nov 13, 2026
50 checks passed
@mikolalysenko
Mikola Lysenko (mikolalysenko) deleted the ci-janitor/hatch-env-scrub branch November 13, 2026 15:13
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) Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants