crates/holger-ui-recipe/tests/estate_siblings.rs
//! **Every sibling the estate patches name is mounted into the build container.**
//!
//! The CI runner copies `.cargo/estate-siblings.toml` to `.cargo/siblings.toml`, so the
//! container's cargo reads its `[patch.crates-io]` paths. Each `../<repo>/…` path there
//! is only readable when `[build.toolchain] siblings` mounts `<repo>` beside the tree.
//!
//! RED in ODEN-CI round 1 (2026-10-25): `rows:MVP` died at `mvp-ui` with "failed to
//! read `/work/monetize/crates/monetize-estate-side/Cargo.toml`". The patch for
//! `monetize-estate-side` (5ff33dd) names `../monetize`, and the toolchain mounted
//! only `edda`.
use std::collections::BTreeSet;
use holger_ui_recipe::{declared, repo_root};
/// The `<repo>` of every `path = "../<repo>/…"` in the patch template.
fn patched_siblings(text: &str) -> BTreeSet<String> {
text.lines()
.map(str::trim)
.filter(|l| !l.starts_with('#'))
.filter_map(|l| l.split("path = \"../").nth(1))
.filter_map(|rest| rest.split('/').next())
.map(str::to_string)
.collect()
}
#[test]
fn every_patched_sibling_is_a_declared_toolchain_sibling() {
let path = repo_root().join(".cargo/estate-siblings.toml");
let text = std::fs::read_to_string(&path).unwrap_or_else(|e| panic!("read {}: {e}", path.display()));
let patched = patched_siblings(&text);
assert!(!patched.is_empty(), "the template names no sibling; the check would be hollow");
let mounted: BTreeSet<String> = declared()
.toolchain
.expect("the recipe declares [build.toolchain]")
.siblings
.into_iter()
.collect();
let missing: Vec<&String> = patched.difference(&mounted).collect();
assert!(
missing.is_empty(),
"estate-siblings.toml patches from {missing:?}, but [build.toolchain] siblings mounts \
only {mounted:?}: the container cannot read those paths"
);
}
#[test]
fn the_reader_takes_the_repo_out_of_each_path() {
let t = "# path = \"../holger/x\"\n[patch.crates-io]\na = { path = \"../edda/crates/a\" }\n\
b = { path = \"../monetize/crates/b\" }\n";
let got: Vec<String> = patched_siblings(t).into_iter().collect();
assert_eq!(got, ["edda", "monetize"]);
}