From 6f14de514b60acf3d37ff0a201f2ed0ca3a7d0c2 Mon Sep 17 00:00:00 2001 From: MkDev11 <94194147+MkDev11@users.noreply.github.com> Date: Tue, 20 Jan 2026 09:35:43 -0500 Subject: [PATCH] [2.x] feat: Add setup-java action support in CrossJava (#8574) 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 --- .../main/scala/sbt/internal/CrossJava.scala | 36 ++++++++++++++ .../scala/sbt/internal/CrossJavaTest.scala | 49 +++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/main/src/main/scala/sbt/internal/CrossJava.scala b/main/src/main/scala/sbt/internal/CrossJava.scala index 4dade4805..845773b7e 100644 --- a/main/src/main/scala/sbt/internal/CrossJava.scala +++ b/main/src/main/scala/sbt/internal/CrossJava.scala @@ -484,17 +484,53 @@ private[sbt] object CrossJava { .toVector } + class SetupJavaDiscoverConfig(base: File) extends JavaDiscoverConf { + private val SetupJavaVendorDir = + """Java_(Zulu|Temurin-Hotspot|Temurin|Adopt|Corretto|Liberica|Microsoft|Semeru)_jdk""".r + private val SetupJavaVersionDir = """([0-9]+)\.([0-9]+)\.([0-9]+)(-[0-9]+)?""".r + + private def normalizeVendor(vendor: String): String = vendor.toLowerCase match { + case "temurin-hotspot" => "temurin" + case "adopt" => "temurin" + case other => other + } + + def candidates(): Vector[String] = wrapNull(base.list()) + + def javaHomes: Vector[(String, File)] = + candidates().flatMap { + case vendorDir @ SetupJavaVendorDir(vendor) => + val vendorPath = base / vendorDir + wrapNull(vendorPath.list()).flatMap { + case versionDir @ SetupJavaVersionDir(major, minor, patch, _) => + val versionPath = vendorPath / versionDir + val archDirs = wrapNull(versionPath.list()) + archDirs.headOption.map { arch => + val javaHome = versionPath / arch + val normalizedVendor = normalizeVendor(vendor) + val version = s"$major.$minor.$patch" + val jv = JavaVersion(version).withVendor(normalizedVendor) + jv.toString -> javaHome + } + case _ => None + } + case _ => Vector.empty + } + } + val configs = Vector( new JabbaDiscoverConfig, new SdkmanDiscoverConfig, new LinuxDiscoverConfig(file("/usr") / "java"), new LinuxDiscoverConfig(file("/usr") / "lib" / "jvm"), + new SetupJavaDiscoverConfig(file("/opt") / "hostedtoolcache"), new MacOsDiscoverConfig, new JavaHomeDiscoverConfig, ) ++ { if (IO.isWindows) { def discover(dir: String, vendors: String*) = new WindowsDiscoverConfig(file(dir), vendors) Vector( + new SetupJavaDiscoverConfig(file("C:") / "hostedtoolcache" / "windows"), discover("C://Program Files/Java", "openjdk"), discover("C://Program Files/Eclipse Foundation", "temurin", "adopt"), discover("C://Program Files/Semeru", "semeru", "adopt-openj9"), diff --git a/main/src/test/scala/sbt/internal/CrossJavaTest.scala b/main/src/test/scala/sbt/internal/CrossJavaTest.scala index 804855a1a..bfd8c8059 100644 --- a/main/src/test/scala/sbt/internal/CrossJavaTest.scala +++ b/main/src/test/scala/sbt/internal/CrossJavaTest.scala @@ -9,9 +9,12 @@ package sbt package internal +import java.io.File import org.scalatest.diagrams.Diagrams import org.scalatest.funsuite.AnyFunSuite import sbt.internal.CrossJava.JavaDiscoverConfig.* +import sbt.io.{ IO, syntax } +import sbt.io.syntax.* import scala.collection.immutable.ListMap class CrossJavaTest extends AnyFunSuite with Diagrams { @@ -193,4 +196,50 @@ class CrossJavaTest extends AnyFunSuite with Diagrams { ) ) } + + test("The setup-java selector should correctly pick up Zulu JDK") { + IO.withTemporaryDirectory { temp => + IO.createDirectory(temp / "Java_Zulu_jdk" / "25.0.1-8" / "x64") + val conf = new SetupJavaDiscoverConfig(temp) + val homes = conf.javaHomes + assert(homes.size == 1) + val (version, javaHome) = homes.head + assert(version == "zulu@25.0.1") + assert(javaHome.getName == "x64") + } + } + + test("The setup-java selector should correctly pick up Temurin JDK") { + IO.withTemporaryDirectory { temp => + IO.createDirectory(temp / "Java_Temurin-Hotspot_jdk" / "11.0.29-7" / "x64") + val conf = new SetupJavaDiscoverConfig(temp) + val homes = conf.javaHomes + assert(homes.size == 1) + val (version, javaHome) = homes.head + assert(version == "temurin@11.0.29") + assert(javaHome.getName == "x64") + } + } + + test("The setup-java selector should normalize Temurin-Hotspot to temurin") { + IO.withTemporaryDirectory { temp => + IO.createDirectory(temp / "Java_Temurin-Hotspot_jdk" / "17.0.5-8" / "x64") + val conf = new SetupJavaDiscoverConfig(temp) + val homes = conf.javaHomes + assert(homes.size == 1) + val (version, _) = homes.head + assert(version == "temurin@17.0.5") + } + } + + test("The setup-java selector should normalize Adopt to temurin") { + IO.withTemporaryDirectory { temp => + IO.createDirectory(temp / "Java_Adopt_jdk" / "11.0.15-10" / "x64") + val conf = new SetupJavaDiscoverConfig(temp) + val homes = conf.javaHomes + assert(homes.size == 1) + val (version, _) = homes.head + assert(version == "temurin@11.0.15") + } + } }