Add SetupJavaDiscoverConfig to detect JDKs installed by GitHub's
setup-java action at paths like:
- /opt/hostedtoolcache/Java_Zulu_jdk/25.0.1-8/x64 (Linux)
- C:\hostedtoolcache\windows\Java_Temurin-Hotspot_jdk\11.0.29-7\x64 (Windows)
These JDKs are now available in fullJavaHomes as zulu@25.0.1,
temurin@11.0.29, etc.
Supported vendors: Zulu, Temurin, Adopt, Corretto, Liberica,
Microsoft, Semeru. Temurin-Hotspot and Adopt are normalized to
temurin.
Fixes#8582
* test: Refactor setup-java tests to use real directory structure
---------
Co-authored-by: mkdev11 <noreply@users.noreply.github.com>
When running commands like 'Test/definedTests' on multi-project builds,
the output was showing raw Vector(...) format instead of nicely formatted
per-item output.
Before:
[info] svc / Test / definedTests
[info] Vector(Test FooSpec : ..., Test BarSpec : ..., ...)
After:
[info] svc / Test / definedTests
[info] * Test FooSpec : ...
[info] * Test BarSpec : ...
The fix extends printSettings to check if values are Seq types in
the multi-project case and format each item on its own line with
a '* ' prefix, matching the single-project behavior.
**Problem**
Currently the shell delegates request tasks even when a non-existent
task like Compile / update is requested.
**Solution**
This removes the delegation, if the input key is scoped, so it will fail.
We will, however, continue to delegate on the subproject axis,
since it's useful to use Global or ThisBuild scoping.
Fixes#8356
**Problem**
When `sbtn` sends a command while another long-running task (like `console`) is already executing, the client silently blocks with no indication that the command is waiting in a queue.
**Solution**
When a new command arrives via the network channel and another command is currently running, the server now sends an `ExecStatusEvent` notification with status `"Queued"` to the client. The client displays a message like:
```
[info] waiting for: console
```
**Problem**
When binary compatibility eviction errors occur, users cannot run
`dependencyTree` to debug the dependency conflict because it fails
with the same eviction error.
**Solution**
Set `evictionErrorLevel` and `assumedEvictionErrorLevel` to `Level.Warn`
for the `dependencyTreeIgnoreMissingUpdate` task, allowing the dependency
tree to be displayed even when eviction errors are present.
Fixes#7255
When using fork := true, sbt spawns child processes that may become
stale if cancelled. Previously, these processes were not cleaned up
when running the exit command.
This fix adds RunningProcesses.killAll() to the shutdown hook so that
all tracked forked processes are terminated when sbt exits.
Fixes#7468
Fixes#7481
When sbt is started by a remote client (BSP or thin client via --server flag),
always start the server regardless of autoStartServer setting. The autoStartServer
setting is meant for automatic server startup, not for blocking explicit server
start requests.
Fixes#7489
When using nested task scopes like otherTask / testTask, the
inputFileChanges macro was returning the wrong scope. It checked
if the scope already had a task axis and returned it as-is, but
this meant it would use otherTask's scope instead of testTask's.
The fix always sets the task axis to the key being queried,
ensuring fileInputs settings are found at the correct scope.
When watchTriggers is explicitly set (non-empty), use only watchTriggers
instead of combining them with fileInputs. This allows users to control
what triggers the watch by setting watchTriggers.
Fixes#7130
When sbt.version in build.properties has trailing whitespace,
sbt incorrectly reports a version mismatch even after reboot.
This fix trims the property value in all places where sbt.version
is read from build.properties:
- Main.scala (version mismatch warning)
- MainLoop.scala (clean command version detection)
- ScriptedTests.scala (test compatibility check)
Fixes#8103
**Problem**
When a val definition in build.sbt changes and the user runs `reload`, sbt crashes with `NoClassDefFoundError: $Wrap<hash>$`.
```
java.lang.NoClassDefFoundError: $Wrape8743d4f36$
at $Wrap0b8ea34d40$.$anonfun$1(build.sbt:1)
```
The workaround was to delete `project/target` directory.
**Solution**
The root cause was that imports were not included in the hash calculation when evaluating build.sbt expressions. When a val definition changes:
1. Its `$Wrap` module gets a new hash
2. Settings that reference the val get new imports pointing to the new module
3. But if the setting expression didn't change, its hash was the same
4. The old cached class was loaded with bytecode referencing the old module
Fix: Include imports in the hash calculation in `Eval.evalCommon`. Also re-enable `cleanEvalClasses` in `Load.scala` which was disabled pending this fix.
Filters out empty versions during parser construction to prevent RuntimeException when creating token parsers. Includes comprehensive test coverage for edge cases.
DependencyTreePlugin is an AutoPlugin with trigger = AllRequirements,
so it loads automatically in scripted tests without requiring explicit
plugin configuration.
Fixes#7511
The previous check used contains("scala-library") which incorrectly
matched any jar with that substring anywhere in the filename, causing
user libraries named like "my-scala-library-foo" to be misclassified
as the Scala standard library and filtered from the classpath.
Changed to use exact match (scala-library.jar) or prefix match
(scala-library-*) to only match the actual Scala library jars,
consistent with how scala-reflect is detected on line 199.
Scala 2.x has supported pipelining since 2020. The fix now allows:
- All Scala 2.x versions (pipelining supported)
- Scala 3.5.0+ (pipelining added in 3.5)
Generated-by: AI-assisted
* Add JSON output support to dependencyLicenseInfo
- Add LicenseInfo rendering object with text and JSON output
- Add dependencyLicenseInfo input task key
- Implement dependencyLicenseInfo task with JSON format support
- Supports --out option for file output
- Auto-detects JSON format from .json file extension
- Follows same pattern as dependencyTree task
Resolves#7771
When using '++version project/task', the parser now accepts project/command
patterns (e.g., 'docs/docusaurusPublishGhpages') even if the project doesn't
exist in the current state. This is achieved by adding a fallback parser
that accepts any 'project/command' pattern alongside the combinedParser.
Previously, '++2.12.19 docs/task' would fail with 'Project not found' if
'docs' project wasn't available in the current Scala version, but
'++2.12.19; docs/task' worked. Now both syntaxes work correctly.
The fix is targeted to only accept slash-delimited patterns, avoiding
interference with other parser components like the -v verbose flag.
Fixes#7574
This adds a new setting that allows users to
configure Coursier's FileCache to cache local file:// artifacts. When enabled,
artifacts from local repositories are copied to the cache directory, which is
useful for scenarios like bundling compiler artifacts in a local repo for
offline use.
Fixes#7547
**Problem**
When cross-building sbt plugins with explicit `scalaVersion` set in `build.sbt`, the `updateSbtClassifiers` task fails because it uses the launcher's Scala version instead of the appropriate Scala version for the target sbt version.
For example, with this configuration:
```scala
lazy val root = (project in file("."))
.enablePlugins(SbtPlugin)
.settings(
scalaVersion := "2.10.7", // Explicit for IDE support
crossSbtVersions := Seq("0.13.17", "1.0.0"),
)
```
Running sbt "show updateSbtClassifiers" would fail with:
Error downloading org.scala-sbt:scripted-plugin_2.12:0.13.17
It should look for scripted-plugin_2.10:0.13.17 since sbt 0.13.x uses Scala 2.10.
**Solution**
Modified sbtClassifiersTasks in Defaults.scala to:
1. Check if the project is an sbt plugin (sbtPlugin.value)
2. For plugins, derive the Scala version from pluginCrossBuild / sbtBinaryVersion using PluginCross.scalaVersionFromSbtBinaryVersion
3. For non-plugins, continue using the launcher's Scala version (original behavior)
**Problem**
When project A's dependencies changed and A was compiled in one command, project B (depending on A) would not invalidate its update cache in a subsequent command. This caused stale classpaths.
The root cause was that `depsUpdated` only checked `!stats.cached`, which only detected fresh resolves within the same command. When a dependency was served from cache (even if resolved fresh in a previous command), `cached` was marked `true`, causing incorrect cache reuse.
Debug scenario from issue:
sbt:aaa> clean
sbt:aaa> a/compile
sbt:aaa> show itTests/depsUpdated
[info] * false <-- BUG: should be true
**Solution**
Added `stamp: String` field to `UpdateStats` that records when the update was resolved. This stamp persists across commands and enables accurate cross-command comparison:
- If any dependency's stamp > our cached stamp, we re-resolve
- Falls back to `!cached` check for backwards compatibility with old caches
- Using `String` type allows future transition from timestamps to content hashes
Set window title to 'sbt <command>: <org> % <name> % <version>' when
running sbt run, runMain, bgRun, or bgRunMain.
For server-side runs, window title is set directly. For client-side runs (sbtn), window title is passed via RunInfo protocol
and set by NetworkClient.
Fixes#7586
When Java compiler generates warnings about missing annotations from
JAR files, the path format is jar:file:///C:/... which causes
InvalidPathException on Windows due to the : character.
The fix filters out jar: paths in toDocument(), similar to how fake
positions like <macro> are already filtered out. This prevents the
exception and allows compilation to continue.
Diagnostics for files inside JARs are not shown in the IDE, which is
correct behavior since they cannot be edited.
Fixes#7665
Generated-by: Cascade (AI pair programmer)
Address review feedback from eed3si9n to make it clearer that GC time
is cumulative CPU time across parallel collectors, which is why it can
exceed wall clock time.
Fixes#8002
**Problem**
consoleProject doesn't work. REPL doesn't even start.
**Solution**
I made some progress into consoleProject.
At least Scala 3.7 repl session will now start.
The problem is that compiler bridge has not implemented binding,
so we can't forward the sbt build information into the repl.
**Problems**
When running forked tests, sbt uses `Runtime.getRuntime().availableProcessors()` to determine the thread pool size, ignoring `concurrentRestrictions`. This is inconsistent with non-forked parallel tests.
**Expectations**
Users should be able to control the number of parallel test threads in forked mode, similar to how `concurrentRestrictions` works for non-forked tests.
**Notes**
Added a new setting `testForkedParallelism` that allows explicit control:
```scala
testForkedParallelism := Some(2) // Use 2 threads
testForkedParallelism := None // Use availableProcessors() (default)
```
Eviction warnings and errors were not reported for Test dependencies because
`EvictionError` only checked the Compile configuration.
This fix runs the eviction check for both Compile and Test configurations
separately, with distinct error messages:
- Compile: `found version conflict(s) in library dependencies`
- Test: `found version conflict(s) in Test dependencies`
When project loading fails in batch mode, sbt was showing an interactive
prompt asking the user to choose between retry, quit, last, or ignore.
However, in batch mode there is no interactive terminal, causing the
process to hang waiting for input that will never come.
This fix checks if we're in batch mode (Prompt.Batch) and automatically
exits with failure (equivalent to 'q' quit option) without prompting the
user. This prevents infinite retry loops on persistent errors and allows
batch mode scripts to fail fast, which is appropriate for CI/CD environments.
The interactive behavior remains unchanged for non-batch mode.
**Problem**
There's a disconnect between what is perceived to be the current
Scala version, and what sbt uses internally, and thus what it
chooses to be the default scalaVersion.
**Solution**
This displays a warning if scalaVersion setting is missing.
**Problem**
There's a disconnect between what is perceived to be the current
Scala version, and what sbt uses internally, and thus what it
chooses to be the default scalaVersion.
**Solution**
This displays a warning if scalaVersion setting is missing.
**Problem**
sbt 2.x uses crossTarget by default, but it contains Scala version
even when crossPaths is false.
**Solution**
This replaces it with the letter "u" for unspecified.