Skip to content

feat: add Gradle and Maven support with Surefire parser (75-90% savings)#782

Open
romualdbassinot-efficy wants to merge 1 commit intortk-ai:developfrom
romualdbassinot-efficy:feat/gradle-maven-support
Open

feat: add Gradle and Maven support with Surefire parser (75-90% savings)#782
romualdbassinot-efficy wants to merge 1 commit intortk-ai:developfrom
romualdbassinot-efficy:feat/gradle-maven-support

Conversation

@romualdbassinot-efficy
Copy link
Copy Markdown

@romualdbassinot-efficy romualdbassinot-efficy commented Mar 22, 2026

Summary

  • Add rtk gradle command with sub-commands: build, test, check, dependencies — filtering Gradle output to errors/failures only (75-90% savings)
  • Add rtk mvn command with sub-commands: compile, test, package, verify, install, dependency:tree — with Surefire XML parser for structured test failure output (75-90% savings)
  • Add real fixtures for both tools (build success/fail, test pass/fail)
  • Register both commands in src/main.rs Commands enum following the Go sub-enum pattern
  • Update CHANGELOG.md and src/discover/rules.rs for missed-savings detection

Changes since initial review (33292fc)

  • gradle: TEST_SUMMARY_RE now captures optional skipped count — passed is correctly total - failed - skipped (previously skipped tests were counted as passing)
  • gradle: empty/no-test runs now return "Gradle test: no tests found" instead of "Gradle test: 0 passed"
  • maven: all-passed format string now uses total_passed instead of total_run, so skipped tests are not reported as passing
  • both: added insta snapshot tests (8 total) for build and test success/failure fixtures

Test plan

  • cargo check --all-targets passes
  • Token savings ≥75% verified via unit tests
  • Snapshot tests added for all 4 fixture files per module
  • rtk gradle build filters Gradle build output to errors only
  • rtk gradle test shows only failed tests with skipped count correct
  • rtk mvn compile filters Maven compile errors
  • rtk mvn test uses Surefire XML when available, falls back to text parser
  • Fallback to raw command on filter failure

🤖 Generated with Claude Code

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Mar 22, 2026

CLA assistant check
All committers have signed the CLA.

@pszymkowiak pszymkowiak added effort-large Plusieurs jours, nouveau module enhancement New feature or request labels Mar 22, 2026
@pszymkowiak
Copy link
Copy Markdown
Collaborator

[w] wshm · Automated triage by AI

📊 Automated PR Analysis

Type feature
🟡 Risk medium

Summary

Adds Gradle and Maven command support to rtk with output filtering that achieves 75-90% token savings. Includes Gradle wrapper auto-detection, Surefire XML test parser for Maven, discovery rules for both build tools, and comprehensive test fixtures.

Review Checklist

  • Tests present
  • Breaking change
  • Docs updated

Analyzed automatically by wshm · This is an automated analysis, not a human review.

@romualdbassinot-efficy romualdbassinot-efficy changed the base branch from master to develop March 22, 2026 20:19
Copy link
Copy Markdown
Collaborator

@pszymkowiak pszymkowiak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — Gradle & Maven support

Good work — real fixtures, savings assertions, gradlew auto-detection, sub-enum pattern. A few things to fix before merge.

P0 — Must Fix

1. CHANGELOG rebase conflict
The diff deletes the Ruby feature entries and the ## [0.31.0] section. Looks like a merge artifact — the [Unreleased] block got duplicated and the old one was removed with its surrounding context. Please check that the full changelog history is intact after your upstream merge.

2. TOML filter conflict
src/filters/gradle.toml and src/filters/mvn-build.toml already exist on develop and match the same commands. The Rust modules are strictly better (Surefire parsing, gradlew detection, sub-enum routing), so please delete the two TOML filters to avoid undefined routing behavior.

P1 — Should Fix

3. Vec<Regex> for noise patterns — O(N×M) per line
Both modules define 17-19 separate Regex objects in a Vec, iterated for every output line. Collapse into a single alternation regex (like rspec_cmd.rs does). Not a blocker but measurable on large Maven reactor builds.

