- 1
//! Tells Cargo the embedded admin SPA is a build input, and refuses to - 2
//! compile against a bundle that no longer matches its own source. - 3
//! - 4
//! `src/admin_ui.rs` embeds `crates/vak-admin-ui/dist` at compile time via - 5
//! `include_dir!`. That macro reads the directory when it expands, but - 6
//! Cargo's own change detection only recompiles a crate when a file it - 7
//! already knows is a dependency changes — a `.rs` source file, unless a - 8
//! build script says otherwise. Nothing here previously told it dist/ was - 9
//! one, so a `cargo build` after `npm run build` regenerated dist/ could - 10
//! (and did) silently keep the previous incremental build of vak-server, - 11
//! embedding assets that no longer matched `index.html`'s own references - 12
//! to them. The result was a 404 on the JS bundle and the CSS: the admin - 13
//! console loaded an empty shell with nothing in the console to explain - 14
//! why, because no JavaScript ever ran to produce an error. - 15
//! - 16
//! `cargo:rerun-if-changed` on a directory is recursive: any file added, - 17
//! removed, or modified under it invalidates the crate's build cache. - 18
//! - 19
//! Watching dist/ alone left the other half of the same trap open. dist/ is - 20
//! *committed*, so editing `vak-admin-ui/src` and running `cargo build` - 21
//! without `npm run build` is a no-op as far as Cargo is concerned: the - 22
//! binary serves the previous bundle, the browser shows stale UI, and - 23
//! nothing anywhere says so. `scripts/release.sh` catches that before a - 24
//! release ships; the manifest check below catches it on the very next - 25
//! build, which is where it is cheap to fix. - 26
- 27
include!("../../scripts/ui_bundle_check.rs"); - 28
- 29
const ADMIN_UI: &str = "../vak-admin-ui"; - 30
/// The workspace client (docs/design/48-web-client.md). This crate embeds - 31
/// its `dist-web/` build under `/app`; `vak-desktop` ships the `dist/` one. - 32
const CLIENT_UI: &str = "../vak-client-ui"; - 33
/// The public site at `/` (docs/design/48-web-client.md §4.6). Not an npm - 34
/// bundle, but exactly the same trap: `site/dist` is committed and embedded - 35
/// with `include_dir!`, so editing `site/src` and running `cargo build` - 36
/// without re-running the builder ships the previous pages with nothing - 37
/// anywhere to say so. - 38
const SITE: &str = "site"; - 39
- 40
fn main() { - 41
for (ui, dist, hint) in [ - 42
( - 43
ADMIN_UI, - 44
"dist", - 45
"Run `npm run build` in crates/vak-admin-ui and commit dist/ (see docs/design/32-release-engineering.md).", - 46
), - 47
( - 48
CLIENT_UI, - 49
"dist-web", - 50
"Run `npm run build:web` in crates/vak-client-ui.", - 51
), - 52
( - 53
SITE, - 54
"dist", - 55
"Run `python3 crates/vak-server/site/build.py` and commit site/dist/.", - 56
), - 57
] { - 58
println!("cargo:rerun-if-changed={ui}/{dist}"); - 59
// The source side must be watched too, or a `src` edit alone never - 60
// re-runs this script and the check silently stops applying. - 61
println!("cargo:rerun-if-changed={ui}/src"); - 62
println!("cargo:rerun-if-changed={ui}/index.html"); - 63
- 64
if let Err(problem) = check_bundle_matches_source(Path::new(ui), dist) { - 65
// `site` lives inside this crate; the two UI trees are siblings. - 66
let crate_name = match ui.strip_prefix("../") { - 67
Some(sibling) => sibling.to_string(), - 68
None => format!("vak-server/{ui}"), - 69
}; - 70
// `cargo::error` is the supported way for a build script to fail - 71
// the build with a readable message; `panic!` would bury it - 72
// under a backtrace the reader does not need. - 73
println!("cargo::error=crates/{crate_name}/{problem}"); - 74
println!("cargo::error={hint}"); - 75
std::process::exit(1); - 76
} - 77
} - 78
} - 79
Indexing the workspace…
Vakyartha documentation is discovering safe artifacts, anchors, and source references.