diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f43ba3..0a9ad6f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,6 +43,9 @@ jobs: run: echo RUSTFLAGS=${RUSTFLAGS}\ --cfg=thiserror_nightly_testing >> $GITHUB_ENV if: matrix.rust == 'nightly' - run: cargo xtask ci --no-extended + if: matrix.rust != '1.64.0' + - run: cargo xtask ci --no-extended -f tokio + if: matrix.rust == '1.64.0' - uses: actions/upload-artifact@v4 if: matrix.rust == 'nightly' && always() with: diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 752b94c..08a0abe 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -15,3 +15,4 @@ workspace = true xshell = "0.2" anyhow = "1" clap = { version = "=4.1.14", features = ["derive"] } +itertools = "0.13" diff --git a/xtask/src/ci.rs b/xtask/src/ci.rs index ec48b35..2c571e9 100644 --- a/xtask/src/ci.rs +++ b/xtask/src/ci.rs @@ -1,7 +1,10 @@ #![allow(clippy::exit)] //! Xtask CI "emulation". +use std::iter; + use anyhow::Result; +use itertools::Itertools; use xshell::{cmd, Shell}; /// How tests are run. @@ -20,6 +23,10 @@ pub(super) struct CiArgs { #[arg(short, long)] testrunner: Option, + /// Which features to **not** test. + #[arg(short, long)] + filter: Option>, + /// Whether to skip extended tests, e.g., `clippy`, `cargo outdated`, and /// `cargo-semver-checks`. Useful in CI, when these run as a separate task. #[arg(long, default_value_t = false)] @@ -61,26 +68,31 @@ pub(super) fn run(args: &CiArgs) -> Result<()> { true }; - let test_matrix = [ - ("ferrunix", ""), - ("ferrunix", "derive"), - ("ferrunix", "multithread"), - ("ferrunix", "tokio"), - ("ferrunix", "tracing"), - ("ferrunix", "multithread,tracing"), - ("ferrunix", "tokio,tracing"), - ("ferrunix", "multithread,tokio,tracing"), - ("ferrunix", "derive,multithread,tokio,tracing"), - ("ferrunix-core", ""), - ("ferrunix-core", "multithread"), - ("ferrunix-core", "tokio"), - ("ferrunix-core", "tracing"), - ("ferrunix-macros", ""), - ("ferrunix-macros", "multithread"), - ("ferrunix-macros", "development"), - ("ferrunix-macros", "development,multithread"), - ("doc-tests", ""), - ]; + let combinations_ferrunix = + feature_combinations(&["derive", "multithread", "tokio", "tracing"]); + let combinations_ferrunix_core = + feature_combinations(&["multithread", "tokio", "tracing"]); + let combinations_ferrunix_macros = + feature_combinations(&["multithread", "development"]); + let test_matrix = { + let ferrunix = iter::repeat("ferrunix").zip(combinations_ferrunix); + let ferrunix_core = + iter::repeat("ferrunix-core").zip(combinations_ferrunix_core); + let ferrunix_macros = + iter::repeat("ferrunix-macros").zip(combinations_ferrunix_macros); + + let filter = args.filter.clone().unwrap_or_default(); + ferrunix + .chain(ferrunix_core) + .chain(ferrunix_macros) + .chain(iter::once(("doc-tests", String::new()))) + .filter(|(_, features)| { + filter + .iter() + .any(|filtered_feature| !features.contains(filtered_feature)) + }) + .collect_vec() + }; let testrunner: &[&str] = match args.testrunner { Some(TestRunner::Nextest) => &["nextest", "run", "--profile", "ci"], @@ -137,3 +149,37 @@ pub(super) fn run(args: &CiArgs) -> Result<()> { Ok(()) } + +/// Generate all possible combinations of `features`. +fn feature_combinations(features: &[&str]) -> Vec { + let len = features.len(); + let base_iter = features.iter().combinations(len); + + let mut chains: Vec>>> = + Vec::with_capacity(len); + for num_combinations in (1..len).rev() { + let iter = base_iter + .clone() + .chain(features.iter().combinations(num_combinations)); + chains.push(Box::new(iter)); + } + + let mut ret = chains + .into_iter() + .map(Itertools::collect_vec) + .flat_map(|outer| { + outer + .into_iter() + .map(|el| { + let x = el.iter().join(","); + x + }) + .collect_vec() + }) + .unique() + .collect::>(); + + ret.push(String::new()); + + ret +} diff --git a/xtask/src/docs.rs b/xtask/src/docs.rs index 4d3c715..dfa1b93 100644 --- a/xtask/src/docs.rs +++ b/xtask/src/docs.rs @@ -1,3 +1,4 @@ +//! Build documentation. use xshell::{cmd, Shell}; /// All arguments for the `xtask docs` command.