Skip to content

Commit 56cef5c

Browse files
authored
Rollup merge of rust-lang#139978 - Kobzol:ci-test-summary, r=jieyouxu
Add citool command for generating a test dashboard This PR implements an initial version of a test suite dashboard, which shows which tests were executed on CI and which tests were ignored. This was discussed [here](https://rust-lang.zulipchat.com/#narrow/channel/238009-t-compiler.2Fmeetings/topic/.5Bsteering.5D.202025-04-11.20Dealing.20with.20disabled.20tests/with/512799036). The dashboard is still quite bare-bones, but I think that it could already be useful. The next step is to create a job index, similarly to the post-merge report, and link from the individual tests to the job that executed them. You can try it locally like this: ```bash $ cargo run --manifest-path src/ci/citool/Cargo.toml --release \ -- test-dashboard 38c560a --output-dir dashboard ``` and then open `dashboard/index.html` in a web browser. CC ````@wesleywiser```` r? ````@jieyouxu````
2 parents 709f4fe + b18e373 commit 56cef5c

File tree

10 files changed

+511
-21
lines changed

10 files changed

+511
-21
lines changed

Diff for: src/ci/citool/Cargo.lock

+67
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,63 @@ version = "1.0.95"
6464
source = "registry+https://github.com/rust-lang/crates.io-index"
6565
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
6666

67+
[[package]]
68+
name = "askama"
69+
version = "0.13.1"
70+
source = "registry+https://github.com/rust-lang/crates.io-index"
71+
checksum = "5d4744ed2eef2645831b441d8f5459689ade2ab27c854488fbab1fbe94fce1a7"
72+
dependencies = [
73+
"askama_derive",
74+
"itoa",
75+
"percent-encoding",
76+
"serde",
77+
"serde_json",
78+
]
79+
80+
[[package]]
81+
name = "askama_derive"
82+
version = "0.13.1"
83+
source = "registry+https://github.com/rust-lang/crates.io-index"
84+
checksum = "d661e0f57be36a5c14c48f78d09011e67e0cb618f269cca9f2fd8d15b68c46ac"
85+
dependencies = [
86+
"askama_parser",
87+
"basic-toml",
88+
"memchr",
89+
"proc-macro2",
90+
"quote",
91+
"rustc-hash",
92+
"serde",
93+
"serde_derive",
94+
"syn",
95+
]
96+
97+
[[package]]
98+
name = "askama_parser"
99+
version = "0.13.0"
100+
source = "registry+https://github.com/rust-lang/crates.io-index"
101+
checksum = "cf315ce6524c857bb129ff794935cf6d42c82a6cff60526fe2a63593de4d0d4f"
102+
dependencies = [
103+
"memchr",
104+
"serde",
105+
"serde_derive",
106+
"winnow",
107+
]
108+
67109
[[package]]
68110
name = "base64"
69111
version = "0.22.1"
70112
source = "registry+https://github.com/rust-lang/crates.io-index"
71113
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
72114

115+
[[package]]
116+
name = "basic-toml"
117+
version = "0.1.10"
118+
source = "registry+https://github.com/rust-lang/crates.io-index"
119+
checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a"
120+
dependencies = [
121+
"serde",
122+
]
123+
73124
[[package]]
74125
name = "build_helper"
75126
version = "0.1.0"
@@ -104,6 +155,7 @@ name = "citool"
104155
version = "0.1.0"
105156
dependencies = [
106157
"anyhow",
158+
"askama",
107159
"build_helper",
108160
"clap",
109161
"csv",
@@ -646,6 +698,12 @@ dependencies = [
646698
"windows-sys 0.52.0",
647699
]
648700

701+
[[package]]
702+
name = "rustc-hash"
703+
version = "2.1.1"
704+
source = "registry+https://github.com/rust-lang/crates.io-index"
705+
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
706+
649707
[[package]]
650708
name = "rustls"
651709
version = "0.23.23"
@@ -1026,6 +1084,15 @@ version = "0.52.6"
10261084
source = "registry+https://github.com/rust-lang/crates.io-index"
10271085
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
10281086

1087+
[[package]]
1088+
name = "winnow"
1089+
version = "0.7.6"
1090+
source = "registry+https://github.com/rust-lang/crates.io-index"
1091+
checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10"
1092+
dependencies = [
1093+
"memchr",
1094+
]
1095+
10291096
[[package]]
10301097
name = "write16"
10311098
version = "1.0.0"

Diff for: src/ci/citool/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ edition = "2021"
55

66
[dependencies]
77
anyhow = "1"
8+
askama = "0.13"
89
clap = { version = "4.5", features = ["derive"] }
910
csv = "1"
1011
diff = "0.1"

Diff for: src/ci/citool/src/analysis.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ use build_helper::metrics::{
88
};
99

1010
use crate::github::JobInfoResolver;
11-
use crate::metrics;
1211
use crate::metrics::{JobMetrics, JobName, get_test_suites};
1312
use crate::utils::{output_details, pluralize};
13+
use crate::{metrics, utils};
1414

1515
/// Outputs durations of individual bootstrap steps from the gathered bootstrap invocations,
1616
/// and also a table with summarized information about executed tests.
@@ -394,18 +394,17 @@ fn aggregate_tests(metrics: &JsonRoot) -> TestSuiteData {
394394
// Poor man's detection of doctests based on the "(line XYZ)" suffix
395395
let is_doctest = matches!(suite.metadata, TestSuiteMetadata::CargoPackage { .. })
396396
&& test.name.contains("(line");
397-
let test_entry = Test { name: generate_test_name(&test.name), stage, is_doctest };
397+
let test_entry = Test {
398+
name: utils::normalize_path_delimiters(&test.name).to_string(),
399+
stage,
400+
is_doctest,
401+
};
398402
tests.insert(test_entry, test.outcome.clone());
399403
}
400404
}
401405
TestSuiteData { tests }
402406
}
403407

