From a68fb51a9280e83a9e061a6432d11665620a6eec Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 27 Jul 2026 09:30:28 +0000 Subject: [PATCH 1/4] feat: add standalone Checkstyle linting Signed-off-by: Gregor Zeitlinger --- .github/renovate-tracked-deps.json | 5 ++ .github/renovate.json5 | 1 + README.md | 2 +- default.json | 1 + docs/linters.md | 2 +- docs/linters/checkstyle.md | 28 +++++++++ mise.toml | 1 + src/linters/mod.rs | 28 ++++++--- src/main.rs | 53 ++++++++--------- src/registry/checks.rs | 30 ++++++++++ src/registry/types.rs | 57 ++++++++++++++++--- src/runner.rs | 49 +++++++++++++--- tests/cases/checkstyle/clean/files/Foo.java | 1 + .../checkstyle/clean/files/checkstyle.xml | 1 + tests/cases/checkstyle/clean/files/mise.toml | 2 + tests/cases/checkstyle/clean/test.toml | 15 +++++ .../checkstyle/missing-config/files/Foo.java | 1 + .../checkstyle/missing-config/files/mise.toml | 2 + .../cases/checkstyle/missing-config/test.toml | 21 +++++++ tests/cases/checkstyle/warning/files/Foo.java | 1 + .../checkstyle/warning/files/checkstyle.xml | 1 + .../cases/checkstyle/warning/files/mise.toml | 2 + tests/cases/checkstyle/warning/test.toml | 20 +++++++ 23 files changed, 274 insertions(+), 50 deletions(-) create mode 100644 docs/linters/checkstyle.md create mode 100644 tests/cases/checkstyle/clean/files/Foo.java create mode 100644 tests/cases/checkstyle/clean/files/checkstyle.xml create mode 100644 tests/cases/checkstyle/clean/files/mise.toml create mode 100644 tests/cases/checkstyle/clean/test.toml create mode 100644 tests/cases/checkstyle/missing-config/files/Foo.java create mode 100644 tests/cases/checkstyle/missing-config/files/mise.toml create mode 100644 tests/cases/checkstyle/missing-config/test.toml create mode 100644 tests/cases/checkstyle/warning/files/Foo.java create mode 100644 tests/cases/checkstyle/warning/files/checkstyle.xml create mode 100644 tests/cases/checkstyle/warning/files/mise.toml create mode 100644 tests/cases/checkstyle/warning/test.toml diff --git a/.github/renovate-tracked-deps.json b/.github/renovate-tracked-deps.json index 295c0200..4251e71d 100644 --- a/.github/renovate-tracked-deps.json +++ b/.github/renovate-tracked-deps.json @@ -32,6 +32,10 @@ "packageName": "hadolint/hadolint", "datasource": "github-tags" }, + "http:checkstyle": { + "packageName": "checkstyle/checkstyle", + "datasource": "github-releases" + }, "ktlint": { "packageName": "pinterest/ktlint", "datasource": "github-releases" @@ -115,6 +119,7 @@ "golangci-lint", "google-java-format", "hadolint", + "http:checkstyle", "ktlint", "lychee", "node", diff --git a/.github/renovate.json5 b/.github/renovate.json5 index efa4a3d9..e531580f 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -64,6 +64,7 @@ "golangci-lint", "google-java-format", "hadolint", + "http:checkstyle", "ktlint", "lychee", "npm:renovate", diff --git a/README.md b/README.md index fa06ae3b..41dbba64 100644 --- a/README.md +++ b/README.md @@ -150,7 +150,7 @@ For Flint contributor workflow and local testing tips, see | ----------------------- | ------------------------------------------------ | ---------------------------------------------------------- | | C# | — | [`dotnet-format`](docs/linters/dotnet-format.md) | | Go | [`golangci-lint`](docs/linters/golangci-lint.md) | [`gofmt`](docs/linters/gofmt.md) | -| Java | — | [`google-java-format`](docs/linters/google-java-format.md) | +| Java | [`checkstyle`](docs/linters/checkstyle.md) | [`google-java-format`](docs/linters/google-java-format.md) | | JavaScript / TypeScript | [`biome`](docs/linters/biome.md) | [`biome-format`](docs/linters/biome-format.md) | | Kotlin | [`ktlint`](docs/linters/ktlint.md) | [`ktlint`](docs/linters/ktlint.md) | | Python | [`ruff`](docs/linters/ruff.md) | [`ruff-format`](docs/linters/ruff-format.md) | diff --git a/default.json b/default.json index aa0a26c5..e9e94d5d 100644 --- a/default.json +++ b/default.json @@ -28,6 +28,7 @@ "golangci-lint", "google-java-format", "hadolint", + "http:checkstyle", "ktlint", "lychee", "npm:renovate", diff --git a/docs/linters.md b/docs/linters.md index 114df62c..99018115 100644 --- a/docs/linters.md +++ b/docs/linters.md @@ -14,7 +14,7 @@ page with its behavior, configuration, and examples. | ----------------------- | ------------------------------------------- | ----------------------------------------------------- | | C# | — | [`dotnet-format`](linters/dotnet-format.md) | | Go | [`golangci-lint`](linters/golangci-lint.md) | [`gofmt`](linters/gofmt.md) | -| Java | — | [`google-java-format`](linters/google-java-format.md) | +| Java | [`checkstyle`](linters/checkstyle.md) | [`google-java-format`](linters/google-java-format.md) | | JavaScript / TypeScript | [`biome`](linters/biome.md) | [`biome-format`](linters/biome-format.md) | | Kotlin | [`ktlint`](linters/ktlint.md) | [`ktlint`](linters/ktlint.md) | | Python | [`ruff`](linters/ruff.md) | [`ruff-format`](linters/ruff-format.md) | diff --git a/docs/linters/checkstyle.md b/docs/linters/checkstyle.md new file mode 100644 index 00000000..dfcefdd3 --- /dev/null +++ b/docs/linters/checkstyle.md @@ -0,0 +1,28 @@ +# `checkstyle` + + + + +| | | +| -------- | ------------------------------------------------------ | +| Project | [checkstyle](https://github.com/checkstyle/checkstyle) | +| Fix | no | +| Binary | `checkstyle` | +| Scope | [files](../linters.md#scope-files) | +| Patterns | `*.java` | +| Config | [`checkstyle.xml`](https://checkstyle.org/config.html) | + + + +`checkstyle` checks Java source against a repository-owned coding standard. It +is report-only; use a formatter such as +[`google-java-format`](google-java-format.md) for safe formatting fixes. + +Flint runs the standalone Checkstyle CLI against selected Java files. A Java +runtime must be available on `PATH` because Checkstyle is distributed as a JAR. +Flint resolves that JAR from the `http:checkstyle` entry in `mise.toml` and +invokes it with `java -jar` on every platform. + +The repository must provide `checkstyle.xml` at its root. A root-level +`checkstyle-suppressions.xml` is also supported through Checkstyle's standard +property default. Flint does not infer Maven or Gradle source roots. diff --git a/mise.toml b/mise.toml index d774b8d2..4868a266 100644 --- a/mise.toml +++ b/mise.toml @@ -17,6 +17,7 @@ editorconfig-checker = "3.8.0" golangci-lint = "2.12.2" google-java-format = "1.35.0" hadolint = "2.14.0" +"http:checkstyle" = { version = "13.8.0", url = "https://github.com/checkstyle/checkstyle/releases/download/checkstyle-{{ version }}/checkstyle-{{ version }}-all.jar", bin = "checkstyle" } ktlint = "1.8.0" lychee = "0.24.2" "npm:renovate" = "43.265.4" diff --git a/src/linters/mod.rs b/src/linters/mod.rs index d14b658e..d504bc08 100644 --- a/src/linters/mod.rs +++ b/src/linters/mod.rs @@ -21,13 +21,13 @@ pub use crate::registry::LinterOutput; /// - PE binary without extension → execute directly by full path /// - Everything else → route through `cmd.exe /C` to handle `.cmd` shims /// -/// Self-executing JARs (e.g. ktlint) cannot run via cmd.exe at all. -/// When `windows_java_jar` is true the binary is resolved to its full path -/// and invoked as `java -jar `. -pub fn spawn_command(argv: &[String], windows_java_jar: bool) -> tokio::process::Command { +/// Self-executing JARs (e.g. ktlint and Checkstyle) need to be invoked through +/// the JVM. When `java_jar` is true the resolved tool path is invoked as +/// `java -jar ` on every platform. +pub fn spawn_command(argv: &[String], java_jar: bool) -> tokio::process::Command { #[cfg(windows)] { - if windows_java_jar { + if java_jar { if let Some(path) = find_file_in_path(&argv[0]) { let mut cmd = tokio::process::Command::new("java"); cmd.arg("-jar").arg(path).args(&argv[1..]); @@ -44,7 +44,12 @@ pub fn spawn_command(argv: &[String], windows_java_jar: bool) -> tokio::process: } #[cfg(not(windows))] { - let _ = windows_java_jar; + if java_jar { + let jar = find_file_in_path(&argv[0]).unwrap_or_else(|| argv[0].clone().into()); + let mut cmd = tokio::process::Command::new("java"); + cmd.arg("-jar").arg(jar).args(&argv[1..]); + return cmd; + } let mut cmd = tokio::process::Command::new(&argv[0]); cmd.args(&argv[1..]); cmd @@ -79,7 +84,7 @@ fn find_pe_binary(binary: &str) -> Option { /// On Windows, return the full path of `binary` from PATH without inspecting /// its contents. Used for self-executing JARs where the caller already knows -/// the invocation style (i.e. `windows_java_jar` is set in the registry). +/// the invocation style (i.e. `java_jar` is set in the registry). #[cfg(windows)] fn find_file_in_path(binary: &str) -> Option { let path_var = std::env::var("PATH").ok()?; @@ -88,3 +93,12 @@ fn find_file_in_path(binary: &str) -> Option { candidate.is_file().then_some(candidate) }) } + +#[cfg(not(windows))] +fn find_file_in_path(binary: &str) -> Option { + let path_var = std::env::var("PATH").ok()?; + std::env::split_paths(&path_var).find_map(|dir| { + let candidate = dir.join(binary); + candidate.is_file().then_some(candidate) + }) +} diff --git a/src/main.rs b/src/main.rs index 353016a1..10ad1a1c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1348,33 +1348,34 @@ rust = { version = "1.94.1", components = "clippy,rustfmt" } assert_eq!( table, - r#"NAME BINARY STATUS SPEED FIX DESCRIPTION PATTERNS -------------------------------------------------------------------------------------------------------------------------------------------------------- -flint-setup (built-in) active fast yes Keep Flint setup current and mise.toml lint tooling canonical mise.toml -shellcheck shellcheck active fast no Lint shell scripts for common mistakes *.sh *.bash *.bats -shfmt shfmt active fast yes Format shell scripts *.sh *.bash -rumdl rumdl active fast yes Lint Markdown files for style and consistency *.md -ryl ryl active fast yes Lint YAML files for style and consistency *.yml *.yaml -taplo taplo active fast yes Format TOML files *.toml -actionlint actionlint active fast no Lint GitHub Actions workflow files .github/workflows/*.yml .github/workflows/*.yaml -zizmor zizmor active fast yes Audit GitHub Actions workflows for security issues .github/workflows/*.yml .github/workflows/*.yaml -hadolint hadolint missing fast no Lint Dockerfiles Dockerfile Dockerfile.* *.dockerfile -xmllint xmllint missing fast no Validate XML files are well-formed *.xml -typos typos active fast yes Check for common spelling mistakes * -editorconfig-checker ec active fast no Check files comply with EditorConfig settings * -golangci-lint golangci-lint missing fast no Lint Go code; uses --new-from-rev to scope analysis to changed code *.go -ruff ruff active fast yes Lint Python code *.py -ruff-format ruff active fast yes Format Python code *.py -biome biome active fast yes Lint JS/TS/JSON files *.json *.jsonc *.js *.ts *.jsx *.tsx -biome-format biome active fast yes Format JS/TS/JSON files *.json *.jsonc *.js *.ts *.jsx *.tsx -cargo-clippy cargo-clippy active fast yes Lint Rust code; runs on all .rs files, not just changed *.rs -cargo-fmt rustfmt active fast yes Format Rust code; runs on all .rs files, not just changed *.rs -gofmt gofmt missing fast yes Format Go code *.go -google-java-format google-java-format missing fast yes Format Java code *.java -ktlint ktlint missing fast yes Lint and format Kotlin code *.kt *.kts -dotnet-format dotnet missing fast yes Format C# code *.cs + r#"NAME BINARY STATUS SPEED FIX DESCRIPTION PATTERNS +--------------------------------------------------------------------------------------------------------------------------------------------------------- +flint-setup (built-in) active fast yes Keep Flint setup current and mise.toml lint tooling canonical mise.toml +shellcheck shellcheck active fast no Lint shell scripts for common mistakes *.sh *.bash *.bats +shfmt shfmt active fast yes Format shell scripts *.sh *.bash +rumdl rumdl active fast yes Lint Markdown files for style and consistency *.md +ryl ryl active fast yes Lint YAML files for style and consistency *.yml *.yaml +taplo taplo active fast yes Format TOML files *.toml +actionlint actionlint active fast no Lint GitHub Actions workflow files .github/workflows/*.yml .github/workflows/*.yaml +zizmor zizmor active fast yes Audit GitHub Actions workflows for security issues .github/workflows/*.yml .github/workflows/*.yaml +hadolint hadolint missing fast no Lint Dockerfiles Dockerfile Dockerfile.* *.dockerfile +xmllint xmllint missing fast no Validate XML files are well-formed *.xml +typos typos active fast yes Check for common spelling mistakes * +editorconfig-checker ec active fast no Check files comply with EditorConfig settings * +golangci-lint golangci-lint missing fast no Lint Go code; uses --new-from-rev to scope analysis to changed code *.go +ruff ruff active fast yes Lint Python code *.py +ruff-format ruff active fast yes Format Python code *.py +biome biome active fast yes Lint JS/TS/JSON files *.json *.jsonc *.js *.ts *.jsx *.tsx +biome-format biome active fast yes Format JS/TS/JSON files *.json *.jsonc *.js *.ts *.jsx *.tsx +cargo-clippy cargo-clippy active fast yes Lint Rust code; runs on all .rs files, not just changed *.rs +cargo-fmt rustfmt active fast yes Format Rust code; runs on all .rs files, not just changed *.rs +gofmt gofmt missing fast yes Format Go code *.go +google-java-format google-java-format missing fast yes Format Java code *.java +checkstyle checkstyle missing fast no Check Java source against a repository-owned Checkstyle configuration *.java +ktlint ktlint missing fast yes Lint and format Kotlin code *.kt *.kts +dotnet-format dotnet missing fast yes Format C# code *.cs lychee lychee active fast no Check for broken links -renovate-deps renovate active adaptive yes Verify Renovate dependency snapshot is up to date renovate.json renovate.json5 .github/renovate.json .github/renovate.json5 .renovaterc .renovaterc.json .renovaterc.json5 +renovate-deps renovate active adaptive yes Verify Renovate dependency snapshot is up to date renovate.json renovate.json5 .github/renovate.json .github/renovate.json5 .renovaterc .renovaterc.json .renovaterc.json5 license-header (built-in) not configured fast no Check source files have the required license header "# ); diff --git a/src/registry/checks.rs b/src/registry/checks.rs index abbbafa0..8835d1ee 100644 --- a/src/registry/checks.rs +++ b/src/registry/checks.rs @@ -26,6 +26,8 @@ const GOFMT_URL: &str = "https://pkg.go.dev/cmd/gofmt"; const GOLANGCI_LINT_URL: &str = "https://golangci-lint.run/"; const GOLANGCI_LINT_CONFIG_URL: &str = "https://golangci-lint.run/usage/configuration/"; const GOOGLE_JAVA_FORMAT_URL: &str = "https://github.com/google/google-java-format"; +const CHECKSTYLE_URL: &str = "https://github.com/checkstyle/checkstyle"; +const CHECKSTYLE_CONFIG_URL: &str = "https://checkstyle.org/config.html"; const HADOLINT_URL: &str = "https://github.com/hadolint/hadolint"; const HADOLINT_CONFIG_URL: &str = "https://github.com/hadolint/hadolint?tab=readme-ov-file#configure"; @@ -53,6 +55,10 @@ const XMLLINT_URL: &str = "https://github.com/jonwiggins/xmloxide"; const YAMLLINT_CONFIG_URL: &str = "https://yamllint.readthedocs.io/en/stable/configuration.html"; const RYL_URL: &str = "https://github.com/owenlamont/ryl"; +const CHECKSTYLE_TOOL_KEY: &str = "http:checkstyle"; +const CHECKSTYLE_BASELINE_TRIGGERS: &[ConfigFile] = + &[ConfigFile::project("checkstyle-suppressions.xml")]; + const SHELLCHECK_UNSUPPORTED_CONFIGS: &[ConfigFile] = &[ ConfigFile::config_dir("shellcheckrc"), ConfigFile::project("shellcheckrc"), @@ -596,6 +602,29 @@ fn check_google_java_format() -> Check { .lang() } +fn check_checkstyle() -> Check { + Check::files( + "checkstyle", + "checkstyle -c checkstyle.xml {FILES}", + &["*.java"], + ) + .java_jar() + .mise_tool(CHECKSTYLE_TOOL_KEY) + .baseline_config(ConfigFile::project("checkstyle.xml")) + .baseline_triggers(CHECKSTYLE_BASELINE_TRIGGERS) + .failure_output_patterns(&["[WARN]", "[ERROR]"]) + .project_url(CHECKSTYLE_URL) + .config_doc_url(CHECKSTYLE_CONFIG_URL) + .overview( + OverviewSection::Languages, + "Java", + OverviewRole::Linter, + Some("Java coding standard"), + ) + .desc("Check Java source against a repository-owned Checkstyle configuration") + .lang() +} + fn check_ktlint() -> Check { Check::files( "ktlint", @@ -723,6 +752,7 @@ pub fn builtin() -> Vec { check_cargo_fmt(), check_gofmt(), check_google_java_format(), + check_checkstyle(), check_ktlint(), check_dotnet_format(), check_lychee(), diff --git a/src/registry/types.rs b/src/registry/types.rs index c0f053e1..566b5ffc 100644 --- a/src/registry/types.rs +++ b/src/registry/types.rs @@ -527,6 +527,8 @@ pub struct Check { pub status_hook: Option, /// Optional output normalizer used for non-verbose failing process runs. pub nonverbose_failure_output: Option, + /// Output markers that make an otherwise successful process invocation fail. + pub failure_output_patterns: &'static [&'static str], /// Optional hint appended when a known toolchain component is missing. pub missing_component_hint: Option, /// Additional config-like files that trigger an all-files baseline run when changed. @@ -550,9 +552,8 @@ pub struct Check { /// Toolchain keys stay above the `# Linters` header in `mise.toml` so they're /// visually separated from lint-only entries. pub toolchain: Option>, - /// On Windows, the binary is a self-executing JAR that cannot be run directly - /// or via cmd.exe — invoke as `java -jar ` instead. - pub windows_java_jar: bool, + /// How to invoke the binary when it is a self-executing JAR. + pub java_jar: Option, /// Extra generated workflow setup needed when this check is selected by `flint init`. pub workflow_setup: Option, pub fix_behavior: FixBehavior, @@ -569,6 +570,35 @@ pub struct Check { pub overviews: Vec, } +/// Controls where a self-executing JAR must be launched through `java -jar`. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum JavaJarMode { + /// Use `java -jar` on every platform. + AllPlatforms, + /// Use `java -jar` only on Windows, where JAR shims cannot run directly. + WindowsOnly, +} + +impl JavaJarMode { + pub(crate) const fn enabled_on_current_platform(self) -> bool { + matches!(self, Self::AllPlatforms) || (cfg!(windows) && matches!(self, Self::WindowsOnly)) + } +} + +#[cfg(test)] +mod java_jar_mode_tests { + use super::JavaJarMode; + + #[test] + fn enables_only_on_configured_platforms() { + assert!(JavaJarMode::AllPlatforms.enabled_on_current_platform()); + assert_eq!( + JavaJarMode::WindowsOnly.enabled_on_current_platform(), + cfg!(windows) + ); + } +} + impl Check { pub fn has_fix(&self) -> bool { match &self.kind { @@ -669,6 +699,7 @@ impl Check { adaptive_relevance: None, status_hook: None, nonverbose_failure_output: None, + failure_output_patterns: &[], missing_component_hint: None, baseline_triggers: &[], is_formatter: false, @@ -684,7 +715,7 @@ impl Check { full_fix_cmd: "", scope, }, - windows_java_jar: false, + java_jar: None, workflow_setup: None, fix_behavior: FixBehavior::Definitive, fix_after: vec![], @@ -722,6 +753,7 @@ impl Check { adaptive_relevance: None, status_hook: None, nonverbose_failure_output: None, + failure_output_patterns: &[], missing_component_hint: None, baseline_triggers: &[], is_formatter: false, @@ -730,7 +762,7 @@ impl Check { activate_unconditionally: false, category: Category::Default, toolchain: None, - windows_java_jar: false, + java_jar: None, workflow_setup: None, fix_behavior: FixBehavior::Definitive, fix_after: vec![], @@ -798,10 +830,16 @@ impl Check { self } + /// Invoke this binary via `java -jar ` rather than directly. + /// Use for self-executing JARs (e.g. ktlint and Checkstyle). + pub fn java_jar(mut self) -> Self { + self.java_jar = Some(JavaJarMode::AllPlatforms); + self + } + /// On Windows, invoke this binary via `java -jar ` rather than directly. - /// Use for self-executing JARs (e.g. ktlint) that cmd.exe cannot run. pub fn windows_java_jar(mut self) -> Self { - self.windows_java_jar = true; + self.java_jar = Some(JavaJarMode::WindowsOnly); self } @@ -995,6 +1033,11 @@ impl Check { self } + pub fn failure_output_patterns(mut self, patterns: &'static [&'static str]) -> Self { + self.failure_output_patterns = patterns; + self + } + pub fn missing_component_hint( mut self, component: &'static str, diff --git a/src/runner.rs b/src/runner.rs index 954a29ca..dda9210d 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -47,6 +47,7 @@ struct InvocationOutputPolicy<'a> { env: &'a [(&'static str, &'static str)], nonverbose_filter_prefixes: &'a [&'static str], stderr_filter_prefixes: &'a [&'static str], + failure_output_patterns: &'a [&'static str], } /// A check with all inputs pre-resolved, ready to execute without borrowing @@ -56,10 +57,11 @@ enum PreparedCheck { name: String, argv_list: Vec>, tracked_files: Vec, - windows_java_jar: bool, + java_jar: bool, env: &'static [(&'static str, &'static str)], nonverbose_filter_prefixes: &'static [&'static str], stderr_filter_prefixes: &'static [&'static str], + failure_output_patterns: &'static [&'static str], nonverbose_failure_output: Option, missing_component_hint: Option, }, @@ -81,10 +83,11 @@ impl PreparedCheck { Self::Invocations { argv_list, tracked_files, - windows_java_jar, + java_jar, env, nonverbose_filter_prefixes, stderr_filter_prefixes, + failure_output_patterns, nonverbose_failure_output, missing_component_hint, .. @@ -97,7 +100,7 @@ impl PreparedCheck { let out = run_invocations( &name, &argv_list, - windows_java_jar, + java_jar, InvocationOutputPolicy { nonverbose: !verbose, env: if verbose { &[] } else { env }, @@ -107,6 +110,7 @@ impl PreparedCheck { nonverbose_filter_prefixes }, stderr_filter_prefixes: if verbose { &[] } else { stderr_filter_prefixes }, + failure_output_patterns, }, nonverbose_failure_output, missing_component_hint, @@ -274,10 +278,13 @@ fn prepare( name, argv_list, tracked_files, - windows_java_jar: check.windows_java_jar, + java_jar: check + .java_jar + .is_some_and(|mode| mode.enabled_on_current_platform()), env: check.env, nonverbose_filter_prefixes: check.nonverbose_filter_prefixes, stderr_filter_prefixes: check.stderr_filter_prefixes, + failure_output_patterns: check.failure_output_patterns, nonverbose_failure_output: check.nonverbose_failure_output, missing_component_hint: check.missing_component_hint, }) @@ -573,7 +580,7 @@ fn render_config_args(config_args: &[String]) -> String { async fn run_invocations( name: &str, invocations: &[Vec], - windows_java_jar: bool, + java_jar: bool, output_policy: InvocationOutputPolicy<'_>, nonverbose_failure_output: Option, missing_component_hint: Option, @@ -587,13 +594,16 @@ async fn run_invocations( if argv.is_empty() { continue; } - let mut cmd = crate::linters::spawn_command(argv, windows_java_jar); + let mut cmd = crate::linters::spawn_command(argv, java_jar); cmd.current_dir(root) .stdin(Stdio::null()) .envs(output_policy.env.iter().copied()); let result = cmd.output().await; match result { Ok(out) => { + let output_policy_failed = + output_contains_any(&out.stdout, output_policy.failure_output_patterns) + || output_contains_any(&out.stderr, output_policy.failure_output_patterns); if output_policy.nonverbose && !out.status.success() && let Some(normalize) = nonverbose_failure_output @@ -634,7 +644,7 @@ async fn run_invocations( combined_stderr.extend_from_slice(&stderr); } } - if !out.status.success() { + if !out.status.success() || output_policy_failed { all_ok = false; } } @@ -656,6 +666,17 @@ async fn run_invocations( } } +fn output_contains_any(output: &[u8], patterns: &[&str]) -> bool { + patterns + .iter() + .filter(|pattern| !pattern.is_empty()) + .any(|pattern| { + output + .windows(pattern.len()) + .any(|window| window == pattern.as_bytes()) + }) +} + fn filter_stderr_lines(stderr: &[u8], prefixes: &[&str]) -> Vec { let text = String::from_utf8_lossy(stderr); let mut out = String::new(); @@ -921,6 +942,7 @@ mod tests { adaptive_relevance: None, status_hook: None, nonverbose_failure_output: None, + failure_output_patterns: &[], missing_component_hint: None, baseline_triggers: &[], is_formatter: false, @@ -929,7 +951,7 @@ mod tests { activate_unconditionally: false, category: Category::Default, toolchain: None, - windows_java_jar: false, + java_jar: None, workflow_setup: None, fix_behavior: crate::registry::FixBehavior::Definitive, fix_after: vec![], @@ -960,6 +982,17 @@ mod tests { } } + #[test] + fn failure_output_patterns_match_stdout_and_stderr() { + assert!(output_contains_any(b"[WARN] violation\n", &["[WARN]"])); + assert!(output_contains_any( + b"error: [WARN] violation\n", + &["[WARN]"] + )); + assert!(!output_contains_any(b"clean\n", &["[WARN]"])); + assert!(!output_contains_any(b"anything\n", &[""])); + } + #[test] fn fix_order_follows_declared_dependencies() { let mut first = project_check(&[]); diff --git a/tests/cases/checkstyle/clean/files/Foo.java b/tests/cases/checkstyle/clean/files/Foo.java new file mode 100644 index 00000000..4e6a6de6 --- /dev/null +++ b/tests/cases/checkstyle/clean/files/Foo.java @@ -0,0 +1 @@ +class Foo {} diff --git a/tests/cases/checkstyle/clean/files/checkstyle.xml b/tests/cases/checkstyle/clean/files/checkstyle.xml new file mode 100644 index 00000000..aab0fd81 --- /dev/null +++ b/tests/cases/checkstyle/clean/files/checkstyle.xml @@ -0,0 +1 @@ + diff --git a/tests/cases/checkstyle/clean/files/mise.toml b/tests/cases/checkstyle/clean/files/mise.toml new file mode 100644 index 00000000..f773a5f9 --- /dev/null +++ b/tests/cases/checkstyle/clean/files/mise.toml @@ -0,0 +1,2 @@ +[tools] +"http:checkstyle" = { version = "13.8.0", url = "https://github.com/checkstyle/checkstyle/releases/download/checkstyle-{{ version }}/checkstyle-{{ version }}-all.jar", bin = "checkstyle" } diff --git a/tests/cases/checkstyle/clean/test.toml b/tests/cases/checkstyle/clean/test.toml new file mode 100644 index 00000000..9d41c3ed --- /dev/null +++ b/tests/cases/checkstyle/clean/test.toml @@ -0,0 +1,15 @@ +[expected] +args = "run --full checkstyle" +exit = 0 + +[fake_bins] +checkstyle = ''' +#!/bin/sh +exit 0 +''' +java = ''' +#!/bin/sh +echo "Starting audit..." +echo "Audit done." >&2 +exit 0 +''' diff --git a/tests/cases/checkstyle/missing-config/files/Foo.java b/tests/cases/checkstyle/missing-config/files/Foo.java new file mode 100644 index 00000000..4e6a6de6 --- /dev/null +++ b/tests/cases/checkstyle/missing-config/files/Foo.java @@ -0,0 +1 @@ +class Foo {} diff --git a/tests/cases/checkstyle/missing-config/files/mise.toml b/tests/cases/checkstyle/missing-config/files/mise.toml new file mode 100644 index 00000000..f773a5f9 --- /dev/null +++ b/tests/cases/checkstyle/missing-config/files/mise.toml @@ -0,0 +1,2 @@ +[tools] +"http:checkstyle" = { version = "13.8.0", url = "https://github.com/checkstyle/checkstyle/releases/download/checkstyle-{{ version }}/checkstyle-{{ version }}-all.jar", bin = "checkstyle" } diff --git a/tests/cases/checkstyle/missing-config/test.toml b/tests/cases/checkstyle/missing-config/test.toml new file mode 100644 index 00000000..2878b1df --- /dev/null +++ b/tests/cases/checkstyle/missing-config/test.toml @@ -0,0 +1,21 @@ +[expected] +args = "run --full checkstyle" +exit = 1 +stderr = ''' +[checkstyle] +Could not find config XML file 'checkstyle.xml'. + +flint: 1 check failed (checkstyle) +💡 Try `flint run --fix` to auto-fix lint issues, then re-run `flint run` to verify. +''' + +[fake_bins] +checkstyle = ''' +#!/bin/sh +exit 0 +''' +java = ''' +#!/bin/sh +printf "Could not find config XML file 'checkstyle.xml'.\\n" +exit 1 +''' diff --git a/tests/cases/checkstyle/warning/files/Foo.java b/tests/cases/checkstyle/warning/files/Foo.java new file mode 100644 index 00000000..4e6a6de6 --- /dev/null +++ b/tests/cases/checkstyle/warning/files/Foo.java @@ -0,0 +1 @@ +class Foo {} diff --git a/tests/cases/checkstyle/warning/files/checkstyle.xml b/tests/cases/checkstyle/warning/files/checkstyle.xml new file mode 100644 index 00000000..aab0fd81 --- /dev/null +++ b/tests/cases/checkstyle/warning/files/checkstyle.xml @@ -0,0 +1 @@ + diff --git a/tests/cases/checkstyle/warning/files/mise.toml b/tests/cases/checkstyle/warning/files/mise.toml new file mode 100644 index 00000000..f773a5f9 --- /dev/null +++ b/tests/cases/checkstyle/warning/files/mise.toml @@ -0,0 +1,2 @@ +[tools] +"http:checkstyle" = { version = "13.8.0", url = "https://github.com/checkstyle/checkstyle/releases/download/checkstyle-{{ version }}/checkstyle-{{ version }}-all.jar", bin = "checkstyle" } diff --git a/tests/cases/checkstyle/warning/test.toml b/tests/cases/checkstyle/warning/test.toml new file mode 100644 index 00000000..dae0cc21 --- /dev/null +++ b/tests/cases/checkstyle/warning/test.toml @@ -0,0 +1,20 @@ +[expected] +args = "run --full checkstyle" +exit = 1 +stderr = ''' +[checkstyle] +[WARN] Foo.java:1: warning\n +flint: 1 check failed (checkstyle) +💡 Try `flint run --fix` to auto-fix lint issues, then re-run `flint run` to verify. +''' + +[fake_bins] +checkstyle = ''' +#!/bin/sh +exit 0 +''' +java = ''' +#!/bin/sh +printf '[WARN] Foo.java:1: warning\\n' +exit 0 +''' From 431602e9ba2f10220409a81ac084946187d1f5a1 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 27 Jul 2026 09:45:52 +0000 Subject: [PATCH 2/4] chore: use direct mise Checkstyle tool Signed-off-by: Gregor Zeitlinger --- .github/renovate-tracked-deps.json | 10 +++---- .github/renovate.json5 | 2 +- .github/workflows/lint.yml | 4 +-- .github/workflows/mise-registry.yml | 4 +-- .github/workflows/release-plz.yml | 8 +++--- .github/workflows/release.yml | 28 +++++++++---------- .github/workflows/test.yml | 12 ++++---- default.json | 2 +- docs/linters/checkstyle.md | 2 +- mise.toml | 2 +- src/init/scaffold.rs | 4 +-- src/registry/checks.rs | 2 -- tests/cases/checkstyle/clean/files/mise.toml | 2 +- .../checkstyle/missing-config/files/mise.toml | 2 +- .../cases/checkstyle/warning/files/mise.toml | 2 +- 15 files changed, 42 insertions(+), 44 deletions(-) diff --git a/.github/renovate-tracked-deps.json b/.github/renovate-tracked-deps.json index 4251e71d..c29d68fa 100644 --- a/.github/renovate-tracked-deps.json +++ b/.github/renovate-tracked-deps.json @@ -16,6 +16,10 @@ "packageName": "biomejs/biome", "datasource": "github-tags" }, + "checkstyle": { + "packageName": "checkstyle/checkstyle", + "datasource": "github-releases" + }, "editorconfig-checker": { "packageName": "editorconfig-checker/editorconfig-checker", "datasource": "github-releases" @@ -32,10 +36,6 @@ "packageName": "hadolint/hadolint", "datasource": "github-tags" }, - "http:checkstyle": { - "packageName": "checkstyle/checkstyle", - "datasource": "github-releases" - }, "ktlint": { "packageName": "pinterest/ktlint", "datasource": "github-releases" @@ -113,13 +113,13 @@ "aqua:jonwiggins/xmloxide", "aqua:owenlamont/ryl", "biome", + "checkstyle", "dotnet", "editorconfig-checker", "go", "golangci-lint", "google-java-format", "hadolint", - "http:checkstyle", "ktlint", "lychee", "node", diff --git a/.github/renovate.json5 b/.github/renovate.json5 index e531580f..46b6e2a7 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -60,11 +60,11 @@ "aqua:jonwiggins/xmloxide", "aqua:owenlamont/ryl", "biome", + "checkstyle", "editorconfig-checker", "golangci-lint", "google-java-format", "hadolint", - "http:checkstyle", "ktlint", "lychee", "npm:renovate", diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 4bce43f9..53c4261f 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -25,8 +25,8 @@ jobs: - name: Setup mise uses: jdx/mise-action@dad1bfd3df957f44999b559dd69dc1671cb4e9ea # v4.2.1 with: - version: v2026.7.7 - sha256: 429f71e7e989908bf975aafac9066329c16e2d8fc7cd8e74fdf21dd6300ffe7c + version: v2026.7.14 + sha256: fc96308f4fa085d7359892ac6351ededb35ecfabf1ddc34f5757bc755a2af8a6 # mise may activate an existing Rust toolchain without adding missing components. - name: Install Rust lint components diff --git a/.github/workflows/mise-registry.yml b/.github/workflows/mise-registry.yml index ea040d10..5ec3f835 100644 --- a/.github/workflows/mise-registry.yml +++ b/.github/workflows/mise-registry.yml @@ -23,8 +23,8 @@ jobs: - name: Setup mise uses: jdx/mise-action@dad1bfd3df957f44999b559dd69dc1671cb4e9ea # v4.2.1 with: - version: v2026.7.7 - sha256: 429f71e7e989908bf975aafac9066329c16e2d8fc7cd8e74fdf21dd6300ffe7c + version: v2026.7.14 + sha256: fc96308f4fa085d7359892ac6351ededb35ecfabf1ddc34f5757bc755a2af8a6 cache_key: "{{default}}-{{env.MISE_ENABLE_TOOLS}}" - name: Restore Rust cache uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 diff --git a/.github/workflows/release-plz.yml b/.github/workflows/release-plz.yml index fe123f8d..086a894a 100644 --- a/.github/workflows/release-plz.yml +++ b/.github/workflows/release-plz.yml @@ -29,8 +29,8 @@ jobs: - name: Setup mise uses: jdx/mise-action@dad1bfd3df957f44999b559dd69dc1671cb4e9ea # v4.2.1 with: - version: v2026.7.7 - sha256: 429f71e7e989908bf975aafac9066329c16e2d8fc7cd8e74fdf21dd6300ffe7c + version: v2026.7.14 + sha256: fc96308f4fa085d7359892ac6351ededb35ecfabf1ddc34f5757bc755a2af8a6 cache_key: "{{default}}-{{env.MISE_ENABLE_TOOLS}}" - name: Create release metadata env: @@ -62,8 +62,8 @@ jobs: - name: Setup mise uses: jdx/mise-action@dad1bfd3df957f44999b559dd69dc1671cb4e9ea # v4.2.1 with: - version: v2026.7.7 - sha256: 429f71e7e989908bf975aafac9066329c16e2d8fc7cd8e74fdf21dd6300ffe7c + version: v2026.7.14 + sha256: fc96308f4fa085d7359892ac6351ededb35ecfabf1ddc34f5757bc755a2af8a6 cache_key: "{{default}}-{{env.MISE_ENABLE_TOOLS}}" - name: Update release PR env: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 44fa68a2..96d7bc74 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -30,35 +30,35 @@ jobs: include: - target: x86_64-unknown-linux-gnu runner: ubuntu-24.04 - mise_version: v2026.7.7 - mise_sha256: 429f71e7e989908bf975aafac9066329c16e2d8fc7cd8e74fdf21dd6300ffe7c + mise_version: v2026.7.14 + mise_sha256: fc96308f4fa085d7359892ac6351ededb35ecfabf1ddc34f5757bc755a2af8a6 - target: x86_64-unknown-linux-musl runner: ubuntu-24.04 build-tool: cross - mise_version: v2026.7.7 - mise_sha256: 429f71e7e989908bf975aafac9066329c16e2d8fc7cd8e74fdf21dd6300ffe7c + mise_version: v2026.7.14 + mise_sha256: fc96308f4fa085d7359892ac6351ededb35ecfabf1ddc34f5757bc755a2af8a6 - target: aarch64-unknown-linux-gnu runner: ubuntu-24.04 build-tool: cross - mise_version: v2026.7.7 - mise_sha256: 429f71e7e989908bf975aafac9066329c16e2d8fc7cd8e74fdf21dd6300ffe7c + mise_version: v2026.7.14 + mise_sha256: fc96308f4fa085d7359892ac6351ededb35ecfabf1ddc34f5757bc755a2af8a6 - target: aarch64-unknown-linux-musl runner: ubuntu-24.04 build-tool: cross - mise_version: v2026.7.7 - mise_sha256: 429f71e7e989908bf975aafac9066329c16e2d8fc7cd8e74fdf21dd6300ffe7c + mise_version: v2026.7.14 + mise_sha256: fc96308f4fa085d7359892ac6351ededb35ecfabf1ddc34f5757bc755a2af8a6 - target: x86_64-apple-darwin runner: macos-15-intel - mise_version: v2026.7.7 - mise_sha256: 7b860e6495eea9a264a16dae575ac20d5618ea2fe97905756c661eb02035c5d9 + mise_version: v2026.7.14 + mise_sha256: 3a3cf40fd034f83bd5cdffd4d673d40b04a79d06affbd30e5fcc4f00ae0ac460 - target: aarch64-apple-darwin runner: macos-latest - mise_version: v2026.7.7 - mise_sha256: 5b890cccc75fc43a494b83ace21dbd2ee26120ff19ba1994cdcd054b3a15abbd + mise_version: v2026.7.14 + mise_sha256: 082262daa1cd73e22f71272c574afda560c4fcf39852bc18884eae9e13cd5f2c - target: x86_64-pc-windows-msvc runner: windows-latest - mise_version: v2026.7.7 - mise_sha256: 918214d1fbfa1ac9845484a54784e32df49aeb86157a010dc36a532943d73e1e + mise_version: v2026.7.14 + mise_sha256: acf83125cf0166701ffa661be72cbb26a852d31b22d2acc399a974f1d3812862 steps: - name: Checkout code diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f97cfa6d..165cc1e7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,14 +17,14 @@ jobs: matrix: include: - os: ubuntu-24.04 - mise_version: v2026.7.7 - mise_sha256: 429f71e7e989908bf975aafac9066329c16e2d8fc7cd8e74fdf21dd6300ffe7c + mise_version: v2026.7.14 + mise_sha256: fc96308f4fa085d7359892ac6351ededb35ecfabf1ddc34f5757bc755a2af8a6 - os: macos-15 - mise_version: v2026.7.7 - mise_sha256: 5b890cccc75fc43a494b83ace21dbd2ee26120ff19ba1994cdcd054b3a15abbd + mise_version: v2026.7.14 + mise_sha256: 082262daa1cd73e22f71272c574afda560c4fcf39852bc18884eae9e13cd5f2c - os: windows-2025 - mise_version: v2026.7.7 - mise_sha256: 918214d1fbfa1ac9845484a54784e32df49aeb86157a010dc36a532943d73e1e + mise_version: v2026.7.14 + mise_sha256: acf83125cf0166701ffa661be72cbb26a852d31b22d2acc399a974f1d3812862 permissions: contents: read diff --git a/default.json b/default.json index e9e94d5d..cc73c9a2 100644 --- a/default.json +++ b/default.json @@ -24,11 +24,11 @@ "aqua:jonwiggins/xmloxide", "aqua:owenlamont/ryl", "biome", + "checkstyle", "editorconfig-checker", "golangci-lint", "google-java-format", "hadolint", - "http:checkstyle", "ktlint", "lychee", "npm:renovate", diff --git a/docs/linters/checkstyle.md b/docs/linters/checkstyle.md index dfcefdd3..9ff2ce46 100644 --- a/docs/linters/checkstyle.md +++ b/docs/linters/checkstyle.md @@ -20,7 +20,7 @@ is report-only; use a formatter such as Flint runs the standalone Checkstyle CLI against selected Java files. A Java runtime must be available on `PATH` because Checkstyle is distributed as a JAR. -Flint resolves that JAR from the `http:checkstyle` entry in `mise.toml` and +Flint resolves that JAR from the direct `checkstyle` entry in `mise.toml` and invokes it with `java -jar` on every platform. The repository must provide `checkstyle.xml` at its root. A root-level diff --git a/mise.toml b/mise.toml index 4868a266..4b90a47e 100644 --- a/mise.toml +++ b/mise.toml @@ -13,11 +13,11 @@ actionlint = "1.7.12" "aqua:jonwiggins/xmloxide" = "0.4.3" "aqua:owenlamont/ryl" = "0.21.0" biome = "2.5.4" +checkstyle = "13.8.0" editorconfig-checker = "3.8.0" golangci-lint = "2.12.2" google-java-format = "1.35.0" hadolint = "2.14.0" -"http:checkstyle" = { version = "13.8.0", url = "https://github.com/checkstyle/checkstyle/releases/download/checkstyle-{{ version }}/checkstyle-{{ version }}-all.jar", bin = "checkstyle" } ktlint = "1.8.0" lychee = "0.24.2" "npm:renovate" = "43.265.4" diff --git a/src/init/scaffold.rs b/src/init/scaffold.rs index b1569787..933bcb0f 100644 --- a/src/init/scaffold.rs +++ b/src/init/scaffold.rs @@ -55,8 +55,8 @@ jobs: - name: Setup mise uses: jdx/mise-action@dad1bfd3df957f44999b559dd69dc1671cb4e9ea # v4.2.1 with: - version: v2026.7.7 - sha256: 429f71e7e989908bf975aafac9066329c16e2d8fc7cd8e74fdf21dd6300ffe7c + version: v2026.7.14 + sha256: fc96308f4fa085d7359892ac6351ededb35ecfabf1ddc34f5757bc755a2af8a6 {rust_steps} - name: Lint env: diff --git a/src/registry/checks.rs b/src/registry/checks.rs index 8835d1ee..9beb432e 100644 --- a/src/registry/checks.rs +++ b/src/registry/checks.rs @@ -55,7 +55,6 @@ const XMLLINT_URL: &str = "https://github.com/jonwiggins/xmloxide"; const YAMLLINT_CONFIG_URL: &str = "https://yamllint.readthedocs.io/en/stable/configuration.html"; const RYL_URL: &str = "https://github.com/owenlamont/ryl"; -const CHECKSTYLE_TOOL_KEY: &str = "http:checkstyle"; const CHECKSTYLE_BASELINE_TRIGGERS: &[ConfigFile] = &[ConfigFile::project("checkstyle-suppressions.xml")]; @@ -609,7 +608,6 @@ fn check_checkstyle() -> Check { &["*.java"], ) .java_jar() - .mise_tool(CHECKSTYLE_TOOL_KEY) .baseline_config(ConfigFile::project("checkstyle.xml")) .baseline_triggers(CHECKSTYLE_BASELINE_TRIGGERS) .failure_output_patterns(&["[WARN]", "[ERROR]"]) diff --git a/tests/cases/checkstyle/clean/files/mise.toml b/tests/cases/checkstyle/clean/files/mise.toml index f773a5f9..40b6fd3f 100644 --- a/tests/cases/checkstyle/clean/files/mise.toml +++ b/tests/cases/checkstyle/clean/files/mise.toml @@ -1,2 +1,2 @@ [tools] -"http:checkstyle" = { version = "13.8.0", url = "https://github.com/checkstyle/checkstyle/releases/download/checkstyle-{{ version }}/checkstyle-{{ version }}-all.jar", bin = "checkstyle" } +checkstyle = "13.8.0" diff --git a/tests/cases/checkstyle/missing-config/files/mise.toml b/tests/cases/checkstyle/missing-config/files/mise.toml index f773a5f9..40b6fd3f 100644 --- a/tests/cases/checkstyle/missing-config/files/mise.toml +++ b/tests/cases/checkstyle/missing-config/files/mise.toml @@ -1,2 +1,2 @@ [tools] -"http:checkstyle" = { version = "13.8.0", url = "https://github.com/checkstyle/checkstyle/releases/download/checkstyle-{{ version }}/checkstyle-{{ version }}-all.jar", bin = "checkstyle" } +checkstyle = "13.8.0" diff --git a/tests/cases/checkstyle/warning/files/mise.toml b/tests/cases/checkstyle/warning/files/mise.toml index f773a5f9..40b6fd3f 100644 --- a/tests/cases/checkstyle/warning/files/mise.toml +++ b/tests/cases/checkstyle/warning/files/mise.toml @@ -1,2 +1,2 @@ [tools] -"http:checkstyle" = { version = "13.8.0", url = "https://github.com/checkstyle/checkstyle/releases/download/checkstyle-{{ version }}/checkstyle-{{ version }}-all.jar", bin = "checkstyle" } +checkstyle = "13.8.0" From 652601cdfa9fec9bdc6ff2a7d492a83f54d291a6 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 27 Jul 2026 10:24:42 +0000 Subject: [PATCH 3/4] chore: allow Renovate libzip package Signed-off-by: Gregor Zeitlinger --- mise.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mise.toml b/mise.toml index 4b90a47e..4627fd51 100644 --- a/mise.toml +++ b/mise.toml @@ -20,7 +20,7 @@ google-java-format = "1.35.0" hadolint = "2.14.0" ktlint = "1.8.0" lychee = "0.24.2" -"npm:renovate" = "43.265.4" +"npm:renovate" = { version = "43.265.4", trust_policy_excludes = ["@yarnpkg/libzip@3.2.2"] } ruff = "0.15.22" rumdl = "0.2.34" shellcheck = "0.11.0" From 9d0a600a5f6c98cfdb430b415927e149538574a5 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 27 Jul 2026 10:54:59 +0000 Subject: [PATCH 4/4] docs: explain Renovate trust exception Signed-off-by: Gregor Zeitlinger --- mise.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mise.toml b/mise.toml index 4627fd51..cbfa0b0c 100644 --- a/mise.toml +++ b/mise.toml @@ -20,6 +20,8 @@ google-java-format = "1.35.0" hadolint = "2.14.0" ktlint = "1.8.0" lychee = "0.24.2" +# @yarnpkg/libzip 3.2.2 is npm-signed and matches Yarn's release commit, but +# was published without provenance; mise's no-downgrade policy otherwise rejects Renovate. "npm:renovate" = { version = "43.265.4", trust_policy_excludes = ["@yarnpkg/libzip@3.2.2"] } ruff = "0.15.22" rumdl = "0.2.34"