From e7348cc4275e970a0cd681d99d579e3496e2fbe3 Mon Sep 17 00:00:00 2001 From: Finn Evers Date: Thu, 23 Apr 2026 12:50:51 +0200 Subject: [PATCH] ci: Perform compliance checks in parallel (#54564) Not to be merged before https://github.com/zed-industries/zed/pull/54550 This makes it so that we perform not all checks sequentially but in parallel which should overall make this a lot faster. Ultimately, we can save some more requests if we were to search for all co-author looking PRs with one GraphQL query, but for now, this here should make things a lot faster already whilst working fine with rate limits. Release Notes: - N/A --- tooling/compliance/src/checks.rs | 44 ++++++++++++++++----------- tooling/compliance/src/report.rs | 12 ++++++++ tooling/xtask/src/tasks/compliance.rs | 6 ++-- 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/tooling/compliance/src/checks.rs b/tooling/compliance/src/checks.rs index 9444d76b96..6558f6e362 100644 --- a/tooling/compliance/src/checks.rs +++ b/tooling/compliance/src/checks.rs @@ -1,5 +1,6 @@ use std::{fmt, ops::Not as _, rc::Rc}; +use futures::StreamExt; use itertools::Itertools as _; use crate::{ @@ -8,7 +9,7 @@ use crate::{ Approvable, CommitAuthor, CommitFileChange, CommitMetadata, GithubApiClient, GithubLogin, PullRequestComment, PullRequestData, PullRequestReview, Repository, ReviewState, }, - report::Report, + report::{Report, ReportEntry}, }; const ZED_ZIPPY_COMMENT_APPROVAL_PATTERN: &str = "@zed-zippy approve"; @@ -409,30 +410,37 @@ impl Reporter { body.contains(ZED_ZIPPY_COMMENT_APPROVAL_PATTERN) || body.contains(ZED_ZIPPY_GROUP_APPROVAL) } - pub async fn generate_report(mut self) -> anyhow::Result { - let mut report = Report::new(); - + pub async fn generate_report(mut self, max_concurrent_checks: usize) -> Report { let commits_to_check = std::mem::take(&mut self.commits); let total_commits = commits_to_check.len(); - for (i, commit) in commits_to_check.into_iter().enumerate() { - println!( - "Checking commit {:?} ({current}/{total})", - commit.sha().short(), - current = i + 1, - total = total_commits - ); + let reports = futures::stream::iter(commits_to_check.into_iter().enumerate().map( + async |(i, commit)| { + println!( + "Checking commit {:?} ({current}/{total})", + commit.sha().short(), + current = i + 1, + total = total_commits + ); - let review_result = self.check_commit(&commit).await; + let review_result = self.check_commit(&commit).await; - if let Err(err) = &review_result { - println!("Commit {:?} failed review: {:?}", commit.sha().short(), err); - } + if let Err(err) = &review_result { + println!("Commit {:?} failed review: {:?}", commit.sha().short(), err); + } - report.add(commit, review_result); - } + (commit, review_result) + }, + )) + .buffered(max_concurrent_checks) + .collect::>() + .await; - Ok(report) + Report::from_entries( + reports + .into_iter() + .map(|(commit, result)| ReportEntry::new(commit, result)), + ) } } diff --git a/tooling/compliance/src/report.rs b/tooling/compliance/src/report.rs index bab0a5783f..7d11567202 100644 --- a/tooling/compliance/src/report.rs +++ b/tooling/compliance/src/report.rs @@ -21,6 +21,12 @@ pub struct ReportEntry { reason: R, } +impl ReportEntry { + pub fn new(commit: CommitDetails, reason: R) -> Self { + Self { commit, reason } + } +} + impl ReportEntry { fn commit_cell(&self) -> String { let title = escape_markdown_link_text(self.commit.title()); @@ -149,6 +155,12 @@ impl Report { Self::default() } + pub fn from_entries(entries: impl IntoIterator>) -> Self { + Self { + entries: entries.into_iter().collect(), + } + } + pub fn add(&mut self, commit: CommitDetails, result: ReviewResult) { self.entries.push(ReportEntry { commit, diff --git a/tooling/xtask/src/tasks/compliance.rs b/tooling/xtask/src/tasks/compliance.rs index 46c40fb82c..5a4b03a961 100644 --- a/tooling/xtask/src/tasks/compliance.rs +++ b/tooling/xtask/src/tasks/compliance.rs @@ -10,6 +10,8 @@ use compliance::{ report::ReportReviewSummary, }; +const MAX_CONCURRENT_REQUESTS: usize = 5; + #[derive(Parser)] pub(crate) struct ComplianceArgs { #[clap(subcommand)] @@ -116,8 +118,8 @@ async fn check_compliance_impl(args: ComplianceArgs) -> Result<()> { println!("Checking commit range {range}, {} total", commits.len()); let report = Reporter::new(commits, client.clone()) - .generate_report() - .await?; + .generate_report(MAX_CONCURRENT_REQUESTS) + .await; println!( "Generated report for version {}",