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
This commit is contained in:
Finn Evers 2026-04-23 12:50:51 +02:00 committed by GitHub
parent 9affe8cbac
commit 61b25b6119
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 42 additions and 20 deletions

View file

@ -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<Report> {
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::<Vec<_>>()
.await;
Ok(report)
Report::from_entries(
reports
.into_iter()
.map(|(commit, result)| ReportEntry::new(commit, result)),
)
}
}

View file

@ -21,6 +21,12 @@ pub struct ReportEntry<R> {
reason: R,
}
impl<R> ReportEntry<R> {
pub fn new(commit: CommitDetails, reason: R) -> Self {
Self { commit, reason }
}
}
impl<R: ToString> ReportEntry<R> {
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<Item = ReportEntry<ReviewResult>>) -> Self {
Self {
entries: entries.into_iter().collect(),
}
}
pub fn add(&mut self, commit: CommitDetails, result: ReviewResult) {
self.entries.push(ReportEntry {
commit,

View file

@ -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 {}",