diff options
Diffstat (limited to '.run/src/bin/ci.rs')
| -rw-r--r-- | .run/src/bin/ci.rs | 201 |
1 files changed, 152 insertions, 49 deletions
diff --git a/.run/src/bin/ci.rs b/.run/src/bin/ci.rs index 39d55eb..c090eaa 100644 --- a/.run/src/bin/ci.rs +++ b/.run/src/bin/ci.rs @@ -11,17 +11,47 @@ fn get_ignore_dirs() -> Vec<String> { vec![".temp".to_string()] } +/// A single CI step, each individually toggleable via `--check-*`. +struct Checks { + build: bool, + clippy: bool, + test: bool, + arg_picker: bool, + markdown_code: bool, + examples: bool, + docs_refresh: bool, + api_docs: bool, +} + +impl Checks { + fn any(&self) -> bool { + self.build + || self.clippy + || self.test + || self.arg_picker + || self.markdown_code + || self.examples + || self.docs_refresh + || self.api_docs + } +} + fn print_help() { println!( r" Usage: ci [options] Options: - -h, --help Print this help message - -y Auto-confirm temporary commits - --dirty Run CI on dirty workspace (skip temp commit & clean check) - --refresh-docs Refresh documentation files - --test-docs Run documentation tests (build, clippy, test) - --test-codes Test examples and documentation code blocks + -h, --help Print this help message + -y Auto-confirm temporary commits + --dirty Run CI on dirty workspace (skip temp commit & clean check) + --check-build Build all crates + --check-clippy Run clippy on all crates (-D warnings) + --check-test Run unit tests for all crates + --check-arg-picker Test the arg-picker crate + --check-markdown-code Verify all *.md code blocks compile + --check-examples Test all examples + --check-docs-refresh Refresh docs and fail if the tree is contaminated + --check-api-docs Build API docs with docs.rs features If no specific options are given, all checks are run. " @@ -33,12 +63,29 @@ fn main() { let _ = colored::control::set_virtual_terminal(true); println!("{}", include_str!("../../../docs/res/ci_banner.txt")); - let (auto_yes, dirty, test_docs, refresh_docs, test_codes, help) = Picker::from_args() + let ( + auto_yes, + dirty, + check_build, + check_clippy, + check_test, + check_arg_picker, + check_markdown_code, + check_examples, + check_docs_refresh, + check_api_docs, + help, + ) = Picker::from_args() .pick_or_default(&arg![yes: bool, 'y']) .pick_or_default(&arg![dirty: bool]) - .pick_or_default(&arg![test_docs: bool]) - .pick_or_default(&arg![refresh_docs: bool]) - .pick_or_default(&arg![test_codes: bool]) + .pick_or_default(&arg![check_build: bool]) + .pick_or_default(&arg![check_clippy: bool]) + .pick_or_default(&arg![check_test: bool]) + .pick_or_default(&arg![check_arg_picker: bool]) + .pick_or_default(&arg![check_markdown_code: bool]) + .pick_or_default(&arg![check_examples: bool]) + .pick_or_default(&arg![check_docs_refresh: bool]) + .pick_or_default(&arg![check_api_docs: bool]) .pick_or_default(&arg![help: bool, 'h']) .unwrap(); @@ -47,8 +94,17 @@ fn main() { return; } - let any_specified = test_docs || refresh_docs || test_codes; - let run_all = !any_specified; + let checks = Checks { + build: check_build, + clippy: check_clippy, + test: check_test, + arg_picker: check_arg_picker, + markdown_code: check_markdown_code, + examples: check_examples, + docs_refresh: check_docs_refresh, + api_docs: check_api_docs, + }; + let run_all = !checks.any(); let needs_commit_temp = !dirty && !{ run_cmd!("git diff-index --quiet HEAD --").is_ok() }; @@ -72,7 +128,7 @@ fn main() { } } - if let Err(exit_code) = ci(test_docs, test_codes, run_all) { + if let Err(exit_code) = ci(&checks, run_all) { restore_workspace(needs_commit_temp).unwrap(); exit(exit_code) } @@ -109,47 +165,94 @@ fn restore_workspace(undo_commit: bool) -> Result<(), i32> { Ok(()) } -fn ci(test_docs: bool, test_codes: bool, run_all: bool) -> Result<(), i32> { - if run_all || test_codes { - println_cargo_style!("Phase: Scan and build all crates"); - build_all()?; - - println_cargo_style!("Phase: Run clippy for all crates"); - clippy_all()?; - - println_cargo_style!("Phase: Test all crates"); - test_all()?; - - println_cargo_style!("Phase: Test arg picker"); - test_arg_picker()?; - } - - if run_all || test_docs { - let mut exit_code = 0; - - println_cargo_style!("Phase: Verify all *.md document code blocks are compilable"); - if let Err(code) = test_docs_code_blocks() { - exit_code = exit_code.max(code); +/// Run one CI step. +/// +/// When `continue_on_error` is set (used for the documentation steps in +/// "run all" mode), a failing step is recorded and the remaining steps still +/// execute, so every problem is reported in a single run. +fn run_step( + exit_code: &mut i32, + phase: &str, + step: fn() -> Result<(), i32>, + continue_on_error: bool, +) -> Result<(), i32> { + println_cargo_style!(phase); + match step() { + Ok(()) => Ok(()), + Err(code) if continue_on_error => { + *exit_code = (*exit_code).max(code); + Ok(()) } + Err(code) => Err(code), + } +} - println_cargo_style!("Phase: Test all examples"); - if let Err(code) = test_examples() { - exit_code = exit_code.max(code); - } +fn ci(checks: &Checks, run_all: bool) -> Result<(), i32> { + let mut exit_code = 0; - println_cargo_style!("Phase: Check all documentation is up to date"); - if let Err(code) = docs_refresh() { - exit_code = exit_code.max(code); - } + if run_all || checks.build { + run_step( + &mut exit_code, + "Phase: Scan and build all crates", + build_all, + false, + )?; + } + if run_all || checks.clippy { + run_step( + &mut exit_code, + "Phase: Run clippy for all crates", + clippy_all, + false, + )?; + } + if run_all || checks.test { + run_step(&mut exit_code, "Phase: Test all crates", test_all, false)?; + } + if run_all || checks.arg_picker { + run_step( + &mut exit_code, + "Phase: Test arg picker", + test_arg_picker, + false, + )?; + } - println_cargo_style!("Phase: Try Build API docs"); - if let Err(code) = deploy_api_docs() { - exit_code = exit_code.max(code); - } + if run_all || checks.markdown_code { + run_step( + &mut exit_code, + "Phase: Verify all *.md document code blocks are compilable", + test_docs_code_blocks, + run_all, + )?; + } + if run_all || checks.examples { + run_step( + &mut exit_code, + "Phase: Test all examples", + test_examples, + run_all, + )?; + } + if run_all || checks.docs_refresh { + run_step( + &mut exit_code, + "Phase: Check all documentation is up to date", + docs_refresh, + run_all, + )?; + } + if run_all || checks.api_docs { + run_step( + &mut exit_code, + "Phase: Try Build API docs", + deploy_api_docs, + run_all, + )?; + } - if exit_code != 0 { - return Err(exit_code); - } + if exit_code != 0 { + return Err(exit_code); } run_cmd!("git add --renormalize .")?; |
