From 645c5d3ea2e56ee10f08a24e6f118852a5011229 Mon Sep 17 00:00:00 2001 From: Eric Githinji Date: Mon, 3 Mar 2025 06:31:41 +0000 Subject: [PATCH 1/7] Use one cross-platform command to install tools. This follows the approach in https://github.com/matklad/cargo-xtask and allow us to run `cargo xtask install-tools` from the project root to install the tools that comprehensive rust depends on, rather than using a bash script which is not truly cross platform. --- .cargo/config.toml | 2 + .github/workflows/install-mdbook/action.yml | 2 +- Cargo.lock | 6 ++- Cargo.toml | 3 +- xtask/Cargo.toml | 6 +++ xtask/src/main.rs | 48 +++++++++++++++++++++ 6 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 .cargo/config.toml create mode 100644 xtask/Cargo.toml create mode 100644 xtask/src/main.rs diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 000000000000..f0ccbc9a8846 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[alias] +xtask = "run --package xtask --" \ No newline at end of file diff --git a/.github/workflows/install-mdbook/action.yml b/.github/workflows/install-mdbook/action.yml index d46db7580deb..a0869d005e27 100644 --- a/.github/workflows/install-mdbook/action.yml +++ b/.github/workflows/install-mdbook/action.yml @@ -6,7 +6,7 @@ runs: using: composite steps: - name: Install mdbook - run: ./install-mdbook.sh + run: cargo xtask install-tools shell: bash - name: Install dependencies for mdbook-pandoc diff --git a/Cargo.lock b/Cargo.lock index 5dea16de6a8b..145e4d6c8a7b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -3703,6 +3703,10 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +[[package]] +name = "xtask" +version = "0.1.0" + [[package]] name = "yoke" version = "0.7.5" diff --git a/Cargo.toml b/Cargo.toml index 2452ca0753bd..a427c67f989b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ members = [ "src/types-and-values", "src/unsafe-rust", "src/user-defined-types", - "third_party/cxx/blobstore", + "third_party/cxx/blobstore", + "xtask", ] resolver = "2" diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml new file mode 100644 index 000000000000..337bfe3d6d6a --- /dev/null +++ b/xtask/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "xtask" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/xtask/src/main.rs b/xtask/src/main.rs new file mode 100644 index 000000000000..32b37ef5ba8f --- /dev/null +++ b/xtask/src/main.rs @@ -0,0 +1,48 @@ +use std::{ + env, + process::Command, +}; + +type DynError = Box; + +fn main() { + if let Err(e) = execute_task() { + eprintln!("{e}"); + std::process::exit(-1); + } +} + +fn execute_task() -> Result<(), DynError> { + let task = env::args().nth(1); + match task.as_deref() { + Some("install-tools") => install_tools()?, + _ => print_help(task.as_deref()), + } + Ok(()) +} + +fn install_tools() -> Result<(), DynError>{ + println!("Installing project tools..."); + Command::new(env!("CARGO")).arg("install").args(["mdbook", "--locked", "--version", "0.4.44"]).status()?; + Command::new(env!("CARGO")).arg("install").args(["mdbook-svgbob", "--locked", "--version", "0.2.1"]).status()?; + Command::new(env!("CARGO")).arg("install").args(["mdbook-pandoc", "--locked", "--version", "0.9.3"]).status()?; + Command::new(env!("CARGO")).arg("install").args(["mdbook-i18n-helpers", "--locked", "--version", "0.3.5"]).status()?; + Command::new(env!("CARGO")).arg("install").args(["i18n-report", "--locked", "--version", "0.2.0"]).status()?; + Command::new(env!("CARGO")).arg("install").args(["--path", "mdbook-exerciser", "--locked"]).status()?; + Command::new(env!("CARGO")).arg("install").args(["--path", "mdbook-course", "--locked"]).status()?; + Ok(()) +} + +fn print_help(task: Option<&str>) { + if let Some(t) = task { + eprintln!( + "Unrecognized task '{t}'. Available tasks: + +install-tools Installs the tools the project dependends on. + +Run with `cargo xtask [task]`. +"); + } else { + eprintln!("Missing task. To execute a task run `cargo xtask [task]`."); + } +} \ No newline at end of file From eeffce072af36ad52f2d7f0027f5b3af8954c238 Mon Sep 17 00:00:00 2001 From: Eric Githinji Date: Mon, 3 Mar 2025 06:48:05 +0000 Subject: [PATCH 2/7] Remove shell script and update README. --- README.md | 2 +- install-mdbook.sh | 11 ----------- xtask/src/main.rs | 3 +++ 3 files changed, 4 insertions(+), 12 deletions(-) delete mode 100755 install-mdbook.sh diff --git a/README.md b/README.md index db7ca9639cc6..1315de592232 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ cd comprehensive-rust Then install these tools with: ```shell -bash install-mdbook.sh +cargo xtask install-tools ``` Run diff --git a/install-mdbook.sh b/install-mdbook.sh deleted file mode 100755 index abd812585fc2..000000000000 --- a/install-mdbook.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -# The --locked flag is important for reproducible builds. It also -# avoids breakage due to skews between mdbook and mdbook-svgbob. -cargo install mdbook --locked --version 0.4.44 -cargo install mdbook-svgbob --locked --version 0.2.1 -cargo install mdbook-pandoc --locked --version 0.9.3 -cargo install mdbook-i18n-helpers --locked --version 0.3.5 -cargo install i18n-report --locked --version 0.2.0 -# these packages are located in this repository -cargo install --path mdbook-exerciser --locked -cargo install --path mdbook-course --locked diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 32b37ef5ba8f..ce675adbb261 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -23,11 +23,14 @@ fn execute_task() -> Result<(), DynError> { fn install_tools() -> Result<(), DynError>{ println!("Installing project tools..."); + // The --locked flag is important for reproducible builds. It also + // avoids breakage due to skews between mdbook and mdbook-svgbob. Command::new(env!("CARGO")).arg("install").args(["mdbook", "--locked", "--version", "0.4.44"]).status()?; Command::new(env!("CARGO")).arg("install").args(["mdbook-svgbob", "--locked", "--version", "0.2.1"]).status()?; Command::new(env!("CARGO")).arg("install").args(["mdbook-pandoc", "--locked", "--version", "0.9.3"]).status()?; Command::new(env!("CARGO")).arg("install").args(["mdbook-i18n-helpers", "--locked", "--version", "0.3.5"]).status()?; Command::new(env!("CARGO")).arg("install").args(["i18n-report", "--locked", "--version", "0.2.0"]).status()?; + // These packages are located in this repository Command::new(env!("CARGO")).arg("install").args(["--path", "mdbook-exerciser", "--locked"]).status()?; Command::new(env!("CARGO")).arg("install").args(["--path", "mdbook-course", "--locked"]).status()?; Ok(()) From 2cafbcd74bbedaf85ab73f6456e376cae0bb2b43 Mon Sep 17 00:00:00 2001 From: Eric Githinji Date: Mon, 3 Mar 2025 06:49:46 +0000 Subject: [PATCH 3/7] Format with dprint. --- .cargo/config.toml | 2 +- Cargo.toml | 2 +- xtask/src/main.rs | 55 +++++++++++++++++++++++++++++++--------------- 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index f0ccbc9a8846..35049cbcb13c 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,2 +1,2 @@ [alias] -xtask = "run --package xtask --" \ No newline at end of file +xtask = "run --package xtask --" diff --git a/Cargo.toml b/Cargo.toml index a427c67f989b..9402942f9571 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ members = [ "src/types-and-values", "src/unsafe-rust", "src/user-defined-types", - "third_party/cxx/blobstore", + "third_party/cxx/blobstore", "xtask", ] resolver = "2" diff --git a/xtask/src/main.rs b/xtask/src/main.rs index ce675adbb261..d05d924a04a5 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1,14 +1,11 @@ -use std::{ - env, - process::Command, -}; +use std::{env, process::Command}; type DynError = Box; fn main() { - if let Err(e) = execute_task() { + if let Err(e) = execute_task() { eprintln!("{e}"); - std::process::exit(-1); + std::process::exit(-1); } } @@ -21,31 +18,53 @@ fn execute_task() -> Result<(), DynError> { Ok(()) } -fn install_tools() -> Result<(), DynError>{ +fn install_tools() -> Result<(), DynError> { println!("Installing project tools..."); // The --locked flag is important for reproducible builds. It also // avoids breakage due to skews between mdbook and mdbook-svgbob. - Command::new(env!("CARGO")).arg("install").args(["mdbook", "--locked", "--version", "0.4.44"]).status()?; - Command::new(env!("CARGO")).arg("install").args(["mdbook-svgbob", "--locked", "--version", "0.2.1"]).status()?; - Command::new(env!("CARGO")).arg("install").args(["mdbook-pandoc", "--locked", "--version", "0.9.3"]).status()?; - Command::new(env!("CARGO")).arg("install").args(["mdbook-i18n-helpers", "--locked", "--version", "0.3.5"]).status()?; - Command::new(env!("CARGO")).arg("install").args(["i18n-report", "--locked", "--version", "0.2.0"]).status()?; + Command::new(env!("CARGO")) + .arg("install") + .args(["mdbook", "--locked", "--version", "0.4.44"]) + .status()?; + Command::new(env!("CARGO")) + .arg("install") + .args(["mdbook-svgbob", "--locked", "--version", "0.2.1"]) + .status()?; + Command::new(env!("CARGO")) + .arg("install") + .args(["mdbook-pandoc", "--locked", "--version", "0.9.3"]) + .status()?; + Command::new(env!("CARGO")) + .arg("install") + .args(["mdbook-i18n-helpers", "--locked", "--version", "0.3.5"]) + .status()?; + Command::new(env!("CARGO")) + .arg("install") + .args(["i18n-report", "--locked", "--version", "0.2.0"]) + .status()?; // These packages are located in this repository - Command::new(env!("CARGO")).arg("install").args(["--path", "mdbook-exerciser", "--locked"]).status()?; - Command::new(env!("CARGO")).arg("install").args(["--path", "mdbook-course", "--locked"]).status()?; + Command::new(env!("CARGO")) + .arg("install") + .args(["--path", "mdbook-exerciser", "--locked"]) + .status()?; + Command::new(env!("CARGO")) + .arg("install") + .args(["--path", "mdbook-course", "--locked"]) + .status()?; Ok(()) } fn print_help(task: Option<&str>) { if let Some(t) = task { - eprintln!( - "Unrecognized task '{t}'. Available tasks: + eprintln!( + "Unrecognized task '{t}'. Available tasks: install-tools Installs the tools the project dependends on. Run with `cargo xtask [task]`. -"); +" + ); } else { eprintln!("Missing task. To execute a task run `cargo xtask [task]`."); } -} \ No newline at end of file +} From d8162021b49ee6cfd965dd01af4503b19d31c5ab Mon Sep 17 00:00:00 2001 From: Eric Githinji Date: Tue, 4 Mar 2025 18:29:51 +0000 Subject: [PATCH 4/7] Fix typo. --- xtask/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xtask/src/main.rs b/xtask/src/main.rs index d05d924a04a5..9da61ab1f2e9 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -59,7 +59,7 @@ fn print_help(task: Option<&str>) { eprintln!( "Unrecognized task '{t}'. Available tasks: -install-tools Installs the tools the project dependends on. +install-tools Installs the tools the project depends on. Run with `cargo xtask [task]`. " From 00bacc57774d1ffc36404417069783a52fa8c056 Mon Sep 17 00:00:00 2001 From: Eric Githinji Date: Tue, 4 Mar 2025 19:19:54 +0000 Subject: [PATCH 5/7] Extract args into an array of arrays for better readability. --- xtask/src/main.rs | 52 +++++++++++++++++++---------------------------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 9da61ab1f2e9..53ca1140d05e 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -2,6 +2,19 @@ use std::{env, process::Command}; type DynError = Box; +const INSTALLATION_ARGS: [[&str; 4]; 7] = [ + // The --locked flag is important for reproducible builds. It also + // avoids breakage due to skews between mdbook and mdbook-svgbob. + ["mdbook", "--locked", "--version", "0.4.44"], + ["mdbook-svgbob", "--locked", "--version", "0.2.1"], + ["mdbook-pandoc", "--locked", "--version", "0.9.3"], + ["mdbook-i18n-helpers", "--locked", "--version", "0.3.5"], + ["i18n-report", "--locked", "--version", "0.2.0"], + // These packages are located in this repository + ["--path", "mdbook-exerciser", "--locked", ""], + ["--path", "mdbook-course", "--locked", ""], +]; + fn main() { if let Err(e) = execute_task() { eprintln!("{e}"); @@ -20,37 +33,14 @@ fn execute_task() -> Result<(), DynError> { fn install_tools() -> Result<(), DynError> { println!("Installing project tools..."); - // The --locked flag is important for reproducible builds. It also - // avoids breakage due to skews between mdbook and mdbook-svgbob. - Command::new(env!("CARGO")) - .arg("install") - .args(["mdbook", "--locked", "--version", "0.4.44"]) - .status()?; - Command::new(env!("CARGO")) - .arg("install") - .args(["mdbook-svgbob", "--locked", "--version", "0.2.1"]) - .status()?; - Command::new(env!("CARGO")) - .arg("install") - .args(["mdbook-pandoc", "--locked", "--version", "0.9.3"]) - .status()?; - Command::new(env!("CARGO")) - .arg("install") - .args(["mdbook-i18n-helpers", "--locked", "--version", "0.3.5"]) - .status()?; - Command::new(env!("CARGO")) - .arg("install") - .args(["i18n-report", "--locked", "--version", "0.2.0"]) - .status()?; - // These packages are located in this repository - Command::new(env!("CARGO")) - .arg("install") - .args(["--path", "mdbook-exerciser", "--locked"]) - .status()?; - Command::new(env!("CARGO")) - .arg("install") - .args(["--path", "mdbook-course", "--locked"]) - .status()?; + + for args in INSTALLATION_ARGS.iter() { + Command::new(env!("CARGO")) + .arg("install") + .args(args.iter().filter(|a| **a != "")) + .status()?; + } + Ok(()) } From c9fef6e4fabdde3e8db098edc54e0ba29a29a936 Mon Sep 17 00:00:00 2001 From: Eric Githinji Date: Thu, 6 Mar 2025 09:49:49 +0000 Subject: [PATCH 6/7] Improve error handling to work well in CI. --- xtask/src/main.rs | 59 ++++++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 53ca1140d05e..c80bef41c194 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -2,19 +2,6 @@ use std::{env, process::Command}; type DynError = Box; -const INSTALLATION_ARGS: [[&str; 4]; 7] = [ - // The --locked flag is important for reproducible builds. It also - // avoids breakage due to skews between mdbook and mdbook-svgbob. - ["mdbook", "--locked", "--version", "0.4.44"], - ["mdbook-svgbob", "--locked", "--version", "0.2.1"], - ["mdbook-pandoc", "--locked", "--version", "0.9.3"], - ["mdbook-i18n-helpers", "--locked", "--version", "0.3.5"], - ["i18n-report", "--locked", "--version", "0.2.0"], - // These packages are located in this repository - ["--path", "mdbook-exerciser", "--locked", ""], - ["--path", "mdbook-course", "--locked", ""], -]; - fn main() { if let Err(e) = execute_task() { eprintln!("{e}"); @@ -26,7 +13,9 @@ fn execute_task() -> Result<(), DynError> { let task = env::args().nth(1); match task.as_deref() { Some("install-tools") => install_tools()?, - _ => print_help(task.as_deref()), + _ => { + return Err(Box::from(get_help_string(task.as_deref()))); + } } Ok(()) } @@ -34,27 +23,49 @@ fn execute_task() -> Result<(), DynError> { fn install_tools() -> Result<(), DynError> { println!("Installing project tools..."); - for args in INSTALLATION_ARGS.iter() { - Command::new(env!("CARGO")) + let install_args: Vec> = vec![ + // The --locked flag is important for reproducible builds. It also + // avoids breakage due to skews between mdbook and mdbook-svgbob. + vec!["mdbook", "--locked", "--version", "0.4.44"], + vec!["mdbook-svgbob", "--locked", "--version", "0.2.1"], + vec!["mdbook-pandoc", "--locked", "--version", "0.9.3"], + vec!["mdbook-i18n-helpers", "--locked", "--version", "0.3.5"], + vec!["i18n-report", "--locked", "--version", "0.2.0"], + // These packages are located in this repository + vec!["--path", "mdbook-exerciser", "--locked"], + vec!["--path", "mdbook-course", "--locked"], + ]; + + for args in &install_args { + let status = Command::new(env!("CARGO")) .arg("install") - .args(args.iter().filter(|a| **a != "")) - .status()?; + .args(args) + .status() + .expect("Failed to execute cargo install"); + + if !status.success() { + let error_message = format!( + "cargo install {} {} exited with status code: {}", + args.get(0).unwrap(), + args.get(1).unwrap(), + status.code().unwrap() + ); + return Err(Box::from(error_message)); + } } Ok(()) } -fn print_help(task: Option<&str>) { +fn get_help_string(task: Option<&str>) -> String { if let Some(t) = task { - eprintln!( + format!( "Unrecognized task '{t}'. Available tasks: install-tools Installs the tools the project depends on. - -Run with `cargo xtask [task]`. " - ); + ) } else { - eprintln!("Missing task. To execute a task run `cargo xtask [task]`."); + "Missing task. To execute a task run `cargo xtask [task]`.".to_string() } } From 78399232797a3733f01f835a8dcbb92578b7b7a9 Mon Sep 17 00:00:00 2001 From: Eric Githinji Date: Thu, 6 Mar 2025 12:45:41 +0000 Subject: [PATCH 7/7] Print full command in error and remove unnecessary new line. --- xtask/src/main.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/xtask/src/main.rs b/xtask/src/main.rs index c80bef41c194..8ec42909c0ad 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -45,9 +45,8 @@ fn install_tools() -> Result<(), DynError> { if !status.success() { let error_message = format!( - "cargo install {} {} exited with status code: {}", - args.get(0).unwrap(), - args.get(1).unwrap(), + "Command 'cargo install {}' exited with status code: {}", + args.join(" "), status.code().unwrap() ); return Err(Box::from(error_message)); @@ -62,8 +61,7 @@ fn get_help_string(task: Option<&str>) -> String { format!( "Unrecognized task '{t}'. Available tasks: -install-tools Installs the tools the project depends on. -" +install-tools Installs the tools the project depends on." ) } else { "Missing task. To execute a task run `cargo xtask [task]`.".to_string()