4. ^ - noise pattern too broad (gradle_cmd.rs)
This strips any line starting with -, which catches legitimate output beyond the Gradle welcome banner. Narrow to the welcome block context or use a more specific pattern.

5. run_other missing tee integration
Both gradle_cmd::run_other and maven_cmd::run_other skip tee::tee_and_hint() — if the filter produces wrong output for an unsupported subcommand, the raw output is lost with no recovery path. See run_test/run_build for the pattern to follow.

6. Missing test for compile-failure in filter_gradle_test
The total == 0 && !build_errors.is_empty() path in filter_gradle_test is never exercised. Add a test calling filter_gradle_test with the gradle_build_fail_raw.txt fixture.

P2 — Nice to Have

7. mvn verify falls through to Other instead of the Surefire parser — consider adding a Verify subcommand routing to run_test.

8. All fixtures from a single project — a multi-module reactor fixture would strengthen coverage.


Overall solid implementation. Fix P0 #1 and #2, and I'll re-review.

@aeppling
Copy link
Copy Markdown
Contributor

Hey

We are cleaning up the codebase and improving the project structure for better onboarding. As part of this effort, PR #826 reorganizes src/ from a flat layout into subfolders.

No logic changes — only file moves and import path updates.

What you need to do

Rebase your branch on develop when receiving this comment:

git fetch origin && git rebase origin/develop

Git detects renames automatically. If you get import conflicts, update the paths:

use crate::git;        // now: use crate::cmds::git::git;
use crate::tracking;   // now: use crate::core::tracking;
use crate::config;     // now: use crate::core::config;
use crate::init;       // now: use crate::hooks::init;
use crate::gain;       // now: use crate::analytics::gain;

Need help rebasing? Tag @aeppling

@romualdbassinot-efficy
Copy link
Copy Markdown
Author

All P0 and P1 items addressed in edd2dcf:

P0 #1 — CHANGELOG: Fixed during rebase onto develop — the [Unreleased] section is intact with all Ruby and Gradle/Maven entries, followed by the upstream [0.31.0] block.

P0 #2 — Conflicting TOML filters: Deleted src/filters/gradle.toml and src/filters/mvn-build.toml.

P1 #3Vec<Regex> O(N×M): Collapsed all noise patterns into a single alternation regex (NOISE_RE) in both gradle_cmd.rs and maven_cmd.rs. One is_match() call per line now.

P1 #4^ - too broad: Removed the pattern from the regex entirely. filter_gradle_build now tracks in_welcome_block state — bullet lines are only dropped between "Here are the highlights" and the next empty line.

P1 #5run_other missing tee: Added tee::tee_and_hint() to both gradle_cmd::run_other and maven_cmd::run_other, matching the pattern in run_test/run_build.

P1 #6 — Missing compile-failure test: Added test_filter_gradle_test_with_build_errors which calls filter_gradle_test with gradle_build_fail_raw.txt — exercises the total == 0 && !build_errors.is_empty() branch.

