From 9bedce4aa4306f88fdf152136bb8cb1910ae99e0 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 9 Oct 2026 09:52:06 +0000 Subject: [PATCH] Keep Maven e2e resolves off Central after warm-up Main CI went red on the Maven 3.6.3 e2e leg (run 37909555148) after a Central blip: the warm-up recovered via the Google mirror, but two later steps went back to Central without any fallback. - The hosted capstone's purge() deleted commons-text 1.10.0, which maven-dependency-plugin 3.6.1 itself depends on, so every resolve after a purge re-fetched it from Central. Purge only the suffixed versions; the project never asks for the base one. - The vendored capstone's `mirrorOf external:*` mirror had the id e2e-mirror-0. The local repository keys cached artifacts by repo id, so that step re-downloaded the whole plugin closure (~60 artifacts) from Central. Give the mirror the id `central`. Locally neither success-path step now fetches from Central. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01Ga7HGbRKViq2awDzQAqsLx --- .../tests/e2e_redirect_maven_build.rs | 17 ++++++++++----- .../tests/e2e_vendor_maven_build.rs | 11 ++++++++-- .../tests/maven_build_common/mod.rs | 21 +++++++++++++++++-- 3 files changed, 40 insertions(+), 9 deletions(-) diff --git a/crates/socket-patch-cli/tests/e2e_redirect_maven_build.rs b/crates/socket-patch-cli/tests/e2e_redirect_maven_build.rs index 153f4d3f1..195411475 100644 --- a/crates/socket-patch-cli/tests/e2e_redirect_maven_build.rs +++ b/crates/socket-patch-cli/tests/e2e_redirect_maven_build.rs @@ -156,12 +156,19 @@ fn socket(cwd: &Path, m2: &Path, args: &[&str]) -> (Option, serde_json::Val (out.status.code(), env, stderr) } -/// Purge every copy of the fixture GAV (base + suffixed) from `m2` so the -/// next resolve must fetch it. +/// Purge every suffixed copy of the fixture from `m2` so the next resolve +/// must fetch it. The base version stays: the project only asks for the +/// suffixed one, and `maven-dependency-plugin` itself depends on +/// commons-text 1.10.0, so purging it sends every later resolve back to +/// Central (CI run 37909555148). fn purge(m2: &Path) { - let dir = m2.join(GROUP_PATH).join(ARTIFACT); - if dir.exists() { - std::fs::remove_dir_all(&dir).unwrap(); + let Ok(versions) = std::fs::read_dir(m2.join(GROUP_PATH).join(ARTIFACT)) else { + return; + }; + for entry in versions.flatten() { + if entry.file_name() != VERSION && entry.path().is_dir() { + std::fs::remove_dir_all(entry.path()).unwrap(); + } } } diff --git a/crates/socket-patch-cli/tests/e2e_vendor_maven_build.rs b/crates/socket-patch-cli/tests/e2e_vendor_maven_build.rs index e20f94a79..7dcce8e4f 100644 --- a/crates/socket-patch-cli/tests/e2e_vendor_maven_build.rs +++ b/crates/socket-patch-cli/tests/e2e_vendor_maven_build.rs @@ -297,10 +297,17 @@ fn maven_vendor_fresh_checkout_install_and_manifestless_vex() { .is_file(), "the local repository stays warm" ); + // The mirror keeps the id `central` so the warm plugin closure (cached + // under that id) is reused instead of re-fetched from Central (CI run + // 37909555148). let mirrored = root.join("mirrored-settings.xml"); - write_settings( + write_settings_with_ids( &mirrored, - &[("external:*", "https://repo.maven.apache.org/maven2")], + &[( + "central", + "external:*", + "https://repo.maven.apache.org/maven2", + )], ); for (label, settings) in [("warm", &settings), ("mirrorOf external:*", &mirrored)] { let out = mvn.copy_dependencies(&fresh, &m2, settings, "target/dep"); diff --git a/crates/socket-patch-cli/tests/maven_build_common/mod.rs b/crates/socket-patch-cli/tests/maven_build_common/mod.rs index 9f315649a..a49bc96fc 100644 --- a/crates/socket-patch-cli/tests/maven_build_common/mod.rs +++ b/crates/socket-patch-cli/tests/maven_build_common/mod.rs @@ -283,11 +283,28 @@ fn is_resolution_failure(out: &Output) -> bool { /// A user `settings.xml` with the given `(mirrorOf, url)` mirrors (none = /// an empty settings file that just shields the run from `~/.m2`). pub fn write_settings(path: &Path, mirrors: &[(&str, &str)]) { + let ids: Vec = (0..mirrors.len()) + .map(|i| format!("e2e-mirror-{i}")) + .collect(); + let mirrors: Vec<(&str, &str, &str)> = ids + .iter() + .zip(mirrors) + .map(|(id, (of, url))| (id.as_str(), *of, *url)) + .collect(); + write_settings_with_ids(path, &mirrors); +} + +/// [`write_settings`] with explicit `(id, mirrorOf, url)` mirrors. A mirror +/// that serves Central's content should keep the id `central`: the local +/// repository records which repository id each artifact came from and +/// re-fetches anything cached under another id, so a differently named +/// mirror re-downloads the whole warm plugin closure from Central. +pub fn write_settings_with_ids(path: &Path, mirrors: &[(&str, &str, &str)]) { let mut body = String::from("\n \n"); - for (i, (of, url)) in mirrors.iter().enumerate() { + for (id, of, url) in mirrors { body.push_str(&format!( - " \n e2e-mirror-{i}\n {of}\n \ + " \n {id}\n {of}\n \ {url}\n \n" )); }