1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-11-30 17:15:23 +02:00

Simplify project commands using cargo xtask (#2753)

We are already using `cargo xtask install-tools` to install the
project's tools, and `cargo xtask web-tests` to run the js tests. In
this PR we provide support for the various `mdbook` commands
(`test`,`serve`, and `build`) with `cargo xtask` commands. This provides
a uniform interface for running tasks in the project. Additionally it
allows these commands to work from within any dirrectory (previously
you'd need to navigate to the workspace root in order to run say `mdbook
build`).

Additionally we're improving the xtask code by making use of `Clap`
enums to handle validation of the possible tasks to run via xtask (this
closes #2741 ).

---------

Co-authored-by: Eric Githinji <egithinji@google.com>
This commit is contained in:
Eric Githinji
2025-05-21 09:58:52 +03:00
committed by GitHub
parent ef20b048ee
commit 738d5ad820
2 changed files with 98 additions and 42 deletions

View File

@@ -20,7 +20,7 @@
//! the tools.
use anyhow::{anyhow, Ok, Result};
use clap::Parser;
use clap::{Parser, ValueEnum};
use std::path::Path;
use std::{env, process::Command};
@@ -32,23 +32,38 @@ fn main() -> Result<()> {
Ok(())
}
#[derive(Parser, Debug)]
#[derive(Parser)]
#[command(
about = "Binary for executing tasks within the Comprehensive Rust project"
)]
struct Args {
#[arg(required = true, help = "The task to execute")]
task: String,
struct Cli {
/// The task to execute
#[arg(value_enum)]
task: Task,
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
enum Task {
/// Installs the tools the project depends on.
InstallTools,
/// Runs the web driver tests in the tests directory.
WebTests,
/// Tests all included Rust snippets.
RustTests,
/// Starts a web server with the course.
Serve,
/// Create a static version of the course in the `book/` directory.
Build,
}
fn execute_task() -> Result<()> {
let task = Args::parse().task;
match task.as_str() {
"install-tools" => install_tools()?,
"web-tests" => run_web_tests()?,
_ => {
return Err(anyhow!(unrecognized_task_string(task.as_str())));
}
let cli = Cli::parse();
match cli.task {
Task::InstallTools => install_tools()?,
Task::WebTests => run_web_tests()?,
Task::RustTests => run_rust_tests()?,
Task::Serve => start_web_server()?,
Task::Build => build()?,
}
Ok(())
}
@@ -109,7 +124,7 @@ fn run_web_tests() -> Result<()> {
if !status.success() {
let error_message = format!(
"Command 'cargo web-tests' exited with status code: {}",
"Command 'cargo xtask web-tests' exited with status code: {}",
status.code().unwrap()
);
return Err(anyhow!(error_message));
@@ -118,12 +133,64 @@ fn run_web_tests() -> Result<()> {
Ok(())
}
// TODO - https://github.com/google/comprehensive-rust/issues/2741: Replace this with Clap
fn unrecognized_task_string(task: &str) -> String {
format!(
"Unrecognized task '{task}'. Available tasks:
fn run_rust_tests() -> Result<()> {
println!("Running rust tests...");
install-tools Installs the tools the project depends on.
web-tests Runs the web driver tests in the tests directory."
)
let path_to_workspace_root = Path::new(env!("CARGO_WORKSPACE_DIR"));
let status = Command::new("mdbook")
.current_dir(path_to_workspace_root.to_str().unwrap())
.arg("test")
.status()
.expect("Failed to execute mdbook test");
if !status.success() {
let error_message = format!(
"Command 'cargo xtask rust-tests' exited with status code: {}",
status.code().unwrap()
);
return Err(anyhow!(error_message));
}
Ok(())
}
fn start_web_server() -> Result<()> {
println!("Starting web server ...");
let path_to_workspace_root = Path::new(env!("CARGO_WORKSPACE_DIR"));
let status = Command::new("mdbook")
.current_dir(path_to_workspace_root.to_str().unwrap())
.arg("serve")
.status()
.expect("Failed to execute mdbook serve");
if !status.success() {
let error_message = format!(
"Command 'cargo xtask serve' exited with status code: {}",
status.code().unwrap()
);
return Err(anyhow!(error_message));
}
Ok(())
}
fn build() -> Result<()> {
println!("Building course...");
let path_to_workspace_root = Path::new(env!("CARGO_WORKSPACE_DIR"));
let status = Command::new("mdbook")
.current_dir(path_to_workspace_root.to_str().unwrap())
.arg("build")
.status()
.expect("Failed to execute mdbook build");
if !status.success() {
let error_message = format!(
"Command 'cargo xtask build' exited with status code: {}",
status.code().unwrap()
);
return Err(anyhow!(error_message));
}
Ok(())
}