Skip to content

CI: hermetic spawns in vendor build tests (#823) - #1484

Merged
Mikola Lysenko (mikolalysenko) merged 4 commits into
mainfrom
agent/fix-ci-hermetic-vendor-build
Oct 13, 2026
Merged

Mikola Lysenko (mikolalysenko) merged 4 commits into
mainfrom
agent/fix-ci-hermetic-vendor-build

Conversation

@mikolalysenko

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

Copy link
Copy Markdown
Collaborator

LLM Description written by Claude Code:claude-opus-5-5

Refs #823 (slice 9 of the hermetic-spawn migration). The issue stays open for the 32 remaining PENDING_RAW_SPAWNS entries.

Root cause

Ten vendor build suites spawned socket-patch with a bare Command::new and their own private SOCKET_* sweep. The copies disagreed with each other and with tests/common/hermetic.rs. Most kept an ambient SOCKET_NO_CONFIG, so SOCKET_NO_CONFIG=0 let a developer's real socket login authenticate the child. None forced the update notifier off. The maven and jvm copies re-added the opt-outs by hand, and the bun copy reused a tool scrub that also removed the forced opt-outs.

Change

  • Each suite's run helper now goes through hermetic::command / hermetic_command (hermetic::binary_command for e2e_vendor_composer_crlf.rs).
  • The suite-specific scrubs stay: Extra::Venv everywhere; M2_HOME for maven/jvm; the bun tool vars through scrub_ambient_bun_tool_env (the SOCKET_*-free variant made for hermetic children); every BUNDLE_* for gem via Extra::Bundle, as CI: hermetic spawns in redirect build tests (#823) #1457 did for the redirect suite; and UV_PROJECT_ENVIRONMENT for pypi via Extra::Pdm. The pypi suite's own bake_leak_guards sets that var in the test process, so before this change it reached every socket-patch child.
  • The ten files leave PENDING_RAW_SPAWNS (42 -> 32), so the ratchet in spawn_env_hygiene.rs keeps them hermetic.

Files: e2e_vendor_{bun,cargo,composer,gem,golang,jvm,maven,npm,pypi}_build.rs, e2e_vendor_composer_crlf.rs, spawn_env_hygiene.rs.

Flake fix found on this PR's CI

The `coverage` job on 230c44a failed in `patch::redirect::upstream::npm::tests::project_registry_decides_a_mirrors_tarball_urls` (a file this PR doesn't otherwise touch; job). Its `from_project: false` path falls back to `SOCKET_NPM_REGISTRY`, which the `#[serial]` bun_lockb and vlt tests set to a wiremock URL. The test itself wasn't serial, so it could race them. Reproduced locally with `SOCKET_NPM_REGISTRY=http://127.0.0.1:9\` (fails), then marked the test `#[serial_test::serial]` like the `client.rs` tests that read the same var. `redirect::upstream` lib tests: 146/146.

CI cost

Only test code changes; no workflow edits. A lean PR run has the same job count (~28 Linux jobs) and about the same job-minutes (~8 min wall) before and after.

Test evidence (local, all toolchains present: cargo, go, npm, uv, composer, bundler, mvn, gradle, bun)

  • cargo fmt --all -- --check: clean
  • cargo clippy --locked --workspace --all-features -- -D warnings: clean
  • --include-ignored per suite, no SKIP lines: composer_crlf 7/7, cargo 39/39, composer 33/33, gem 41/41, golang 36/36, npm 41/41, pypi 54/54, bun 37/37, maven 5/5, jvm 38/38, spawn_env_hygiene 15/15
  • Ratchet: no_new_bare_binary_spawns would fail with "no longer spawn the binary bare" if the list entries were left in, and with "spawn the binary with a bare Command::new" if a file were reverted.

/code-review high

  • Fixed: the pypi UV_PROJECT_ENVIRONMENT leak; maven/jvm now use Extra::Venv like the other suites.
  • Not fixed here (behavior that predates this PR and needs new shared Extra variants, so it is out of scope for a pure migration slice): ambient PIPENV_* reaching the pypi child, COMPOSER_VENDOR_DIR / COMPOSER_HOME reaching the composer children, and vex_e2e_common::run_vex (shared by many suites) applying only Extra::Venv, so the gem VEX legs still see ambient BUNDLE_*. These are good candidates for a follow-up slice that adds Extra::Pipenv / Extra::Composer and lets run_vex take extras.
  • Skipped as cosmetic: hermetic_command(&binary()) vs hermetic::binary_command() (kept the CI: hermetic spawns in redirect build tests (#823) #1457 spelling), and the bun suite's redundant --no-telemetry, which this PR didn't add.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AhV4KjRucQ3Tg5k4KMLzT1


Generated by Claude Code

Assisted-by: Claude Code:claude-opus-5-5
Ten vendor build suites started socket-patch with a bare Command::new
and their own SOCKET_* sweep. The copies drifted: most kept an ambient
SOCKET_NO_CONFIG (so SOCKET_NO_CONFIG=0 let a developer's real login
authenticate the child), none forced the update notifier off, and the
maven/jvm copies re-added the opt-outs by hand.

Their run helpers now go through tests/common/hermetic.rs, and the
files leave PENDING_RAW_SPAWNS (42 -> 32) so the ratchet keeps them
hermetic. Suite-specific scrubs stay: VIRTUAL_ENV, M2_HOME, the bun
tool vars (now the SOCKET_*-free scrub_ambient_bun_tool_env), and the
gem suite now drops every ambient BUNDLE_* like the redirect suite.
Refs #823.

Assisted-by: Claude Code:claude-opus-5-5
The pypi vendor suite's leak guards set UV_PROJECT_ENVIRONMENT in the
test process, and the python crawler reads it, so every socket-patch
child it spawned inherited a bogus venv path. Remove it (Extra::Pdm)
along with VIRTUAL_ENV. The maven and jvm suites now drop VIRTUAL_ENV
through Extra::Venv like the rest instead of a hand-written removal.

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as ready for review October 13, 2026 14:17
@mikolalysenko Mikola Lysenko (mikolalysenko) added the ci-perf CI / merge-queue performance finding (profiler routine) label Oct 13, 2026
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@mikolalysenko Mikola Lysenko (mikolalysenko) removed the ci-perf CI / merge-queue performance finding (profiler routine) label Oct 13, 2026

@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.

project_registry_decides_a_mirrors_tarball_urls falls back to the
SOCKET_NPM_REGISTRY env var, which the bun_lockb and vlt tests set to
a wiremock URL under #[serial]. This test was not serial, so it could
read their value and fail, as it did on the coverage job for #1484.
Mark it #[serial] like the client.rs tests that read the same var.

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

BugBot review


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 00f01c7. Configure here.

Merged via the queue into main with commit 285a5e8 Oct 13, 2026
54 checks passed
@mikolalysenko
Mikola Lysenko (mikolalysenko) deleted the agent/fix-ci-hermetic-vendor-build branch October 13, 2026 14:59
Mikola Lysenko (mikolalysenko) added a commit that referenced this pull request Oct 13, 2026
Covers #1469, #1470, #1474, #1475, #1478, #1479, #1480 and #1482; #1484 is
CI-only. The notes now cover main through 285a5e8.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
github-merge-queue Bot pushed a commit that referenced this pull request Oct 13, 2026
* ci(release): publish npm from release.yml, not publish-npm.yml

Every socket-patch npm package's trusted publisher is registered against
release.yml, and npm allows only one publisher per package. The 5.0.0
release dispatched publish-npm.yml, whose OIDC token named that file, so
npm rejected it with E401 before staging anything.

Move the npm leg back inline as release.yml's npm-publish job (same steps
as publish-npm.yml) and delete publish-npm.yml, so the existing
registration keeps working. Add an `npm-retry-version` input that skips
the version gate, build, tag, GitHub release and crates.io jobs and
re-stages npm from an existing release's assets; this retries 5.0.0 now
and replaces the manual Publish npm dispatch. crates.io stays dispatched
through publish-cargo.yml, since crates.io allows several publishers per
crate.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(release): fold 22 more PRs into the 5.0.0 notes

Cover the PRs merged to main after #1432's base (1779317..4cb3643):
Cargo source replacement and registry = "crates-io" (#338/#455, #386),
pnpm lockfile=false (#1074), berry removed descriptors (#1435), yarnrc
${VAR} reads (#1100), CRLF .npmrc append (#1196), Composer vendor-dir
cascade and global home (#439/#686, #586), Go +incompatible vex (#484),
gem moved BUNDLE_GEMFILE and commented Gemfile revert (#952, #988),
Poetry source = "pypi" (#1282) and Hatch path characters (#547).

No entries for #1411 (macOS fix to code #1393 added in this release;
the #1393 entry already describes the intended behavior), #1426 (perf
regression introduced and fixed within 5.0.0) or the CI/test/bench PRs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(release): cover #1419, #1434, #1440, #1442, #1444 in the 5.0.0 notes

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(release): 5.0.1

Cut [Unreleased] into [5.0.1] — 2026-10-13 and stamp 5.0.1 with
scripts/version-sync.sh. The 5.0.1 notes cover main through 501c6d9
(#1449), i.e. every PR after the v5.0.0 tag (6ad6add): the npm
publish fix (5.0.0 never reached npm or crates.io, 5.0.1 is the first
v5 there), #1465, #759, #1460, #1462, #1445, #869, #1447, #1450,
#1467, and #1449 under Maintenance. CI/test-only PRs (#1448, #1452,
#1454, #1457, #1459) have no entries.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(release): 5.0.1 notes for PRs merged since the cut

Covers #1469, #1470, #1474, #1475, #1478, #1479, #1480 and #1482; #1484 is
CI-only. The notes now cover main through 285a5e8.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants