Skip to main content

max / makenotwork

2.0 KB · 63 lines History Blame Raw
1 //! CI guard for business assumptions.
2 //!
3 //! Catches at PR time what would otherwise only fail at prod boot:
4 //! - `docs/business/assumptions.toml` parses
5 //! - All consistency rules pass (sums, bounds, founding ≤ standard)
6 //! - Every `{{ ... }}` marker in the live site-docs corpus resolves
7 //!
8 //! Run with: cargo test --test assumptions
9
10 use docengine::Assumptions;
11
12 // Canonical assumptions.toml ships with the repo at server/docs/business/.
13 // Cargo runs tests with cwd = crate manifest dir (MNW/server/), so the
14 // relative path is just docs/... — no traversal.
15 const ASSUMPTIONS_PATH: &str = "docs/business/assumptions.toml";
16 const SITE_DOCS_PATH: &str = "site-docs/public";
17
18 #[test]
19 fn real_assumptions_file_parses_and_validates() {
20 let a = Assumptions::load(ASSUMPTIONS_PATH)
21 .unwrap_or_else(|e| panic!("failed to load {ASSUMPTIONS_PATH}: {e}"));
22 a.validate()
23 .unwrap_or_else(|e| panic!("assumptions failed validation:\n{e}"));
24 }
25
26 #[test]
27 fn every_marker_in_site_docs_resolves() {
28 let a = Assumptions::load(ASSUMPTIONS_PATH).expect("load");
29
30 let mut failures = Vec::new();
31 visit_markdown(std::path::Path::new(SITE_DOCS_PATH), &mut |path, body| {
32 if !body.contains("{{") {
33 return;
34 }
35 if let Err(e) = a.substitute(body) {
36 failures.push(format!(" {}: {e}", path.display()));
37 }
38 });
39
40 if !failures.is_empty() {
41 panic!(
42 "{} doc(s) contain unresolved {{{{ … }}}} markers:\n{}",
43 failures.len(),
44 failures.join("\n")
45 );
46 }
47 }
48
49 fn visit_markdown(dir: &std::path::Path, f: &mut impl FnMut(&std::path::Path, &str)) {
50 let Ok(entries) = std::fs::read_dir(dir) else {
51 return;
52 };
53 for entry in entries.flatten() {
54 let path = entry.path();
55 if path.is_dir() {
56 visit_markdown(&path, f);
57 } else if path.extension().and_then(|s| s.to_str()) == Some("md")
58 && let Ok(body) = std::fs::read_to_string(&path) {
59 f(&path, &body);
60 }
61 }
62 }
63