feat(gradlew): Gradle support for Android/Kotlin developers - #312
Conversation
|
Hi @yonatankarp, @rubixhacker, @kherembourg! Three Gradle PRs are open at the same time (#263, #288, #312) — they overlap significantly on |
|
Strong implementation — best architecture of the Gradle PRs (streaming/batch/passthrough). 48 tests, real fixtures, Windows
Note: 3 other PRs cover similar scope (#288, #368, #374). This is the strongest Gradle implementation so far. |
|
Note: this PR adds rules to Please remove the changes to |
|
I am very much fine with picking either, I implemented very basic functionality just so the PR will not endup as 24k lines of code 😄 |
|
Hello @yonatankarp We can also merge everything with your PR @rubixhacker but I personally prefer to not mix maven and gradle. |
|
Thanks for the thorough review @pszymkowiak! All 5 items addressed in the latest push (rebased on master + 1 fix commit):
772 tests passing (61 gradlew + 163 discover + rest of suite), |
|
Done ✅ — removed all changes to Added gradle patterns to Rust instead:
|
|
I am good with dropping my PR @kherembourg and doing a separate one targeting Maven 😄 Your PR is more comprehensive for Gradle |
|
Thanks @rubixhacker |
|
Any update on when this will be merged? |
|
Reviewing the code, I think I prefer this PR instead of #381 Sorry @sebastianbarrozo 😄 |
|
I understand reviewers are likely swamped with PRs right now, so it might take a while to get a full review. Happy to make any changes needed to help move this along, just let me know! |
|
Hi! Two things needed before we can review:
Thanks! |
|
Hey We are cleaning up the codebase and improving the project structure for better onboarding. As part of this effort, PR #826 reorganizes No logic changes — only file moves and import path updates. What you need to doRebase your branch on git fetch origin && git rebase origin/developGit 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 |
|
Thanks @pszymkowiak @aeppling |
|
Hey @kherembourg , sorry for the time, could you please remove the cargo.lock from this commit and just accept both change on the rules.rs conflict ? Here is a filter quality review , now a priority to ensure no loss of signal that could cause retries, as well as a few out-of-scope items : Lint filter drops code context linesThe lint filter only keeps lines matching violation regex patterns, silently dropping the code snippet and caret indicator that follow each violation: The LLM gets MainActivity.kt:45: Error: Format string invalid [StringFormatInvalid] with zero context about what code is wrong. It would have to open the file and read line 45, costing more tokens than keeping the 2-3 context lines would have cost. Build filter drops all warningsThe ERROR_LINE regex catches errors but not warnings, should this really be silent ? Out-of-scope changesThe PR modifies Ruby rules unrelated to Gradle:
Tag me here if solved i'll proceed to last review and approval if valid, thanks your patience and contributing to RTK |
|
Hi @aeppling Thanks a lot for the feedback! No worries about the delay, I completely understand the challenges of maintaining a successful open source project. Everything should be addressed:
|
|
Could we merge this soon? Looking forward to it. |
|
Hey @kherembourg This did get correctly rebase with change, please look into the current implementation of rules pattern in the develop branch. This should match other commands implementation by using existing wrappers and functions. We're sorry refacto landed before this PR, but this was our priority and codebase should now conform to this. Tag me once this is fixed so i can check it all good, if need help to implement, you can reach me on the RTK discord |
Adds rtk gradlew command for build, test, lint, and dependency operations on Gradle projects. Filters task progress noise, preserves build scan URLs, test failures, lint violations, and compiler warnings. Recognises ./gradlew, gradlew, gradlew.bat, and gradle invocations. Surfaces unit-test report paths and shows a progress indicator for long-running tasks. Targets 75% savings (90% on test, 80% on build). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Hey @aeppling I have made all the changes, it should be coherent with the refacto on develop now and all changes are related to this PR purpose. |
Extract a new_gradle_command() helper that uses string literals in every Command::new() branch. The .semgrep.yml dynamic-command-execution rule rejects Command::new(var) — semgrep needs to statically audit the executable set. Same runtime behaviour: prefer ./gradlew (or gradlew.bat on Windows), fall back to gradle. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Hey @kherembourg , thanks for looking into this quickly. One thing last, you're still using your own run function like run_streaming() , but in runner.rs we have shared function run with RunMode::Filtered, Streamed, Passthrough. This is still related to the refacto standardization
Beyond fixing the semgrep block, this gives you ChildGuard (zombie prevention), 10 MiB output cap, broken pipe handling, and proper Result return, none of which are in the current implementation. If any issues using this do not hesitate to reach me |
|
You can check commands like cargo_cmd for examples which implement streaming as well |
Replaces custom run_streaming / run_batch / run_passthrough / ProgressIndicator with the shared runner helpers used by cargo and other commands: - Build → runner::run_streamed with a BuildLineFilter implementing StreamFilter - Test/Lint/Connected/Deps → runner::run_filtered with the existing filter_* closures (filter_test, filter_connected, filter_lint, filter_dependencies) - Other / verbose flags → runner::run_passthrough(tool, args, verbose) Benefits inherited from runner.rs: ChildGuard zombie prevention, 10 MiB output cap, broken pipe handling, proper Result<i32> exit-code propagation. run() now returns Result<i32> like cargo_cmd / golangci_cmd. main.rs updated to forward the exit code with `?` directly (no manual `0` wrapper). All Command::new() invocations remain string literals (semgrep dynamic-command-execution rule). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
In new_gradle_command(), the two Command::new("gradle") fallback branches should use resolved_command("gradle"), this is how all other commands resolve system binaries, and handles Windows .CMD/.BAT wrappers correctly. |
|
Then we should be finally good to go ! Thanks for your reactivity |
new_gradle_command() now uses resolved_command("gradle") for the two
fallback branches (Windows + Unix when no local wrapper is present),
matching how cargo / golangci-lint / etc. resolve system binaries.
Local wrappers (./gradlew, gradlew.bat) stay as string literals — they
are relative paths, not on PATH, and semgrep's dynamic-command-execution
rule needs literals here.
Net effect: PATHEXT-aware resolution on Windows (.CMD/.BAT shims work),
no behavioural change on Unix.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Thanks for your feedback @aeppling |
|
LGTM :) Will be released in 0.40.0 , by the end of the week i think! |
Summary
Comprehensive Gradle support for Android and Kotlin developers using
./gradlew(orgradle). Filters verbose Gradle output down to what matters — status, errors, and results — with 60–85% token savings depending on the task.This PR covers the full Android development workflow: building, testing, linting, installing to devices, dependency inspection, and project cleanup.
Commands Handled
rtk gradlew assembleDebugrtk gradlew bundleReleasertk gradlew cleanrtk gradlew installDebugrtk gradlew uninstallDebugrtk gradlew checkrtk gradlew testDebugUnitTestrtk gradlew connectedDebugAndroidTestrtk gradlew lintrtk gradlew dependenciesrtk gradlew <other>Features
is_terminal()guard)gradlewhen./gradlewwrapper is not found in the project--stacktrace,--info,--debugflags bypass all filtering for full outputrtk ./gradlewandrtk gradleboth work as aliases forrtk gradlew./gradlew <cmd>andgradle <cmd>are automatically rewritten tortk gradlew <cmd>by the hookgradlew.batdetected automaticallyArchitecture
cleanargument determines the filter strategy> Task :progress lines, daemon messages, configuration noise; keeps BUILD SUCCESSFUL/FAILED, error lines, and warningsQuality Checks
cargo fmt --all --check— cleancargo clippy --all-targets— no new warningscargo test --all— 494 passed, 0 failed./gradlewoutput on an Android projectgradlerewrite supportManual Testing
Manually tested on a real Android project with
./gradlew:rtk gradlew assembleDebug— build filtered correctly, progress spinner visible in terminalrtk gradlew testDebugUnitTest— only test results shownrtk gradlew clean— task noise stripped, BUILD result preservedrtk gradlew check— mixed test+lint output filtered correctlyrtk gradlew installDebug— install filtered like buildrtk gradlew dependencies— only top-level deps shown per configurationrtk ./gradlew testDebugUnitTest— alias works--stacktrace)rtk gradlew assembleDebug | cat)🤖 Generated with Claude Code