From abbaa3943e427750cb9a36265525a6370ba5f963 Mon Sep 17 00:00:00 2001 From: BD103 <59022059+BD103@users.noreply.github.com> Date: Mon, 29 Apr 2024 20:54:14 -0400 Subject: [PATCH] Small changes to `ci` tool (#13137) # Objective - Many of the items in the `ci` tool use `pub(crate)`, which is functionally equivalent to `pub` when the crate is not a library. - A few items are missing documentation. ## Solution - Make all `pub(crate)` items just `pub`. - `pub` is easier to type and less obscure, and there's not harm from this change. - Add / modify documentation on `CI`, `Prepare`, and `PreparedCommand`. --- tools/ci/src/ci.rs | 10 +++++-- tools/ci/src/commands/bench_check.rs | 2 +- tools/ci/src/commands/cfg_check.rs | 2 +- tools/ci/src/commands/clippy.rs | 2 +- tools/ci/src/commands/compile.rs | 2 +- tools/ci/src/commands/compile_check.rs | 2 +- tools/ci/src/commands/compile_fail.rs | 2 +- tools/ci/src/commands/doc.rs | 2 +- tools/ci/src/commands/doc_check.rs | 2 +- tools/ci/src/commands/doc_test.rs | 2 +- tools/ci/src/commands/example_check.rs | 2 +- tools/ci/src/commands/format.rs | 2 +- tools/ci/src/commands/lints.rs | 2 +- tools/ci/src/commands/mod.rs | 28 +++++++++--------- tools/ci/src/commands/test.rs | 2 +- tools/ci/src/commands/test_check.rs | 2 +- tools/ci/src/main.rs | 4 +-- tools/ci/src/prepare.rs | 39 ++++++++++++++++++++++++-- 18 files changed, 74 insertions(+), 35 deletions(-) diff --git a/tools/ci/src/ci.rs b/tools/ci/src/ci.rs index 30543c3c7d..953c2ca459 100644 --- a/tools/ci/src/ci.rs +++ b/tools/ci/src/ci.rs @@ -4,9 +4,10 @@ use argh::FromArgs; /// The CI command line tool for Bevy. #[derive(FromArgs)] -pub(crate) struct CI { +pub struct CI { #[argh(subcommand)] command: Option, + /// continue running commands even if one fails #[argh(switch)] keep_going: bool, @@ -16,7 +17,7 @@ impl CI { /// Runs the specified commands or all commands if none are specified. /// /// When run locally, results may differ from actual CI runs triggered by `.github/workflows/ci.yml`. - /// This is because the official CI runs latest stable, while local runs use whatever the default Rust is locally. + /// This is usually related to differing toolchains and configuration. pub fn run(self) { let sh = xshell::Shell::new().unwrap(); @@ -29,10 +30,13 @@ impl CI { // This will automatically move back to the original directory once dropped. let _subdir_hook = command.subdir.map(|path| sh.push_dir(path)); + // Execute each command, checking if it returned an error. if command.command.envs(command.env_vars).run().is_err() { let name = command.name; let message = command.failure_message; + if self.keep_going { + // We use bullet points here because there can be more than one error. failures.push(format!("- {name}: {message}")); } else { failures.push(format!("{name}: {message}")); @@ -41,8 +45,10 @@ impl CI { } } + // Log errors at the very end. if !failures.is_empty() { let failures = failures.join("\n"); + panic!( "One or more CI commands failed:\n\ {failures}" diff --git a/tools/ci/src/commands/bench_check.rs b/tools/ci/src/commands/bench_check.rs index 32b083fd15..6aa205a595 100644 --- a/tools/ci/src/commands/bench_check.rs +++ b/tools/ci/src/commands/bench_check.rs @@ -5,7 +5,7 @@ use xshell::cmd; /// Checks that the benches compile. #[derive(FromArgs, Default)] #[argh(subcommand, name = "bench-check")] -pub(crate) struct BenchCheckCommand {} +pub struct BenchCheckCommand {} impl Prepare for BenchCheckCommand { fn prepare<'a>(&self, sh: &'a xshell::Shell, _flags: Flag) -> Vec> { diff --git a/tools/ci/src/commands/cfg_check.rs b/tools/ci/src/commands/cfg_check.rs index 59146f5883..057b2fc48d 100644 --- a/tools/ci/src/commands/cfg_check.rs +++ b/tools/ci/src/commands/cfg_check.rs @@ -5,7 +5,7 @@ use xshell::cmd; /// Checks that the project compiles using the nightly compiler with cfg checks enabled. #[derive(FromArgs, Default)] #[argh(subcommand, name = "cfg-check")] -pub(crate) struct CfgCheckCommand {} +pub struct CfgCheckCommand {} impl Prepare for CfgCheckCommand { fn prepare<'a>(&self, sh: &'a xshell::Shell, _flags: Flag) -> Vec> { diff --git a/tools/ci/src/commands/clippy.rs b/tools/ci/src/commands/clippy.rs index 817249f03a..5e097c05a1 100644 --- a/tools/ci/src/commands/clippy.rs +++ b/tools/ci/src/commands/clippy.rs @@ -5,7 +5,7 @@ use xshell::cmd; /// Check for clippy warnings and errors. #[derive(FromArgs, Default)] #[argh(subcommand, name = "clippy")] -pub(crate) struct ClippyCommand {} +pub struct ClippyCommand {} impl Prepare for ClippyCommand { fn prepare<'a>(&self, sh: &'a xshell::Shell, _flags: Flag) -> Vec> { diff --git a/tools/ci/src/commands/compile.rs b/tools/ci/src/commands/compile.rs index bcb3b6f312..70234c88a5 100644 --- a/tools/ci/src/commands/compile.rs +++ b/tools/ci/src/commands/compile.rs @@ -8,7 +8,7 @@ use argh::FromArgs; /// Alias for running the `compile-fail`, `bench-check`, `example-check`, `compile-check`, and `test-check` subcommands. #[derive(FromArgs, Default)] #[argh(subcommand, name = "compile")] -pub(crate) struct CompileCommand {} +pub struct CompileCommand {} impl Prepare for CompileCommand { fn prepare<'a>(&self, sh: &'a xshell::Shell, flags: Flag) -> Vec> { diff --git a/tools/ci/src/commands/compile_check.rs b/tools/ci/src/commands/compile_check.rs index 8f3939951a..62d8a8da75 100644 --- a/tools/ci/src/commands/compile_check.rs +++ b/tools/ci/src/commands/compile_check.rs @@ -5,7 +5,7 @@ use xshell::cmd; /// Checks that the project compiles. #[derive(FromArgs, Default)] #[argh(subcommand, name = "compile-check")] -pub(crate) struct CompileCheckCommand {} +pub struct CompileCheckCommand {} impl Prepare for CompileCheckCommand { fn prepare<'a>(&self, sh: &'a xshell::Shell, _flags: Flag) -> Vec> { diff --git a/tools/ci/src/commands/compile_fail.rs b/tools/ci/src/commands/compile_fail.rs index 07d989b2b0..3bb4d18a8b 100644 --- a/tools/ci/src/commands/compile_fail.rs +++ b/tools/ci/src/commands/compile_fail.rs @@ -5,7 +5,7 @@ use xshell::cmd; /// Runs the compile-fail tests. #[derive(FromArgs, Default)] #[argh(subcommand, name = "compile-fail")] -pub(crate) struct CompileFailCommand {} +pub struct CompileFailCommand {} impl Prepare for CompileFailCommand { fn prepare<'a>(&self, sh: &'a xshell::Shell, flags: Flag) -> Vec> { diff --git a/tools/ci/src/commands/doc.rs b/tools/ci/src/commands/doc.rs index 9d1fbeab26..f4ccb089f2 100644 --- a/tools/ci/src/commands/doc.rs +++ b/tools/ci/src/commands/doc.rs @@ -5,7 +5,7 @@ use argh::FromArgs; /// Alias for running the `doc-test` and `doc-check` subcommands. #[derive(FromArgs, Default)] #[argh(subcommand, name = "doc")] -pub(crate) struct DocCommand {} +pub struct DocCommand {} impl Prepare for DocCommand { fn prepare<'a>(&self, sh: &'a xshell::Shell, flags: Flag) -> Vec> { diff --git a/tools/ci/src/commands/doc_check.rs b/tools/ci/src/commands/doc_check.rs index a678d0ca8f..cf346c7544 100644 --- a/tools/ci/src/commands/doc_check.rs +++ b/tools/ci/src/commands/doc_check.rs @@ -5,7 +5,7 @@ use xshell::cmd; /// Checks that all docs compile. #[derive(FromArgs, Default)] #[argh(subcommand, name = "doc-check")] -pub(crate) struct DocCheckCommand {} +pub struct DocCheckCommand {} impl Prepare for DocCheckCommand { fn prepare<'a>(&self, sh: &'a xshell::Shell, _flags: Flag) -> Vec> { diff --git a/tools/ci/src/commands/doc_test.rs b/tools/ci/src/commands/doc_test.rs index 4b64adb14b..c1ce22c3e6 100644 --- a/tools/ci/src/commands/doc_test.rs +++ b/tools/ci/src/commands/doc_test.rs @@ -5,7 +5,7 @@ use xshell::cmd; /// Runs all doc tests. #[derive(FromArgs, Default)] #[argh(subcommand, name = "doc-test")] -pub(crate) struct DocTestCommand {} +pub struct DocTestCommand {} impl Prepare for DocTestCommand { fn prepare<'a>(&self, sh: &'a xshell::Shell, flags: Flag) -> Vec> { diff --git a/tools/ci/src/commands/example_check.rs b/tools/ci/src/commands/example_check.rs index 696803d72d..d3d3f5ddf2 100644 --- a/tools/ci/src/commands/example_check.rs +++ b/tools/ci/src/commands/example_check.rs @@ -5,7 +5,7 @@ use xshell::cmd; /// Checks that the examples compile. #[derive(FromArgs, Default)] #[argh(subcommand, name = "example-check")] -pub(crate) struct ExampleCheckCommand {} +pub struct ExampleCheckCommand {} impl Prepare for ExampleCheckCommand { fn prepare<'a>(&self, sh: &'a xshell::Shell, _flags: Flag) -> Vec> { diff --git a/tools/ci/src/commands/format.rs b/tools/ci/src/commands/format.rs index f6b2933431..f5aacc5301 100644 --- a/tools/ci/src/commands/format.rs +++ b/tools/ci/src/commands/format.rs @@ -5,7 +5,7 @@ use xshell::cmd; /// Check code formatting. #[derive(FromArgs, Default)] #[argh(subcommand, name = "format")] -pub(crate) struct FormatCommand {} +pub struct FormatCommand {} impl Prepare for FormatCommand { fn prepare<'a>(&self, sh: &'a xshell::Shell, _flags: Flag) -> Vec> { diff --git a/tools/ci/src/commands/lints.rs b/tools/ci/src/commands/lints.rs index 1e714460be..ae6715a08b 100644 --- a/tools/ci/src/commands/lints.rs +++ b/tools/ci/src/commands/lints.rs @@ -5,7 +5,7 @@ use argh::FromArgs; /// Alias for running the `format` and `clippy` subcommands. #[derive(FromArgs, Default)] #[argh(subcommand, name = "lints")] -pub(crate) struct LintsCommand {} +pub struct LintsCommand {} impl Prepare for LintsCommand { fn prepare<'a>(&self, sh: &'a xshell::Shell, flags: Flag) -> Vec> { diff --git a/tools/ci/src/commands/mod.rs b/tools/ci/src/commands/mod.rs index a057c390fa..6b8cba6bf6 100644 --- a/tools/ci/src/commands/mod.rs +++ b/tools/ci/src/commands/mod.rs @@ -1,17 +1,17 @@ -pub(crate) use bench_check::*; -pub(crate) use cfg_check::*; -pub(crate) use clippy::*; -pub(crate) use compile::*; -pub(crate) use compile_check::*; -pub(crate) use compile_fail::*; -pub(crate) use doc::*; -pub(crate) use doc_check::*; -pub(crate) use doc_test::*; -pub(crate) use example_check::*; -pub(crate) use format::*; -pub(crate) use lints::*; -pub(crate) use test::*; -pub(crate) use test_check::*; +pub use bench_check::*; +pub use cfg_check::*; +pub use clippy::*; +pub use compile::*; +pub use compile_check::*; +pub use compile_fail::*; +pub use doc::*; +pub use doc_check::*; +pub use doc_test::*; +pub use example_check::*; +pub use format::*; +pub use lints::*; +pub use test::*; +pub use test_check::*; mod bench_check; mod cfg_check; diff --git a/tools/ci/src/commands/test.rs b/tools/ci/src/commands/test.rs index 5f0d552707..efb4f518dc 100644 --- a/tools/ci/src/commands/test.rs +++ b/tools/ci/src/commands/test.rs @@ -5,7 +5,7 @@ use xshell::cmd; /// Runs all tests (except for doc tests). #[derive(FromArgs, Default)] #[argh(subcommand, name = "test")] -pub(crate) struct TestCommand {} +pub struct TestCommand {} impl Prepare for TestCommand { fn prepare<'a>(&self, sh: &'a xshell::Shell, flags: Flag) -> Vec> { diff --git a/tools/ci/src/commands/test_check.rs b/tools/ci/src/commands/test_check.rs index 552c6c590b..81f11c214a 100644 --- a/tools/ci/src/commands/test_check.rs +++ b/tools/ci/src/commands/test_check.rs @@ -5,7 +5,7 @@ use xshell::cmd; /// Checks that all tests compile. #[derive(FromArgs, Default)] #[argh(subcommand, name = "test-check")] -pub(crate) struct TestCheckCommand {} +pub struct TestCheckCommand {} impl Prepare for TestCheckCommand { fn prepare<'a>(&self, sh: &'a xshell::Shell, _flags: Flag) -> Vec> { diff --git a/tools/ci/src/main.rs b/tools/ci/src/main.rs index 28fbe82dc1..0e7681ada1 100644 --- a/tools/ci/src/main.rs +++ b/tools/ci/src/main.rs @@ -4,8 +4,8 @@ mod ci; mod commands; mod prepare; -pub(crate) use self::ci::*; -pub(crate) use self::prepare::*; +pub use self::ci::*; +pub use self::prepare::*; fn main() { argh::from_env::().run(); diff --git a/tools/ci/src/prepare.rs b/tools/ci/src/prepare.rs index 46d09c3531..923bc33f80 100644 --- a/tools/ci/src/prepare.rs +++ b/tools/ci/src/prepare.rs @@ -1,20 +1,44 @@ use bitflags::bitflags; /// Trait for preparing a subcommand to be run. -pub(crate) trait Prepare { +pub trait Prepare { + /// A method that returns a list of [`PreparedCommand`]s to be run for a given shell and flags. + /// + /// # Example + /// + /// ``` + /// # use crate::{Flag, Prepare, PreparedCommand}; + /// # use argh::FromArgs; + /// # use xshell::Shell; + /// # + /// #[derive(FromArgs)] + /// #[argh(subcommand, name = "check")] + /// struct CheckCommand {} + /// + /// impl Prepare for CheckCommand { + /// fn prepare<'a>(&self, sh: &'a Shell, flags: Flag) -> Vec> { + /// vec![PreparedCommand::new::( + /// cmd!(sh, "cargo check --workspace"), + /// "Please fix linter errors", + /// )] + /// } + /// } + /// ``` fn prepare<'a>(&self, sh: &'a xshell::Shell, flags: Flag) -> Vec>; } bitflags! { + /// Flags that modify how commands are run. #[derive(Clone, Copy, Debug, PartialEq, Eq)] - pub(crate) struct Flag: u32 { + pub struct Flag: u32 { /// Forces certain checks to continue running even if they hit an error. const KEEP_GOING = 1 << 0; } } +/// A command with associated metadata, created from a command that implements [`Prepare`]. #[derive(Debug)] -pub(crate) struct PreparedCommand<'a> { +pub struct PreparedCommand<'a> { /// The name of the command. pub name: &'static str, @@ -32,6 +56,13 @@ pub(crate) struct PreparedCommand<'a> { } impl<'a> PreparedCommand<'a> { + /// Creates a new [`PreparedCommand`] from a [`Cmd`] and a failure message. + /// + /// The other fields of [`PreparedCommand`] are filled in with their default values. + /// + /// For more information about creating a [`Cmd`], please see the [`cmd!`](xshell::cmd) macro. + /// + /// [`Cmd`]: xshell::Cmd pub fn new( command: xshell::Cmd<'a>, failure_message: &'static str, @@ -45,11 +76,13 @@ impl<'a> PreparedCommand<'a> { } } + /// A builder that overwrites the current sub-directory with a new value. pub fn with_subdir(mut self, subdir: &'static str) -> Self { self.subdir = Some(subdir); self } + /// A builder that adds a new environmental variable to the list. pub fn with_env_var(mut self, key: &'static str, value: &'static str) -> Self { self.env_vars.push((key, value)); self