crates/Skidbladnir-build-thing/tests/build_gate.rs
//! **⚒ Build Thing's BUILD GATE, asserted where a test run sees it.**
//!
//! The forge's door (`dwarves buildthing` / ⚒ Build) ends every delivery with
//! `nornir_build_thing::buildgate::tally_bins`: every `[[bin]]` cargo can see in this
//! tree must come out of a declared row, or be named in `[build.allow_unbuilt_bins]`
//! with the reason it has no row — and no excuse may name a bin a row builds.
//! MEASURED 2026-10-16 (the build-thing sweep on loki): this repo's declaration was
//! RED on that gate and no test here asked the question, so the first place it
//! showed was the forge, after a whole build. This is the same function over the
//! same declaration, with the bins the declared cargo rows name.
//!
//! A new `[[bin]]` lands RED here until it gets a row or a written reason.
use std::collections::BTreeSet;
use std::path::PathBuf;
use nornir_build_thing::buildgate::tally_bins;
use nornir_build_thing::variant::{ArtifactKind, BuildVariantSet};
/// The checkout this crate lives in: the nearest ancestor that declares a build space.
fn repo_root() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.ancestors()
.find(|d| BuildVariantSet::conventional_path(d).is_file())
.expect("an ancestor declares .nornir/build-variants.toml")
.to_path_buf()
}
#[test]
fn every_bin_is_built_by_a_row_or_excused_with_a_reason() {
let root = repo_root();
let set = BuildVariantSet::discover(&root)
.expect("the declaration loads")
.expect("this repo declares a build space");
let produced: BTreeSet<String> = set
.variants
.iter()
.filter(|v| matches!(v.kind, ArtifactKind::Exe | ArtifactKind::Service))
.filter_map(|v| v.bin.clone())
.collect();
let (tally, problems) = tally_bins(&root, produced, false).expect("the gate runs");
// NON-VACUOUS: a walker that found no bins would pass any declaration.
assert!(!tally.declared.is_empty(), "the gate saw no [[bin]] at all under {}", root.display());
assert!(problems.is_empty(), "[build.allow_unbuilt_bins] problems: {problems:#?}");
tally.verdict().unwrap_or_else(|e| panic!("{e}\n{}", tally.headline()));
}
/// The `[package] name` of every workspace member the manifest at `dir` reaches
/// (`.` itself when it is a package), read as plain TOML: `cargo metadata` would
/// resolve, and a guard must not rewrite the tree it audits.
fn packages_of_workspace(dir: &std::path::Path) -> BTreeSet<String> {
let read = |d: &std::path::Path| -> toml::Table {
let path = d.join("Cargo.toml");
std::fs::read_to_string(&path)
.unwrap_or_else(|e| panic!("read {}: {e}", path.display()))
.parse::<toml::Table>()
.unwrap_or_else(|e| panic!("parse {}: {e}", path.display()))
};
let name = |t: &toml::Table| -> Option<String> {
t.get("package")?.get("name")?.as_str().map(str::to_string)
};
let root = read(dir);
let mut out: BTreeSet<String> = name(&root).into_iter().collect();
let members = root
.get("workspace")
.and_then(|w| w.get("members"))
.and_then(|m| m.as_array())
.cloned()
.unwrap_or_default();
for m in members {
let m = m.as_str().expect("a member entry is a string");
out.extend(name(&read(&dir.join(m))));
}
out
}
/// **Every cargo row names a package its build can find.** A row's `cargo build -p
/// <package>` runs in the root workspace unless the row declares `manifest_dir` (a
/// DETACHED workspace), so the package must be a member there.
///
/// RED in ODEN-CI round 1 (2026-10-25): `rows:ORIGINAL` died at `cargo build -p
/// skidbladnir-probe` with "package ID specification `skidbladnir-probe` did not
/// match any packages". `probe/` is its own `[workspace]` (static musl, std only),
/// and the two rows built from it declared no `manifest_dir`.
#[test]
fn every_cargo_row_names_a_package_of_the_workspace_it_builds_in() {
let root = repo_root();
let set = BuildVariantSet::discover(&root)
.expect("the declaration loads")
.expect("this repo declares a build space");
let mut lost = Vec::new();
let mut rows = 0;
for v in &set.variants {
let Some(pkg) = v.package.as_deref() else { continue };
rows += 1;
let dir = match v.manifest_dir.as_deref().map(str::trim).filter(|d| !d.is_empty()) {
Some(d) => root.join(d),
None => root.clone(),
};
if !packages_of_workspace(&dir).contains(pkg) {
lost.push(format!("{} -> -p {pkg} in {}", v.name, dir.display()));
}
}
assert!(rows > 0, "no cargo row was read; the gate would be hollow");
assert!(
lost.is_empty(),
"these rows name a package their workspace does not contain, so `cargo build -p` \
finds nothing (declare `manifest_dir` for a detached workspace):\n {}",
lost.join("\n ")
);
}