Skip to content

Commit bf7ef6a

Browse files
Retry the yarn-classic corepack probe (#1673)
require_yarn_classic probed `corepack yarn@<release> --version` once and, under SOCKET_PATCH_YARN_E2E_REQUIRED=1, panicked on any failure. A single DNS timeout on a Depot host therefore failed the yarn-classic 1.22.22 merge-queue leg on 2026-10-22, evicted #1653 and forced the green group behind it to rebuild (~32 queue-min, ~94 job-min). Retry the probe after 2 s and 5 s before treating the release as unavailable, and keep the last attempt's stderr in the SKIP/panic message instead of discarding it. A missing corepack binary is not retried, a wrong release still panics at once, and a release that stays unfetchable still fails the REQUIRED leg. Refs #1671 Co-authored-by: Claude <noreply@anthropic.com>
1 parent 86bbd45 commit bf7ef6a

1 file changed

Lines changed: 39 additions & 23 deletions

File tree

‎crates/socket-patch-cli/tests/common/yarn_classic_vex.rs‎

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535

3636
use std::ffi::OsString;
3737
use std::path::Path;
38-
use std::process::{Command, Stdio};
38+
use std::process::Command;
3939

4040
use crate::vex_e2e_common::{
4141
assert_absent, assert_attested, assert_not_attested, binary, run_vex, statements_for,
@@ -112,36 +112,52 @@ pub fn skip(suite: &str, why: &str) {
112112
/// probed from a neutral temp dir (an ancestor `packageManager` field would
113113
/// make corepack refuse) with the suites' cache isolation applied by
114114
/// `isolate`. On `false` the caller returns after [`skip`].
115+
///
116+
/// A failed fetch is retried (after 2 s, then 5 s) before it counts as
117+
/// unavailable: one DNS blip on a CI host otherwise fails the leg under
118+
/// [`REQUIRED_ENV`]`=1` and evicts its merge-queue entry (#1671).
115119
pub fn require_yarn_classic(suite: &str, isolate: impl Fn(&mut Command)) -> bool {
116120
let spec = yarn_classic();
117121
let want = yarn_classic_version();
118122
let probe = tempfile::tempdir().expect("tempdir");
119-
let mut cmd = Command::new("corepack");
120-
cmd.args([spec.as_str(), "--version"])
121-
.current_dir(probe.path())
122-
.env("COREPACK_ENABLE_DOWNLOAD_PROMPT", "0");
123-
isolate(&mut cmd);
124-
let got = cmd
125-
.stderr(Stdio::null())
126-
.output()
127-
.ok()
128-
.filter(|o| o.status.success())
129-
.map(|o| String::from_utf8_lossy(&o.stdout).trim().to_string());
130-
match got {
131-
Some(v) if v == want => true,
132-
Some(v) => {
123+
let mut last_err = String::new();
124+
for (attempt, backoff) in [0, 2, 5].into_iter().enumerate() {
125+
std::thread::sleep(std::time::Duration::from_secs(backoff));
126+
let mut cmd = Command::new("corepack");
127+
cmd.args([spec.as_str(), "--version"])
128+
.current_dir(probe.path())
129+
.env("COREPACK_ENABLE_DOWNLOAD_PROMPT", "0");
130+
isolate(&mut cmd);
131+
let out = match cmd.output() {
132+
Ok(out) => out,
133+
Err(e) => {
134+
// corepack itself is missing: retrying cannot help.
135+
last_err = format!("cannot run corepack: {e}");
136+
break;
137+
}
138+
};
139+
if out.status.success() {
140+
let got = String::from_utf8_lossy(&out.stdout).trim().to_string();
141+
if got == want {
142+
return true;
143+
}
133144
// A wrong release is never a skip: the leg would silently test
134145
// another yarn.
135-
panic!("{suite}: `corepack {spec} --version` reported {v:?}, expected {want}");
136-
}
137-
None => {
138-
skip(
139-
suite,
140-
&format!("`corepack {spec}` unavailable (corepack absent or not fetchable)"),
141-
);
142-
false
146+
panic!("{suite}: `corepack {spec} --version` reported {got:?}, expected {want}");
143147
}
148+
last_err = format!(
149+
"attempt {} exited {}: {}",
150+
attempt + 1,
151+
out.status,
152+
String::from_utf8_lossy(&out.stderr).trim()
153+
);
154+
eprintln!("{suite}: `corepack {spec} --version` failed, {last_err}");
144155
}
156+
skip(
157+
suite,
158+
&format!("`corepack {spec}` unavailable (corepack absent or not fetchable; {last_err})"),
159+
);
160+
false
145161
}
146162

147163
// ── manifest-less VEX ─────────────────────────────────────────────────

0 commit comments

Comments
 (0)