404-
/// Normalizes Windows-style path delimiters to Unix-style paths.
405-
fn generate_test_name(name: &str) -> String {
406-
name.replace('\\', "/")
407-
}
408-
409408
/// Prints test changes in Markdown format to stdout.
410409
fn report_test_diffs(
411410
diff: AggregatedTestDiffs,

Diff for: src/ci/citool/src/main.rs

+31-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod datadog;
44
mod github;
55
mod jobs;
66
mod metrics;
7+
mod test_dashboard;
78
mod utils;
89

910
use std::collections::{BTreeMap, HashMap};
@@ -22,7 +23,8 @@ use crate::datadog::upload_datadog_metric;
2223
use crate::github::JobInfoResolver;
2324
use crate::jobs::RunType;
2425
use crate::metrics::{JobMetrics, download_auto_job_metrics, download_job_metrics, load_metrics};
25-
use crate::utils::load_env_var;
26+
use crate::test_dashboard::generate_test_dashboard;
27+
use crate::utils::{load_env_var, output_details};
2628

2729
const CI_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/..");
2830
const DOCKER_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../docker");
@@ -180,12 +182,26 @@ fn postprocess_metrics(
180182
}
181183

182184
fn post_merge_report(db: JobDatabase, current: String, parent: String) -> anyhow::Result<()> {
183-
let metrics = download_auto_job_metrics(&db, &parent, &current)?;
185+
let metrics = download_auto_job_metrics(&db, Some(&parent), &current)?;
184186

185187
println!("\nComparing {parent} (parent) -> {current} (this PR)\n");
186188

187189
let mut job_info_resolver = JobInfoResolver::new();
188190
output_test_diffs(&metrics, &mut job_info_resolver);
191+
192+
output_details("Test dashboard", || {
193+
println!(
194+
r#"\nRun
195+
196+
```bash
197+
cargo run --manifest-path src/ci/citool/Cargo.toml -- \
198+
test-dashboard {current} --output-dir test-dashboard
199+
```
200+
And then open `test-dashboard/index.html` in your browser to see an overview of all executed tests.
201+
"#
202+
);
203+
});
204+
189205
output_largest_duration_changes(&metrics, &mut job_info_resolver);
190206

191207
Ok(())
@@ -234,6 +250,14 @@ enum Args {
234250
/// Current commit that will be compared to `parent`.
235251
current: String,
236252
},
253+
/// Generate a directory containing a HTML dashboard of test results from a CI run.
254+
TestDashboard {
255+
/// Commit SHA that was tested on CI to analyze.
256+
current: String,
257+
/// Output path for the HTML directory.
258+
#[clap(long)]
259+
output_dir: PathBuf,
260+
},
237261
}
238262

239263
#[derive(clap::ValueEnum, Clone)]
@@ -275,7 +299,11 @@ fn main() -> anyhow::Result<()> {
275299
postprocess_metrics(metrics_path, parent, job_name)?;
276300
}
277301
Args::PostMergeReport { current, parent } => {
278-
post_merge_report(load_db(default_jobs_file)?, current, parent)?;
302+
post_merge_report(load_db(&default_jobs_file)?, current, parent)?;
303+
}
304+
Args::TestDashboard { current, output_dir } => {
305+
let db = load_db(&default_jobs_file)?;
306+
generate_test_dashboard(db, &current, &output_dir)?;
279307
}
280308
}
281309

Diff for: src/ci/citool/src/metrics.rs

+12-11
Original file line numberDiff line numberDiff line change
@@ -46,24 +46,25 @@ pub struct JobMetrics {
4646
/// `parent` and `current` should be commit SHAs.
4747
pub fn download_auto_job_metrics(
4848
job_db: &JobDatabase,
49-
parent: &str,
49+
parent: Option<&str>,
5050
current: &str,
5151
) -> anyhow::Result<HashMap<JobName, JobMetrics>> {
5252
let mut jobs = HashMap::default();
5353

5454
for job in &job_db.auto_jobs {
5555
eprintln!("Downloading metrics of job {}", job.name);
56-
let metrics_parent = match download_job_metrics(&job.name, parent) {
57-
Ok(metrics) => Some(metrics),
58-
Err(error) => {
59-
eprintln!(
60-
r#"Did not find metrics for job `{}` at `{parent}`: {error:?}.
56+
let metrics_parent =
57+
parent.and_then(|parent| match download_job_metrics(&job.name, parent) {
58+
Ok(metrics) => Some(metrics),
59+
Err(error) => {
60+
eprintln!(
61+
r#"Did not find metrics for job `{}` at `{parent}`: {error:?}.
6162
Maybe it was newly added?"#,
62-
job.name
63-
);
64-
None
65-
}
66-
};
63+
job.name
64+
);
65+
None
66+
}
67+
});
6768
let metrics_current = download_job_metrics(&job.name, current)?;
6869
jobs.insert(
6970
job.name.clone(),

0 commit comments

Comments
 (0)