1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-05-22 10:21:03 +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
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 98 additions and 42 deletions

View File

@ -46,7 +46,7 @@ Articles and blog posts from around the web which cover Comprehensive Rust:
_[Rust Training at Scale | Rust Global @ RustConf 2024](https://youtu.be/7h5KyMqt2-Q?si=4M99HdWWxMaqN8Zr)_. _[Rust Training at Scale | Rust Global @ RustConf 2024](https://youtu.be/7h5KyMqt2-Q?si=4M99HdWWxMaqN8Zr)_.
What Google learnt from teaching Comprehensive Rust for more than two years. What Google learnt from teaching Comprehensive Rust for more than two years.
## Building ## Setup
The course is built using a few tools: The course is built using a few tools:
@ -55,10 +55,7 @@ The course is built using a few tools:
- [mdbook-i18n-helpers and i18n-report](https://github.com/google/mdbook-i18n-helpers) - [mdbook-i18n-helpers and i18n-report](https://github.com/google/mdbook-i18n-helpers)
- [mdbook-exerciser](mdbook-exerciser/) - [mdbook-exerciser](mdbook-exerciser/)
- [mdbook-course](mdbook-course/) - [mdbook-course](mdbook-course/)
- [mdbook-linkcheck](https://github.com/Michael-F-Bryan/mdbook-linkcheck)
In addition,
[mdbook-linkcheck](https://github.com/Michael-F-Bryan/mdbook-linkcheck) checks
the internal links.
First install Rust by following the instructions on https://rustup.rs/. Then First install Rust by following the instructions on https://rustup.rs/. Then
clone this repository: clone this repository:
@ -74,25 +71,17 @@ Then install these tools with:
cargo xtask install-tools cargo xtask install-tools
``` ```
Run ## Commands
```shell Here is a summary of the various commands you can run in the project.
mdbook test
```
to test all included Rust snippets. Run | Command | Description |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
```shell | `cargo xtask install-tools` | Install all the tools the project depends on. |
mdbook serve | `cargo xtask serve` | Start a web server with the course. You'll find the content on http://localhost:3000. |
``` | `cargo xtask rust-tests` | Test the included Rust snippets. |
| `cargo xtask web-tests` | Run the web driver tests in the tests directory. |
to start a web server with the course. You'll find the content on | `cargo xtask build` | Create a static version of the course in the `book/` directory. Note that you have to separately build and zip exercises and add them to book/html. To build any of the translated versions of the course, run MDBOOK_BOOK__LANGUAGE=xx mdbook build -d book/xx where xx is the ISO 639 language code (e.g. da for the Danish translation). [TRANSLATIONS.md](TRANSLATIONS.md) contains further instructions. |
<http://localhost:3000>. You can use `mdbook build` to create a static version
of the course in the `book/` directory. Note that you have to separately build
and zip exercises and add them to `book/html`. To build any of the translated
versions of the course, run `MDBOOK_BOOK__LANGUAGE=xx mdbook build -d book/xx`
where `xx` is the ISO 639 language code (e.g. `da` for the Danish translation).
[TRANSLATIONS.md](TRANSLATIONS.md) contains further instructions.
> **Note** On Windows, you need to enable symlinks > **Note** On Windows, you need to enable symlinks
> (`git config --global core.symlinks true`) and Developer Mode. > (`git config --global core.symlinks true`) and Developer Mode.

View File

@ -20,7 +20,7 @@
//! the tools. //! the tools.
use anyhow::{anyhow, Ok, Result}; use anyhow::{anyhow, Ok, Result};
use clap::Parser; use clap::{Parser, ValueEnum};
use std::path::Path; use std::path::Path;
use std::{env, process::Command}; use std::{env, process::Command};
@ -32,23 +32,38 @@ fn main() -> Result<()> {
Ok(()) Ok(())
} }
#[derive(Parser, Debug)] #[derive(Parser)]
#[command( #[command(
about = "Binary for executing tasks within the Comprehensive Rust project" about = "Binary for executing tasks within the Comprehensive Rust project"
)] )]
struct Args { struct Cli {
#[arg(required = true, help = "The task to execute")] /// The task to execute
task: String, #[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<()> { fn execute_task() -> Result<()> {
let task = Args::parse().task; let cli = Cli::parse();
match task.as_str() { match cli.task {
"install-tools" => install_tools()?, Task::InstallTools => install_tools()?,
"web-tests" => run_web_tests()?, Task::WebTests => run_web_tests()?,
_ => { Task::RustTests => run_rust_tests()?,
return Err(anyhow!(unrecognized_task_string(task.as_str()))); Task::Serve => start_web_server()?,
} Task::Build => build()?,
} }
Ok(()) Ok(())
} }
@ -109,7 +124,7 @@ fn run_web_tests() -> Result<()> {
if !status.success() { if !status.success() {
let error_message = format!( let error_message = format!(
"Command 'cargo web-tests' exited with status code: {}", "Command 'cargo xtask web-tests' exited with status code: {}",
status.code().unwrap() status.code().unwrap()
); );
return Err(anyhow!(error_message)); return Err(anyhow!(error_message));
@ -118,12 +133,64 @@ fn run_web_tests() -> Result<()> {
Ok(()) Ok(())
} }
// TODO - https://github.com/google/comprehensive-rust/issues/2741: Replace this with Clap fn run_rust_tests() -> Result<()> {
fn unrecognized_task_string(task: &str) -> String { println!("Running rust tests...");
format!(
"Unrecognized task '{task}'. Available tasks:
install-tools Installs the tools the project depends on. let path_to_workspace_root = Path::new(env!("CARGO_WORKSPACE_DIR"));
web-tests Runs the web driver tests in the tests directory."
) 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(())
} }