Files
OpenFUT/openfut-blaze-host/build.rs
T
funman300 cf3ddde3a6 blaze-host: move the dirty-tree safeguard to launch and evidence time
The compiled-in dirty flag cannot be trusted for this job. Cargo does not
re-run a build script when another crate's source changes, so editing the
adapter and rebuilding the host leaves it reading 'clean' -- verified by
appending a line to the adapter and watching the flag not move.

So the stamp now only names the commit, and the real safeguards run at the
moment they matter and cannot go stale:

  * sidecar.sh checks the working tree at LAUNCH and warns.
  * check-live-parity.sh REFUSES on a dirty tree, since it produces the
    artefact a migration decision is made from. ALLOW_DIRTY=1 overrides for a
    throwaway check.

Both scope to the three migration crates, so unrelated submodule dirt does not
trigger them -- a warning that is always on is a warning nobody reads.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 01:56:43 +00:00

70 lines
2.7 KiB
Rust

//! Stamp build identity into the binary.
//!
//! A live FIFA trace has to be attributable to an exact binary. During the
//! mutation runs for the previous step, four sidecars were left listening —
//! two of them serving deliberately broken builds — and nothing in their output
//! said so. A later A/B against one of those would have read as a genuine
//! parity failure.
//!
//! So the host prints its commit, working-tree cleanliness and profile at
//! startup, and `dirty` is the important one: a mutation-tested build is a
//! dirty build, and now it announces itself.
use std::process::Command;
fn git(args: &[&str]) -> Option<String> {
let out = Command::new("git").args(args).output().ok()?;
if !out.status.success() {
return None;
}
Some(String::from_utf8_lossy(&out.stdout).trim().to_string())
}
fn main() {
let commit = git(&["rev-parse", "--short=7", "HEAD"]).unwrap_or_else(|| "unknown".into());
// Scoped to the crates this binary is actually built from.
//
// A whole-repo check reads DIRTY permanently here, because unrelated
// submodules carry pre-existing modifications. A warning that is always on
// is a warning nobody reads — which would defeat the point, since the whole
// job of this flag is to make a mutated build announce itself.
//
// Untracked files are excluded: scratch output is not a build difference,
// but an edited source file certainly is.
let dirty = match git(&[
"status",
"--porcelain",
"--untracked-files=no",
"--",
"openfut-blaze-host",
"openfut-adapter-fifa17",
"openfut-protocol-blaze",
]) {
Some(s) if !s.is_empty() => "DIRTY",
Some(_) => "clean",
None => "unknown",
};
println!("cargo:rustc-env=OPENFUT_BUILD_COMMIT={commit}");
println!("cargo:rustc-env=OPENFUT_BUILD_DIRTY={dirty}");
// Re-stamp when HEAD moves.
//
// IMPORTANT LIMITATION: this flag is best-effort and CAN BE STALE. Cargo
// will not re-run a build script because some other crate's source changed,
// so editing the adapter and rebuilding the host can leave `dirty` reading
// "clean". Verified: appending a line to the adapter and rebuilding did not
// flip it.
//
// So the compiled-in value is useful for naming the commit, and is NOT the
// safeguard. `sidecar.sh` re-checks the working tree at launch and
// `check-live-parity.sh` refuses to produce evidence from a dirty tree —
// those run at the right moment and cannot go stale.
for p in ["../.git/HEAD", "../.git/index"] {
if std::path::Path::new(p).exists() {
println!("cargo:rerun-if-changed={p}");
}
}
}