diff --git a/tools/ci/src/main.rs b/tools/ci/src/main.rs index 39f0f5a2e42..24b98bd6484 100644 --- a/tools/ci/src/main.rs +++ b/tools/ci/src/main.rs @@ -2,7 +2,7 @@ use anyhow::{bail, Result}; use clap::{CommandFactory, Parser, Subcommand}; -use duct::cmd; +use duct::{cmd, Expression}; use serde_json::Value; use std::ffi::OsStr; use std::ffi::OsString; @@ -20,6 +20,24 @@ mod util; use util::ensure_repo_root; +/// On Windows, `pnpm` is installed as a `.cmd` shim which `CreateProcess` cannot +/// find without going through the shell. Wrapping with `cmd /c` fixes this. +/// On Unix, we invoke `pnpm` directly. +fn pnpm(args: I) -> Expression +where + I: IntoIterator, + S: AsRef, +{ + let args: Vec = args.into_iter().map(|a| a.as_ref().to_os_string()).collect(); + if cfg!(windows) { + let mut full: Vec = vec!["/c".into(), "pnpm".into()]; + full.extend(args); + cmd("cmd", full) + } else { + cmd("pnpm", args) + } +} + /// SpacetimeDB CI tasks /// /// This tool provides several subcommands for automating CI workflows in SpacetimeDB. @@ -432,9 +450,9 @@ fn run_publish_checks() -> Result<()> { } fn run_typescript_tests() -> Result<()> { - cmd!("pnpm", "build").dir("crates/bindings-typescript").run()?; - cmd!("pnpm", "test").dir("crates/bindings-typescript").run()?; - cmd!("pnpm", "generate").dir("templates/chat-react-ts").run()?; + pnpm(["build"]).dir("crates/bindings-typescript").run()?; + pnpm(["test"]).dir("crates/bindings-typescript").run()?; + pnpm(["generate"]).dir("templates/chat-react-ts").run()?; let diff_status = cmd!( "bash", "tools/check-diff.sh", @@ -444,19 +462,19 @@ fn run_typescript_tests() -> Result<()> { if !diff_status.status.success() { bail!("Bindings are dirty. Please generate bindings again and commit them to this branch."); } - cmd!("pnpm", "build").dir("templates/chat-react-ts").run()?; - cmd!("pnpm", "-r", "--filter", "./**", "run", "build") + pnpm(["build"]).dir("templates/chat-react-ts").run()?; + pnpm(["-r", "--filter", "./**", "run", "build"]) .dir("templates") .run()?; - cmd!("pnpm", "-r", "--filter", "./**", "run", "build") + pnpm(["-r", "--filter", "./**", "run", "build"]) .dir("crates/bindings-typescript") .run()?; Ok(()) } fn run_docs_build() -> Result<()> { - cmd!("pnpm", "install").dir("docs").run()?; - cmd!("pnpm", "build").dir("docs").run()?; + pnpm(["install"]).dir("docs").run()?; + pnpm(["build"]).dir("docs").run()?; Ok(()) } @@ -482,7 +500,7 @@ fn main() -> Result<()> { match cli.cmd { Some(CiCmd::Test) => { - cmd!("pnpm", "build").dir("crates/bindings-typescript").run()?; + pnpm(["build"]).dir("crates/bindings-typescript").run()?; // TODO: This doesn't work on at least user Linux machines, because something here apparently uses `sudo`? @@ -635,7 +653,7 @@ fn main() -> Result<()> { cmd!("dotnet", "csharpier", "--check", ".") .dir("crates/bindings-csharp") .run()?; - cmd!("pnpm", "lint").run()?; + pnpm(["lint"]).run()?; cmd!("cargo", "test", "--doc", "--target", "wasm32-unknown-unknown") .dir("crates/bindings") .run()?; @@ -745,8 +763,8 @@ fn main() -> Result<()> { ); } - cmd!("pnpm", "install", "--recursive").run()?; - cmd!("pnpm", "generate-cli-docs").dir("docs").run()?; + pnpm(["install", "--recursive"]).run()?; + pnpm(["generate-cli-docs"]).dir("docs").run()?; let out = cmd!("git", "status", "--porcelain", "--", "docs").read()?; if out.is_empty() { log::info!("No docs changes detected");