aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwillcl-ark <will@256k1.dev>2024-05-07 15:37:31 +0100
committerwillcl-ark <will@256k1.dev>2024-05-24 12:11:50 +0100
commit4b7d9842691046b01f0c08d69f924ddb62ccc4c6 (patch)
tree4f9466b3bc2c1e5e41e3cae4f1f61125a3cd400d
parent43a66c55ec8770cf7c21112aac9b997f3f2fb704 (diff)
downloadbitcoin-4b7d9842691046b01f0c08d69f924ddb62ccc4c6.tar.xz
lint: add markdown hyperlink checker
This adds a markdown hyperlink check task to the lint test_runner. It relies on having the [`mlc`](https://crates.io/crates/mlc) binary found on $PATH, but will fail with `success` if the binary is not found. `mlc` is also added to the ci/04_install.sh script run by the containerfile. Note that broken markdown hyperlinks will be detected in untracked markdown files found in a dirty working directory (including e.g. .venv).
-rwxr-xr-xci/lint/04_install.sh5
-rw-r--r--test/lint/README.md1
-rw-r--r--test/lint/test_runner/src/main.rs50
3 files changed, 54 insertions, 2 deletions
diff --git a/ci/lint/04_install.sh b/ci/lint/04_install.sh
index 6b12c53f2a..87e3a8fa9b 100755
--- a/ci/lint/04_install.sh
+++ b/ci/lint/04_install.sh
@@ -57,3 +57,8 @@ SHELLCHECK_VERSION=v0.8.0
curl -sL "https://github.com/koalaman/shellcheck/releases/download/${SHELLCHECK_VERSION}/shellcheck-${SHELLCHECK_VERSION}.linux.x86_64.tar.xz" | \
tar --xz -xf - --directory /tmp/
mv "/tmp/shellcheck-${SHELLCHECK_VERSION}/shellcheck" /usr/bin/
+
+MLC_VERSION=v0.16.3
+MLC_BIN=mlc-x86_64-linux
+curl -sL "https://github.com/becheran/mlc/releases/download/${MLC_VERSION}/${MLC_BIN}" -o "/usr/bin/mlc"
+chmod +x /usr/bin/mlc
diff --git a/test/lint/README.md b/test/lint/README.md
index 13c2099808..49ed8356c3 100644
--- a/test/lint/README.md
+++ b/test/lint/README.md
@@ -37,6 +37,7 @@ Then you can use:
| [`lint-python-dead-code.py`](/test/lint/lint-python-dead-code.py) | [vulture](https://github.com/jendrikseipp/vulture)
| [`lint-shell.py`](/test/lint/lint-shell.py) | [ShellCheck](https://github.com/koalaman/shellcheck)
| [`lint-spelling.py`](/test/lint/lint-spelling.py) | [codespell](https://github.com/codespell-project/codespell)
+| markdown link check | [mlc](https://github.com/becheran/mlc)
In use versions and install instructions are available in the [CI setup](../../ci/lint/04_install.sh).
diff --git a/test/lint/test_runner/src/main.rs b/test/lint/test_runner/src/main.rs
index d5dd98effe..5f980eb398 100644
--- a/test/lint/test_runner/src/main.rs
+++ b/test/lint/test_runner/src/main.rs
@@ -4,9 +4,9 @@
use std::env;
use std::fs;
+use std::io::ErrorKind;
use std::path::{Path, PathBuf};
-use std::process::Command;
-use std::process::ExitCode;
+use std::process::{Command, ExitCode, Stdio};
type LintError = String;
type LintResult = Result<(), LintError>;
@@ -292,6 +292,51 @@ fn lint_doc() -> LintResult {
}
}
+fn lint_markdown() -> LintResult {
+ let bin_name = "mlc";
+ let mut md_ignore_paths = get_subtrees();
+ md_ignore_paths.push("./doc/README_doxygen.md");
+ let md_ignore_path_str = md_ignore_paths.join(",");
+
+ let mut cmd = Command::new(bin_name);
+ cmd.args([
+ "--offline",
+ "--ignore-path",
+ md_ignore_path_str.as_str(),
+ "--root-dir",
+ ".",
+ ])
+ .stdout(Stdio::null()); // Suppress overly-verbose output
+
+ match cmd.output() {
+ Ok(output) if output.status.success() => Ok(()),
+ Ok(output) => {
+ let stderr = String::from_utf8_lossy(&output.stderr);
+ let filtered_stderr: String = stderr // Filter out this annoying trailing line
+ .lines()
+ .filter(|&line| line != "The following links could not be resolved:")
+ .collect::<Vec<&str>>()
+ .join("\n");
+ Err(format!(
+ r#"
+One or more markdown links are broken.
+
+Relative links are preferred (but not required) as jumping to file works natively within Emacs.
+
+Markdown link errors found:
+{}
+ "#,
+ filtered_stderr
+ ))
+ }
+ Err(e) if e.kind() == ErrorKind::NotFound => {
+ println!("`mlc` was not found in $PATH, skipping markdown lint check.");
+ Ok(())
+ }
+ Err(e) => Err(format!("Error running mlc: {}", e)), // Misc errors
+ }
+}
+
fn lint_all() -> LintResult {
let mut good = true;
let lint_dir = get_git_root().join("test/lint");
@@ -325,6 +370,7 @@ fn main() -> ExitCode {
("no-tabs check", lint_tabs_whitespace),
("build config includes check", lint_includes_build_config),
("-help=1 documentation check", lint_doc),
+ ("markdown hyperlink check", lint_markdown),
("lint-*.py scripts", lint_all),
];