Builds the dashboard frontend (`cd dashboard && npm ci/install && npm run build`) when dist assets are missing or stale, so plain `cargo build` / `cargo install --path .` work from a fresh checkout. Published crates ship the prebuilt dist files (see `package.include` in Cargo.toml), so this never runs for crates.io builds unless those packaged files are incomplete.
(reason: &str, affected: &[&str])
| 100 | /// prebuilt dist files (see `package.include` in Cargo.toml), so this never |
| 101 | /// runs for crates.io builds unless those packaged files are incomplete. |
| 102 | fn auto_build_dashboard_assets(reason: &str, affected: &[&str]) { |
| 103 | let fail_fast = |detail: &str| -> ! { |
| 104 | let affected = if affected.is_empty() { |
| 105 | "dashboard source files changed since the embedded dist assets were built".to_string() |
| 106 | } else { |
| 107 | affected.join("\n ") |
| 108 | }; |
| 109 | panic!( |
| 110 | "\n\ndashboard dist assets are {reason}:\n {affected}\n\n\ |
| 111 | The dashboard UI is embedded into the binary at compile time\n\ |
| 112 | (src/dashboard/assets.rs), so the frontend must be built first:\n\n \ |
| 113 | cd dashboard && npm ci && npm run build\n\n{detail}\n", |
| 114 | ); |
| 115 | }; |
| 116 | |
| 117 | let dashboard_dir = Path::new("dashboard"); |
| 118 | if !dashboard_dir.join("package.json").exists() { |
| 119 | fail_fast("dashboard/package.json not found; cannot build the assets automatically."); |
| 120 | } |
| 121 | let Some(npm) = npm_program() else { |
| 122 | fail_fast( |
| 123 | "npm was not found on PATH, so the build could not produce them \ |
| 124 | automatically.\nInstall Node.js 22+ (https://nodejs.org) and re-run the build.", |
| 125 | ); |
| 126 | }; |
| 127 | |
| 128 | // Automatic rebuilds must refresh dependencies even when `node_modules` |
| 129 | // already exists: a pulled package-lock change can add build-time imports |
| 130 | // that the stale install does not contain yet. |
| 131 | if let Err(ci_err) = run_npm(npm, &["ci"], dashboard_dir) { |
| 132 | println!("cargo::warning=dashboard assets: npm ci failed, retrying with npm install"); |
| 133 | if let Err(install_err) = run_npm(npm, &["install"], dashboard_dir) { |
| 134 | fail_fast(&format!( |
| 135 | "automatic dependency install failed.\n\nnpm ci:\n{ci_err}\n\nnpm install:\n{install_err}" |
| 136 | )); |
| 137 | } |
| 138 | } |
| 139 | if let Err(build_err) = run_npm(npm, &["run", "build"], dashboard_dir) { |
| 140 | fail_fast(&format!("automatic dashboard build failed.\n\n{build_err}")); |
| 141 | } |
| 142 | println!("cargo::warning=dashboard assets: npm build finished; embedding fresh dist files"); |
| 143 | } |
| 144 | |
| 145 | fn fnv_hash_bytes(hash: &mut u64, bytes: &[u8]) { |
| 146 | for byte in bytes { |
no test coverage detected