max / makenotwork
1 file changed,
+26 insertions,
-13 deletions
| @@ -87,30 +87,43 @@ fn write_if_changed(path: &Path, contents: &str) { | |||
| 87 | 87 | /// Compile the TypeScript frontend (`frontend/`) to browser ESM in | |
| 88 | 88 | /// `static/dist/` via `npm run build` (which runs `tsc`). | |
| 89 | 89 | /// | |
| 90 | - | /// Best-effort and non-fatal: a missing `node_modules` (deps not installed), | |
| 91 | - | /// an absent Node, or a compile error only emits a `cargo::warning` and leaves | |
| 92 | - | /// the Rust build to succeed against whatever `static/dist/` already holds. | |
| 93 | - | /// Dependency install (`npm install` in `frontend/`) is a manual/deploy step, | |
| 94 | - | /// not build.rs's job. Set `MNW_SKIP_FRONTEND_BUILD=1` to opt out entirely. | |
| 95 | - | /// | |
| 96 | - | /// Prereq for the deploy pipeline once a template references `static/dist/`: | |
| 97 | - | /// the build host must have Node and have run `npm install` in `frontend/`. | |
| 90 | + | /// Self-contained: on a fresh checkout or a new build host (no `node_modules`) | |
| 91 | + | /// it runs `npm ci` first, so there is no manual install gate before a deploy. | |
| 92 | + | /// Best-effort and non-fatal otherwise — an absent Node or a compile error only | |
| 93 | + | /// emits a `cargo::warning` and leaves the Rust build to succeed against | |
| 94 | + | /// whatever `static/dist/` already holds. Set `MNW_SKIP_FRONTEND_BUILD=1` to | |
| 95 | + | /// opt out entirely (e.g. a Node-less CI that doesn't need the JS). | |
| 98 | 96 | fn build_frontend() { | |
| 99 | 97 | // Re-run the whole build script when the TS sources or its config change. | |
| 100 | 98 | println!("cargo::rerun-if-changed=frontend/src"); | |
| 101 | 99 | println!("cargo::rerun-if-changed=frontend/package.json"); | |
| 100 | + | println!("cargo::rerun-if-changed=frontend/package-lock.json"); | |
| 102 | 101 | println!("cargo::rerun-if-changed=frontend/tsconfig.json"); | |
| 103 | 102 | ||
| 104 | 103 | if std::env::var_os("MNW_SKIP_FRONTEND_BUILD").is_some() { | |
| 105 | 104 | println!("cargo::warning=frontend build skipped (MNW_SKIP_FRONTEND_BUILD set)"); | |
| 106 | 105 | return; | |
| 107 | 106 | } | |
| 107 | + | // Fresh checkout / new build host: install deps once (clean, from the | |
| 108 | + | // lockfile) so the frontend build needs no manual `npm install` gate before | |
| 109 | + | // a deploy. Skipped once node_modules exists; needs network on this run. | |
| 108 | 110 | if !Path::new("frontend/node_modules").is_dir() { | |
| 109 | - | println!( | |
| 110 | - | "cargo::warning=frontend/node_modules missing — run `npm install` in server/frontend; \ | |
| 111 | - | skipping TypeScript build (serving existing static/dist)" | |
| 112 | - | ); | |
| 113 | - | return; | |
| 111 | + | match Command::new("npm").args(["ci"]).current_dir("frontend").status() { | |
| 112 | + | Ok(s) if s.success() => {} | |
| 113 | + | Ok(s) => { | |
| 114 | + | println!( | |
| 115 | + | "cargo::warning=npm ci failed (exit {:?}); skipping frontend build (serving existing static/dist)", | |
| 116 | + | s.code() | |
| 117 | + | ); | |
| 118 | + | return; | |
| 119 | + | } | |
| 120 | + | Err(e) => { | |
| 121 | + | println!( | |
| 122 | + | "cargo::warning=could not run npm ({e}); is Node installed? skipping frontend build (serving existing static/dist)" | |
| 123 | + | ); | |
| 124 | + | return; | |
| 125 | + | } | |
| 126 | + | } | |
| 114 | 127 | } | |
| 115 | 128 | match Command::new("npm") | |
| 116 | 129 | .args(["run", "build"]) |