Skip to content

Commit db2deec

Browse files
committed
CI: check that new lints use the correct stabilization version
New lints are found by comparing the metadata with the base one. The declared version must be equal to the stabilization version.
1 parent 753629b commit db2deec

File tree

5 files changed

+156
-1
lines changed

5 files changed

+156
-1
lines changed

.github/workflows/versioncheck.yml

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
name: New lint stabilization version check
2+
3+
on:
4+
push:
5+
branches:
6+
- auto
7+
- try
8+
pull_request:
9+
paths:
10+
- 'clippy_lints/src/**/*.rs'
11+
12+
env:
13+
RUST_BACKTRACE: 1
14+
CARGO_INCREMENTAL: 0
15+
16+
concurrency:
17+
# For a given workflow, if we push to the same PR, cancel all previous builds on that PR.
18+
group: "${{ github.workflow }}-${{ github.event.pull_request.number}}"
19+
cancel-in-progress: true
20+
21+
jobs:
22+
# Collect lint metadata on the PR's target branch and stores the results as an artifact
23+
base:
24+
runs-on: ubuntu-latest
25+
26+
steps:
27+
- name: Checkout
28+
uses: actions/checkout@v4
29+
with:
30+
fetch-depth: 2
31+
32+
# HEAD is the generated merge commit `refs/pull/N/merge` between the PR and `master`, `HEAD^`
33+
# being the commit from `master` that is the base of the merge
34+
- name: Checkout base
35+
run: git checkout HEAD^
36+
37+
- name: Cache metadata
38+
id: cache-metadata
39+
uses: actions/cache@v4
40+
with:
41+
path: util/gh-pages/lints.json
42+
key: metadata-bin-${{ hashfiles('clippy_lints/**') }}
43+
44+
- name: Collect metadata
45+
if: steps.cache-metadata.outputs.cache-hit != 'true'
46+
run: cargo collect-metadata
47+
48+
- name: Upload base JSON
49+
uses: actions/upload-artifact@v4
50+
with:
51+
name: base
52+
path: util/gh-pages/lints.json
53+
54+
head:
55+
runs-on: ubuntu-latest
56+
57+
steps:
58+
- name: Checkout
59+
uses: actions/checkout@v4
60+
with:
61+
fetch-depth: 2
62+
63+
- name: Cache metadata
64+
id: cache-metadata
65+
uses: actions/cache@v4
66+
with:
67+
path: util/gh-pages/lints.json
68+
key: metadata-bin-${{ hashfiles('clippy_lints/**') }}
69+
70+
- name: Collect metadata
71+
if: steps.cache-metadata.outputs.cache-hit != 'true'
72+
run: cargo collect-metadata
73+
74+
- name: Upload base JSON
75+
uses: actions/upload-artifact@v4
76+
with:
77+
name: head
78+
path: util/gh-pages/lints.json
79+
80+
# Retrieves the head and base JSON results and prints the diff to the GH actions step summary
81+
diff:
82+
runs-on: ubuntu-latest
83+
84+
needs: [base, head]
85+
86+
steps:
87+
- name: Checkout
88+
uses: actions/checkout@v4
89+
90+
- name: Download JSON
91+
uses: actions/download-artifact@v4
92+
93+
- name: Diff results
94+
run: |
95+
cargo dev check_new_lints_version base/lints.json head/lints.json

clippy_dev/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ clap = { version = "4.4", features = ["derive"] }
1010
indoc = "1.0"
1111
itertools = "0.12"
1212
opener = "0.6"
13+
serde = { version = "1.0.210", features = ["derive"] }
14+
serde_json = "1.0.128"
1315
shell-escape = "0.1"
1416
walkdir = "2.3"
1517

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use std::collections::HashMap;
2+
use std::fs::File;
3+
use std::path::Path;
4+
use std::process;
5+
6+
use crate::new_lint::get_stabilization_version;
7+
8+
#[derive(serde::Deserialize)]
9+
struct Lint {
10+
id: String,
11+
version: String,
12+
}
13+
14+
fn load_metadata(metadata: &Path) -> HashMap<String, String> {
15+
let lints: Vec<Lint> = serde_json::from_reader(File::open(metadata).unwrap()).unwrap();
16+
lints.into_iter().map(|lint| (lint.id, lint.version)).collect()
17+
}
18+
19+
pub fn check_lint_version(old_metadata: &Path, new_metadata: &Path) {
20+
let stabilization_version = get_stabilization_version();
21+
let old_lints = load_metadata(old_metadata);
22+
let mut new_lints = load_metadata(new_metadata)
23+
.into_iter()
24+
.filter(|(name, _)| !old_lints.contains_key(name))
25+
.collect::<Vec<_>>();
26+
if new_lints.is_empty() {
27+
println!("No new lints");
28+
return;
29+
}
30+
new_lints.sort_unstable();
31+
let mut error = false;
32+
println!("New lints:");
33+
for (name, version) in new_lints {
34+
if version == stabilization_version {
35+
println!(" - {name}");
36+
} else {
37+
println!(" - {name}: lint declares version {version}, stabilization version is {stabilization_version}");
38+
error = true;
39+
}
40+
}
41+
if error {
42+
process::exit(1);
43+
}
44+
}

clippy_dev/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use std::io;
1818
use std::path::PathBuf;
1919
use std::process::{self, ExitStatus};
2020

21+
pub mod check_lint_version;
2122
pub mod dogfood;
2223
pub mod fmt;
2324
pub mod lint;

clippy_dev/src/main.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
#![warn(rust_2018_idioms, unused_lifetimes)]
44

55
use clap::{Args, Parser, Subcommand};
6-
use clippy_dev::{dogfood, fmt, lint, new_lint, serve, setup, update_lints};
6+
use clippy_dev::{check_lint_version, dogfood, fmt, lint, new_lint, serve, setup, update_lints};
77
use std::convert::Infallible;
8+
use std::path::PathBuf;
89

910
fn main() {
1011
let dev = Dev::parse();
@@ -13,6 +14,10 @@ fn main() {
1314
DevCommand::Bless => {
1415
eprintln!("use `cargo bless` to automatically replace `.stderr` and `.fixed` files as tests are being run");
1516
},
17+
DevCommand::CheckNewLintsVersion {
18+
old_metadata,
19+
new_metadata,
20+
} => check_lint_version::check_lint_version(&old_metadata, &new_metadata),
1621
DevCommand::Dogfood {
1722
fix,
1823
allow_dirty,
@@ -89,6 +94,14 @@ struct Dev {
8994
enum DevCommand {
9095
/// Bless the test output changes
9196
Bless,
97+
/// Check that new lints agree with the stabilization version
98+
#[command(name = "check_new_lints_version")]
99+
CheckNewLintsVersion {
100+
/// Original metadata
101+
old_metadata: PathBuf,
102+
/// New metadata
103+
new_metadata: PathBuf,
104+
},
92105
/// Runs the dogfood test
93106
Dogfood {
94107
#[arg(long)]

0 commit comments

Comments
 (0)