feat: use a build file (pom.xml / build.gradle / build.sbt / build.mill) as a JBang dependency - #2657
Open
maxandersen wants to merge 1 commit into
Open
feat: use a build file (pom.xml / build.gradle / build.sbt / build.mill) as a JBang dependency#2657maxandersen wants to merge 1 commit into
maxandersen wants to merge 1 commit into
Conversation
Contributor
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Team Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
maxandersen
force-pushed
the
builddeps
branch
from
September 3, 2026 20:54
dc51d1e to
ac9ac09
Compare
Adds an experimental //DEPS syntax that lets a script depend on a build file (pom.xml, build.gradle[.kts], build.sbt, build.mill, build.mill.yaml, build.sc). JBang invokes the matching build tool and adds its compile classpath to the script's classpath. Works from //DEPS directives in local scripts and from --deps on the command line. Design ------ * Strategy pattern: BuildSystem interface + one class per tool (Maven, Gradle, sbt, Mill). BuildTools holds the shared subprocess runner, wrapper-script detection, and JBANG_CLASSPATH= marker helpers. BuildSystemClassPaths coordinates dispatch, path resolution, and caching. * Wrappers are preferred over global tools (mvnw, gradlew, ./mill). * Resolved classpaths are cached under $JBANG_DIR/cache/projects/buildclasspaths/ keyed by build file path + mtime + size, with a jar-existence sanity check to invalidate stale entries when the local repo has been wiped. Clear with `jbang cache clear --projects`. Tool-specific handling ---------------------- * Maven: `dependency:build-classpath` with an output file so we never have to parse Maven's log. * Gradle: a temporary init script registers `jbangPrintClasspath` on any subproject with the `java` plugin. Fails loudly if no such subproject exists, instead of silently returning empty. * sbt: `sbt --error --batch "export Compile / dependencyClasspath"` with output validated to look like a classpath (contains File.pathSeparator or ends with .jar). * Mill: `mill --disable-ticker show compileClasspath`; parses the JSON output while ignoring log lines and JVM `sun.misc.Unsafe` warnings that also contain `[`, and strips Mill's `qref:vN:HASH:` / `ref:vN:HASH:` entry prefixes. Path resolution --------------- * Script-embedded `//DEPS build.gradle` is resolved relative to the script file. * CLI `--deps build.gradle` is resolved relative to CWD (previously resolved to the script's directory, which for remote/aliased scripts is a cache dir under ~/.jbang/cache/urls/). * `//DEPS ^pom.xml` uses `Util.findNearestWith` to walk up from the script's directory to find the file. * Embedded build-file deps in remote/URL-based scripts are rejected up front with an actionable error rather than trying to resolve them against the download cache. Ant is not supported (no standard compile-classpath convention). Tests ----- * Unit tests in TestBuildSystemClassPaths cover each strategy via wrapper-script stubs, `^` lookup, CWD-based CLI resolution, cache behavior, remote-script rejection, and failure paths. * Integration tests in BuildSystemClassPathsIT exercise all four real build tools using fixtures under `itests/builddeps/<tool>/`. Each fixture ships a `mise.toml` declaring the tool it needs; the IT runs `mise install` per fixture and then `mise exec` to invoke jbang with the declared tools on PATH. Tests skip cleanly when mise is not installed. Mill ships its official bootstrap script (`./mill`) in the fixture, matching how real Mill projects work. Docs ---- `docs/modules/ROOT/pages/running.adoc` now has a dedicated section with a "Why" motivation, a per-tool support table, caching behavior, and limitations.
maxandersen
force-pushed
the
builddeps
branch
from
September 3, 2026 21:00
ac9ac09 to
ea81e3f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Experimental: use a build file as a JBang dependency
Supersedes #2597 (which only covered Maven + Gradle and lacked caching, integration tests, and remote-script safeguards). Addresses #449 and #43.
Adds an experimental
//DEPS <build-file>(and--deps <build-file>) syntax that lets a script reuse the compile dependencies declared in a real project's build file. JBang invokes the matching build tool, extracts the compile classpath, caches it, and adds the entries to the script's classpath.Command-line form:
What changed vs #2597
BuildSysteminterface + one class per tool (MavenBuildSystem,GradleBuildSystem,SbtBuildSystem,MillBuildSystem). Shared plumbing (subprocess runner, wrapper detection,JBANG_CLASSPATH=marker) lives inBuildTools. Adding a fifth tool is a new class + one line in a registry.--disable-ticker show compileClasspathand understands theqref:vN:HASH:PATH/ref:vN:HASH:PATHentry format. sbt usesexport Compile / dependencyClasspathwith output validation.jbang cache clear --projects.--depspath resolution fixed to resolve relative to CWD instead of the script's directory. Previouslyjbang --deps pom.xml properties@jbangdevlooked forpom.xmlin the catalog cache dir. Regression test included.//DEPS build.gradlein a script fetched from a URL/catalog is rejected up front with an actionable error, instead of silently trying to resolve against the download cache.build.xmledits, which isn't worth the surface area.itests/builddeps/<tool>/for each supported tool with apom.xml/build.gradle/build.sbt/build.mill, asrc/main/java/example/Greeter.javaproject class, and amise.tomldeclaring the tool version needed.BuildSystemClassPathsITusesmise install+mise execto run each tool for real; skips cleanly when mise isn't installed. Mill ships its official./millbootstrap script the way real Mill projects do.Known scope limitation (feedback wanted)
Only the project's declared compile dependencies are added — the project's own compiled classes are not. If you need to reference the project's source from a script, pull the files in with
//SOURCES:A future release may add a scope option (
compilevsruntime) so the project's own output can be included automatically. Which scope should be the default? Feedback welcome — comment below.Security
Build files can execute code. This is called out in the docs and is why the feature is marked EXPERIMENTAL. Only use with build files you trust.
Testing
TestBuildSystemClassPaths): 11 tests covering per-strategy dispatch,^lookup, CWD-based CLI resolution, cache hit/miss, remote-script rejection, and failure paths.BuildSystemClassPathsIT): all four tools exercised end-to-end viamise— passes on my machine, skips whenmiseisn't installed.spotlessCheckclean.