diff options
| author | Owen Jacobson <owen@grimoire.ca> | 2025-06-11 23:29:30 -0400 |
|---|---|---|
| committer | Owen Jacobson <owen@grimoire.ca> | 2025-06-11 23:33:18 -0400 |
| commit | ddef0916de13949e800a63fa3490a73e98996fa2 (patch) | |
| tree | 83b2d65f928498a65b4518858dd736422741380c | |
| parent | 6e6b068ae2adc8c5ef8acb633dcadfbdc3221b61 (diff) | |
Use `npm ci` for automated package installation.
From its documentation:
> This command is similar to `npm install`, except it's meant to be used in automated environments such as test platforms, continuous integration, and deployment -- or any situation where you want to make sure you're doing a clean install of your dependencies.
We don't need a clean install, necessarily - just a complete one that matches the package configuration. However, this command is clearly documented as being used for automated environments, and I think integration with another build tool is close enough to that intention to fit.
It also promises not to rewrite `package.json` or `package-lock.json`. (`npm install`, on the other hand, rewrites `package-lock.json` regularly.) As we do not intend to change the source tree when building it, this is the preferred behaviour.
Finally, this fixes a behaviour I encountered where certain `cargo` commands - sometimes including `cargo build` - could completely reformat `package-lock.json` without any warning and without any user-visible rationale for it.
| -rw-r--r-- | build.rs | 25 |
1 files changed, 18 insertions, 7 deletions
@@ -4,19 +4,30 @@ fn main() -> Result<(), io::Error> { // trigger recompilation when a new migration is added println!("cargo::rerun-if-changed=migrations"); - // rerun npm install whenever packages or npm config are changed + // The following sections are intended to allow developers and packagers to create a working + // `pilcrow` binary in one step in a clean source tree, using Cargo, even though Pilcrow is + // written in two-and-a-half languages. + // + // The final binary embeds the Svelte UI. These steps build it. And, in service of that one-step + // build idea, they also install the NPM dependencies needed to carry out that build. (Cargo + // does this out of the box for Rust dependencies.) + + // rerun npm ci whenever packages or npm config are changed println!("cargo::rerun-if-changed=.npmrc"); println!("cargo::rerun-if-changed=package.json"); - // `node_modules` and `package-lock.json` are always touched if `npm install` - // runs, leading to spurious rebuilds. + println!("cargo::rerun-if-changed=package-lock.json"); + // In theory, we should rerun `npm ci` if `node_modules` has changed since the last build, to + // put it back into a known-good state. However, `npm ci` itself _always_ rewrites + // `node_modules`, so asking Cargo to rerun this build script if `node_modules` changes leads to + // Cargo always rerunning this build script. So, as a compromise, we assume that changes to + // `package-lock.json` or `package.json` are sufficient justification to rerun `npm ci`, because + // those are the most likely secondary indicators of changes to the installed packages. // - // See: <https://github.com/npm/cli/issues/7874> - // println!("cargo::rerun-if-changed=package-lock.json"); // println!("cargo::rerun-if-changed=node_modules"); - let status = Command::new("npm").args(["install"]).status()?; + let status = Command::new("npm").args(["ci"]).status()?; if !status.success() { return Err(io::Error::other(format!( - "'npm install' exited with status {status:?}" + "'npm ci' exited with status {status:?}" ))); } |
