Skip to content

Commit a547af9

Browse files
Rollup merge of #141705 - GuillaumeGomez:eslint-tidy, r=Kobzol
Add eslint as part of `tidy` run Rustdoc uses `eslint` to run lints on the JS files. Currently you need to run it by hand since it's not part of any `x.py` command. This PR makes it part of `test tidy`. However, to prevent having all rust developers to install `npm` and `eslint`, I made it optional: if `eslint` is not installed, then the check is simply skipped (but will tell that it is being skipped). The second commit removes the manual checks from the docker file since `eslint` is run as part of tidy. cc `@lolbinarycat,` [#t-rustdoc > eslint seems to only be run in CI](https://rust-lang.zulipchat.com/#narrow/channel/266220-t-rustdoc/topic/eslint.20seems.20to.20only.20be.20run.20in.20CI/with/520761477)
2 parents cb7efc0 + 8645ef7 commit a547af9

File tree

6 files changed

+112
-5
lines changed

6 files changed

+112
-5
lines changed

src/ci/docker/host-x86_64/mingw-check-tidy/Dockerfile

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
2424
mingw-w64 \
2525
&& rm -rf /var/lib/apt/lists/*
2626

27+
COPY scripts/nodejs.sh /scripts/
28+
RUN sh /scripts/nodejs.sh /node
29+
ENV PATH="/node/bin:${PATH}"
30+
31+
# Install eslint
32+
COPY host-x86_64/mingw-check-tidy/eslint.version /tmp/
33+
2734
COPY scripts/sccache.sh /scripts/
2835
RUN sh /scripts/sccache.sh
2936

@@ -36,5 +43,5 @@ COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/
3643

3744
# NOTE: intentionally uses python2 for x.py so we can test it still works.
3845
# validate-toolstate only runs in our CI, so it's ok for it to only support python3.
39-
ENV SCRIPT TIDY_PRINT_DIFF=1 python2.7 ../x.py test \
40-
--stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
46+
ENV SCRIPT TIDY_PRINT_DIFF=1 npm install eslint@$(head -n 1 /tmp/eslint.version) && \
47+
python2.7 ../x.py test --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
8.6.0

src/ci/docker/host-x86_64/mingw-check/Dockerfile

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,4 @@ ENV SCRIPT \
6565
python3 ../x.py test collect-license-metadata && \
6666
# Runs checks to ensure that there are no issues in our JS code.
6767
es-check es2019 ../src/librustdoc/html/static/js/*.js && \
68-
eslint -c ../src/librustdoc/html/static/.eslintrc.js ../src/librustdoc/html/static/js/*.js && \
69-
eslint -c ../src/tools/rustdoc-js/.eslintrc.js ../src/tools/rustdoc-js/tester.js && \
70-
eslint -c ../src/tools/rustdoc-gui/.eslintrc.js ../src/tools/rustdoc-gui/tester.js && \
7168
tsc --project ../src/librustdoc/html/static/js/tsconfig.json

src/tools/tidy/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ pub mod mir_opt_tests;
8282
pub mod pal;
8383
pub mod rustdoc_css_themes;
8484
pub mod rustdoc_gui_tests;
85+
pub mod rustdoc_js;
8586
pub mod rustdoc_templates;
8687
pub mod style;
8788
pub mod target_policy;

src/tools/tidy/src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ fn main() {
3535
let library_path = root_path.join("library");
3636
let compiler_path = root_path.join("compiler");
3737
let librustdoc_path = src_path.join("librustdoc");
38+
let tools_path = src_path.join("tools");
3839
let crashes_path = tests_path.join("crashes");
3940

4041
let args: Vec<String> = env::args().skip(1).collect();
@@ -108,6 +109,7 @@ fn main() {
108109
check!(rustdoc_gui_tests, &tests_path);
109110
check!(rustdoc_css_themes, &librustdoc_path);
110111
check!(rustdoc_templates, &librustdoc_path);
112+
check!(rustdoc_js, &librustdoc_path, &tools_path, &src_path);
111113
check!(known_bug, &crashes_path);
112114
check!(unknown_revision, &tests_path);
113115

src/tools/tidy/src/rustdoc_js.rs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//! Tidy check to ensure that rustdoc templates didn't forget a `{# #}` to strip extra whitespace
2+
//! characters.
3+
4+
use std::ffi::OsStr;
5+
use std::path::{Path, PathBuf};
6+
use std::process::Command;
7+
8+
use ignore::DirEntry;
9+
10+
use crate::walk::walk_no_read;
11+
12+
fn run_eslint(args: &[PathBuf], config_folder: PathBuf, bad: &mut bool) {
13+
let mut child = match Command::new("npx")
14+
.arg("eslint")
15+
.arg("-c")
16+
.arg(config_folder.join(".eslintrc.js"))
17+
.args(args)
18+
.spawn()
19+
{
20+
Ok(child) => child,
21+
Err(error) => {
22+
*bad = true;
23+
eprintln!("failed to run eslint: {error:?}");
24+
return;
25+
}
26+
};
27+
match child.wait() {
28+
Ok(exit_status) => {
29+
if exit_status.success() {
30+
return;
31+
}
32+
eprintln!("eslint command failed");
33+
}
34+
Err(error) => eprintln!("eslint command failed: {error:?}"),
35+
}
36+
*bad = true;
37+
}
38+
39+
fn get_eslint_version_inner(global: bool) -> Option<String> {
40+
let mut command = Command::new("npm");
41+
command.arg("list").arg("--parseable").arg("--long").arg("--depth=0");
42+
if global {
43+
command.arg("--global");
44+
}
45+
let output = command.output().ok()?;
46+
let lines = String::from_utf8_lossy(&output.stdout);
47+
lines.lines().find_map(|l| l.split(':').nth(1)?.strip_prefix("eslint@")).map(|v| v.to_owned())
48+
}
49+
50+
fn get_eslint_version() -> Option<String> {
51+
get_eslint_version_inner(false).or_else(|| get_eslint_version_inner(true))
52+
}
53+
54+
pub fn check(librustdoc_path: &Path, tools_path: &Path, src_path: &Path, bad: &mut bool) {
55+
let eslint_version_path =
56+
src_path.join("ci/docker/host-x86_64/mingw-check-tidy/eslint.version");
57+
let eslint_version = match std::fs::read_to_string(&eslint_version_path) {
58+
Ok(version) => version.trim().to_string(),
59+
Err(error) => {
60+
*bad = true;
61+
eprintln!("failed to read `{}`: {error:?}", eslint_version_path.display());
62+
return;
63+
}
64+
};
65+
match get_eslint_version() {
66+
Some(version) => {
67+
if version != eslint_version {
68+
*bad = true;
69+
eprintln!(
70+
"⚠️ Installed version of eslint (`{version}`) is different than the \
71+
one used in the CI (`{eslint_version}`)",
72+
);
73+
eprintln!(
74+
"You can install this version using `npm update eslint` or by using \
75+
`npm install eslint@{eslint_version}`",
76+
);
77+
return;
78+
}
79+
}
80+
None => {
81+
eprintln!("`eslint` doesn't seem to be installed. Skipping tidy check for JS files.");
82+
eprintln!("You can install it using `npm install eslint@{eslint_version}`");
83+
return;
84+
}
85+
}
86+
let mut files_to_check = Vec::new();
87+
walk_no_read(
88+
&[&librustdoc_path.join("html/static/js")],
89+
|path, is_dir| is_dir || !path.extension().is_some_and(|ext| ext == OsStr::new("js")),
90+
&mut |path: &DirEntry| {
91+
files_to_check.push(path.path().into());
92+
},
93+
);
94+
println!("Running eslint on rustdoc JS files");
95+
run_eslint(&files_to_check, librustdoc_path.join("html/static"), bad);
96+
97+
run_eslint(&[tools_path.join("rustdoc-js/tester.js")], tools_path.join("rustdoc-js"), bad);
98+
run_eslint(&[tools_path.join("rustdoc-gui/tester.js")], tools_path.join("rustdoc-gui"), bad);
99+
}

0 commit comments

Comments
 (0)