All 23 Gradle/Maven unit tests pass. P2 items (#7 verify routing, #8 multi-module fixture) noted for a follow-up if wanted.

@osipxd
Copy link
Copy Markdown

osipxd commented Mar 30, 2026

Probably related to #381

@romualdbassinot-efficy romualdbassinot-efficy force-pushed the feat/gradle-maven-support branch 2 times, most recently from 16f1d4d to 4a4187a Compare April 10, 2026 13:13
@romualdbassinot-efficy
Copy link
Copy Markdown
Author

Code review

Found 4 issues:

  1. No snapshot tests in either new filter module — cli-testing.md says "Every new filter: All filters must have snapshot test" (priority 🔴 Critical), requiring assert_snapshot! from the insta crate for regression detection.

https://github.com/rtk-ai/rtk/blob/b6bc8ccc2ab91e48b83c25fde47259e896926153/src/cmds/jvm/gradle_cmd.rs#L568-L590

  1. total_passed is computed but immediately suppressed with let _ = total_passed, and the "all passed" format string uses total_run instead — when skipped tests exist, the output overstates the pass count (e.g., "14 passed, 2 skipped" when only 12 actually passed).

let total_failed = total_failures + total_errors;
let total_passed = total_run.saturating_sub(total_failed + total_skipped);
let _ = total_passed; // used implicitly in formatting below
// No tests found
if total_run == 0 {
let time_info = if total_time.is_empty() {
String::new()
} else {
format!(" ({})", total_time)
};
if build_status == "FAILURE" {
return format!("mvn test: BUILD FAILURE{}", time_info);
}
return format!("mvn test: no tests found{}", time_info);
}
// All passed
if total_failed == 0 {
let time_info = if total_time.is_empty() {
String::new()
} else {
format!(" ({})", total_time)
};
let skip_info = if total_skipped > 0 {
format!(", {} skipped", total_skipped)
} else {
String::new()
};
return format!("mvn test: {} passed{}{}", total_run, skip_info, time_info);
}

  1. filter_gradle_test returns "Gradle test: 0 passed" when no tests are found (empty output), while the equivalent Maven path returns "mvn test: no tests found" — the Gradle message is semantically misleading since "0 passed" implies tests were executed.

if failed == 0 && !has_build_failure {
let time_info = if time_str.is_empty() {
String::new()
} else {
format!(" ({})", time_str)
};
return format!("Gradle test: {} passed{}", total, time_info);
}

  1. TEST_SUMMARY_RE only captures total and failed counts ("N tests completed, M failed"), but Gradle's real output includes a skipped count ("22 tests completed, 2 failed, 1 skipped"). The passed calculation at line 262 uses total - fail_count, ignoring skipped tests and overstating the passed count.

// Gradle test summary: "N tests completed, M failed"
static ref TEST_SUMMARY_RE: Regex =
Regex::new(r"^(\d+)\s+tests?\s+completed,\s+(\d+)\s+failed").unwrap();
// Stack trace line (indented, starts with "at ")

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

- Add `rtk gradle` with sub-commands: build, test, check, dependencies
  Filters daemon noise, download progress, UP-TO-DATE tasks; shows
  errors and failures only (75-90% token savings)
- Add `rtk mvn` with sub-commands: compile, test, package, verify,
  install, dependency:tree. Includes Surefire XML parser for structured
  test failure output with text fallback (75-90% token savings)
- Add gradlew wrapper auto-detection (./gradlew vs gradle)
- Register both commands in main.rs following the Go sub-enum pattern
- Delete TOML-based gradle.toml and mvn-build.toml (replaced by Rust)
- Update src/discover/rules.rs and src/hooks for missed-savings detection
- Add 8 real fixtures (Gradle + Maven build/test success/fail)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@novoj
Copy link
Copy Markdown

novoj commented Apr 15, 2026

Any progress in this issue? It would be great to have at least "something" - even if it wouldn't be perfect. I also see there are multiple opened PR for adding Maven/Gradle support. So there surely is quite a demand for this feature 🙏🏼

mariuszs added a commit to mariuszs/rtk-java that referenced this pull request Apr 17, 2026
`mvn verify` (the canonical goal that produces target/failsafe-reports/)
previously fell through to Passthrough — no filtering, no XML enrichment
— even though the failsafe parser was already implemented for run_test.

- New MvnCommands::Verify variant; dispatch_mvn routes to run_verify.
- Extract run_test body to private run_tests_like(binary, goal, ...);
  both run_test and run_verify wrap it. Shared filter + enrichment.
- Parameterize filter_mvn_test summary prefix via filter_mvn_tests_with_goal
  (goal in {"test", "verify"}). Public wrappers filter_mvn_test /
  filter_mvn_verify preserve existing call sites.
- Generalize enrich_with_reports zero-tests detection + error message
  (ends_with(": no tests run"), goal extracted from summary prefix).
- Discover rules: add `verify` to mvn and mvnd patterns.
- Snapshot + prefix-assertion tests for verify path; goal-awareness test
  for enrichment's zero-tests branch.

Addresses P2 rtk-ai#7 from the review of sibling PR rtk-ai#782.
mariuszs added a commit to mariuszs/rtk-java that referenced this pull request Apr 17, 2026
`mvn verify` (the canonical goal that produces target/failsafe-reports/)
previously fell through to Passthrough — no filtering, no XML enrichment
— even though the failsafe parser was already implemented for run_test.

- New MvnCommands::Verify variant; dispatch_mvn routes to run_verify.
- Extract run_test body to private run_tests_like(binary, goal, ...);
  both run_test and run_verify wrap it. Shared filter + enrichment.
- Parameterize filter_mvn_test summary prefix via filter_mvn_tests_with_goal
  (goal in {"test", "verify"}). Public wrappers filter_mvn_test /
  filter_mvn_verify preserve existing call sites.
- Generalize enrich_with_reports zero-tests detection + error message
  (ends_with(": no tests run"), goal extracted from summary prefix).
- Discover rules: add `verify` to mvn and mvnd patterns.
- Snapshot + prefix-assertion tests for verify path; goal-awareness test
  for enrichment's zero-tests branch.

Addresses P2 rtk-ai#7 from the review of sibling PR rtk-ai#782.
mariuszs added a commit to mariuszs/rtk-java that referenced this pull request Apr 17, 2026
`mvn verify` (the canonical goal that produces target/failsafe-reports/)
previously fell through to Passthrough — no filtering, no XML enrichment
— even though the failsafe parser was already implemented for run_test.

- New MvnCommands::Verify variant; dispatch_mvn routes to run_verify.
- Extract run_test body to private run_tests_like(binary, goal, ...);
  both run_test and run_verify wrap it. Shared filter + enrichment.
- Parameterize filter_mvn_test summary prefix via filter_mvn_tests_with_goal
  (goal in {"test", "verify"}). Public wrappers filter_mvn_test /
  filter_mvn_verify preserve existing call sites.
- Generalize enrich_with_reports zero-tests detection + error message
  (ends_with(": no tests run"), goal extracted from summary prefix).
- Discover rules: add `verify` to mvn and mvnd patterns.
- Snapshot + prefix-assertion tests for verify path; goal-awareness test
  for enrichment's zero-tests branch.

Addresses P2 rtk-ai#7 from the review of sibling PR rtk-ai#782.
mariuszs added a commit to mariuszs/rtk-java that referenced this pull request Apr 17, 2026
Multi-module compile output was dominated by the `Reactor Build Order:` block
and per-module `Reactor Summary` status lines (~40 redundant tokens on a
green 5-module build), and javac `[ERROR] <path>:[line,col]` locations were
emitted twice — inline during compilation and again in the trailing help
block — nearly doubling the failure-path output.

Changes in filter_mvn_compile:
- Skip `Reactor Build Order:` block entirely (redundant with per-module
  Building headers that are already stripped).
- Collapse Reactor Summary: emit a compact `Reactor: N modules — M SUCCESS,
  K FAILURE (name, ...)` line only when something failed; all-green reactors
  rely on the surviving `BUILD SUCCESS` line.
- Dedup `[ERROR] <path>:[line,col]` occurrences by (path, line, col). When
  a duplicate fires, swallow the indented `[ERROR] symbol:/location:/
  required:/found:/reason:` context lines that mirror an earlier javac
  explanation emitted without the `[ERROR]` prefix.

Also: broaden `deprecated` check to `deprecat` (catches both `deprecated`
and `deprecation` variants); strip `/pom.xml` path references (previously
only literal `from pom.xml` matched); drop the Help-footer line `For more
information about the errors...` which wasn't in the boilerplate list.

Savings on fixtures adapted from rtk-ai#782 (attribution in filenames):

  mvn_pr782_compile_success_raw  74.6% → 97.8%  (+23pp)
  mvn_pr782_compile_fail_raw     49.1% → 79.7%  (+31pp)
  mvn_pr782_test_pass_raw        98.7% → 98.7%  (unchanged, correct)
  mvn_pr782_test_fail_raw        93.4% → 93.4%  (unchanged, correct)

Four new regression tests validate multi-module accumulation (20 tests
across 6 modules must not report only the first module's count), failure
enumeration uniqueness, reactor collapse, and javac error dedup.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort-large Plusieurs jours, nouveau module enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants