From 7045413eb0b0d12be1b13779166950d71c037891 Mon Sep 17 00:00:00 2001 From: HackingGate Date: Wed, 9 Sep 2026 23:18:35 +0900 Subject: [PATCH] The submodule fixture commits as somebody, and a failed git says what git said Two tests have been failing on main since #143's run, in every job that runs the suite -- coverage, pre-commit, prek and scan engine -- and passing on every contributor's machine. `with_a_submodule` gives an identity to the source repository it builds and then adds that repository as a submodule. The tests commit into `root/sub`, which is the CLONE `git submodule add` made, and a clone carries none of the source's local config. So the commit borrowed whoever was configured globally: a developer machine has somebody, and CI has nobody. The clone is handed the same identity the fixture gives everything else it builds. The second half is why this took a local repro to find. The `git` helper sent stderr to `Stdio::null()` and asserted `"git {args:?} failed"`, so eleven minutes of CI reported back the one fact the reader already had -- that the command failed -- and threw away the sentence naming the cause. It now prints what git said and which directory it said it in. Verified by running the whole suite with GIT_CONFIG_GLOBAL and GIT_CONFIG_SYSTEM pointed at /dev/null, which is the condition CI runs under: 807 passed, 0 failed. The same suite was 2 failed before this change. Claude-Session: https://claude.ai/code/session_01HertdiAvdNKGyjR91jvRUM --- tests/supply_chain_cli.rs | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/tests/supply_chain_cli.rs b/tests/supply_chain_cli.rs index 48a74b8..22b0d50 100644 --- a/tests/supply_chain_cli.rs +++ b/tests/supply_chain_cli.rs @@ -138,14 +138,22 @@ fn recording(answer: &str) -> String { } fn git(root: &Path, args: &[&str]) { - let status = Command::new(support::real_git()) + let output = Command::new(support::real_git()) .args(args) .current_dir(root) .stdout(Stdio::null()) - .stderr(Stdio::null()) - .status() + .output() .unwrap(); - assert!(status.success(), "git {args:?} failed"); + // What git said, and where. A helper that swallowed stderr reported a + // missing committer identity as `git ["commit", ...] failed`, which is the + // one fact a reader already has -- and the cause was one config line away in + // a message nobody could see. + assert!( + output.status.success(), + "git {args:?} in {} failed:\n{}", + root.display(), + String::from_utf8_lossy(&output.stderr) + ); } fn commit(root: &Path, message: &str) -> String { @@ -785,6 +793,15 @@ fn with_a_submodule(root: &Path) { "sub", ], ); + // The submodule in the working tree is a CLONE, and a clone carries none of + // the source repository's local config. Every other repository this fixture + // builds is handed an identity at `init`; this one is handed one here, + // because the tests that commit into it commit into the clone and not into + // the source. Without it the fixture borrows whoever is configured globally, + // which is a machine that has somebody -- and CI is a machine that does not. + let checkout = root.join("sub"); + git(&checkout, &["config", "user.name", "Test"]); + git(&checkout, &["config", "user.email", "test@example.test"]); commit(root, "track the member"); }