diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-08-18 09:23:45 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-08-18 09:23:45 +0800 |
| commit | a6e3888c1b1448a96c6bb88cd9b9edb506fbb736 (patch) | |
| tree | 2432f6a9ddc5c788fc857442d2743852d80c67d3 | |
| parent | ee3c2e39ac8456712bf21bd5f3d300d9c8b5605a (diff) | |
feat(ci-new): add clippy-all task to run clippy on all crates
| -rw-r--r-- | mingling_ci/help.txt | 1 | ||||
| -rw-r--r-- | mingling_ci/src/task.rs | 1 | ||||
| -rw-r--r-- | mingling_ci/src/task/cmd_clippy.rs | 90 |
3 files changed, 92 insertions, 0 deletions
diff --git a/mingling_ci/help.txt b/mingling_ci/help.txt index 4081ded..1c59030 100644 --- a/mingling_ci/help.txt +++ b/mingling_ci/help.txt @@ -17,3 +17,4 @@ COMMANDS: TASKS: build-all Build all crates + clippy-all Run clippy with -D warnings on all crates diff --git a/mingling_ci/src/task.rs b/mingling_ci/src/task.rs index 6d86ac6..1d389b0 100644 --- a/mingling_ci/src/task.rs +++ b/mingling_ci/src/task.rs @@ -1 +1,2 @@ pub(crate) mod cmd_build; +pub(crate) mod cmd_clippy; diff --git a/mingling_ci/src/task/cmd_clippy.rs b/mingling_ci/src/task/cmd_clippy.rs new file mode 100644 index 0000000..8ec4236 --- /dev/null +++ b/mingling_ci/src/task/cmd_clippy.rs @@ -0,0 +1,90 @@ +use std::path::Path; + +use just_progress::progress::{self, ProgressInfo}; +use mingling::{ + Grouped, Routable, + macros::{buffer, command, r_println, renderer}, +}; + +use crate::Next; +use crate::reporter::{self, ReportResult}; +use crate::res::Manifests; + +#[command(node = "clippy-all")] +pub async fn clippy_all(manifests: &Manifests) -> Next { + const TASK: &str = "Clippy-All"; + + reporter::set_task(TASK); + + let total = manifests.package_dirs.len(); + progress::update(TASK, 0.0, ProgressInfo::Info("Clippy")); + + // Run one `cargo clippy` per manifest in parallel. + let mut set = tokio::task::JoinSet::new(); + for (name, path) in &manifests.package_dirs { + let (name, path) = (name.clone(), path.clone()); + set.spawn(async move { (name, run_cargo_clippy(&path).await) }); + } + + // Collect all outcomes first, then dump the report files in one round. + let mut results: Vec<(String, ReportResult)> = Vec::new(); + let mut done = 0; + while let Some(joined) = set.join_next().await { + done += 1; + let Ok((name, (ok, output))) = joined else { + continue; + }; + // The count is small, so the `usize -> f32` cast cannot lose precision. + #[allow(clippy::cast_precision_loss)] + let overall = done as f32 / total as f32; + progress::update(TASK, overall, ProgressInfo::Info("Clippy")); + results.push(( + name, + if ok { + ReportResult::Ok + } else { + ReportResult::Error(output) + }, + )); + } + + let fail_count = results + .iter() + .filter(|(_, r)| matches!(r, ReportResult::Error(_))) + .count(); + for (name, result) in results { + reporter::export(&name, result); + } + + ResultClippyAll { fail_count }.to_chain() +} + +/// Runs `cargo clippy --manifest-path <path> -- -D warnings`, returning success +/// and output. +async fn run_cargo_clippy(path: &Path) -> (bool, String) { + let output = tokio::process::Command::new("cargo") + .args(["clippy", "--manifest-path"]) + .arg(path) + .args(["--", "-D", "warnings"]) + .output() + .await; + match output { + Ok(output) => { + let mut log = String::from_utf8_lossy(&output.stdout).into_owned(); + log.push_str(&String::from_utf8_lossy(&output.stderr)); + (output.status.success(), log) + } + Err(e) => (false, format!("failed to run cargo: {e}")), + } +} + +/// Number of packages that failed clippy. +#[derive(Grouped)] +pub struct ResultClippyAll { + pub fail_count: usize, +} + +#[renderer(buffer)] +pub fn render_clippy_all(r: ResultClippyAll) { + r_println!("Clippy-All: {} package(s) failed", r.fail_count); +} |
