diff --git a/oss-licenses-plugin/build.gradle.kts b/oss-licenses-plugin/build.gradle.kts index f9b0485d..003e23d3 100644 --- a/oss-licenses-plugin/build.gradle.kts +++ b/oss-licenses-plugin/build.gradle.kts @@ -63,6 +63,7 @@ dependencies { testImplementation("com.google.guava:guava:33.7.1-jre") testImplementation("com.google.truth:truth:1.4.5") testImplementation("com.google.code.gson:gson:2.14.0") + testImplementation("org.semver4j:semver4j:6.0.0") testImplementation("com.android.tools.build:gradle:9.2.1") { because("Needed for DependencyTaskTest.") } diff --git a/oss-licenses-plugin/src/e2eTest/kotlin/com/google/android/gms/oss/licenses/plugin/EndToEndTest.kt b/oss-licenses-plugin/src/e2eTest/kotlin/com/google/android/gms/oss/licenses/plugin/EndToEndTest.kt index 2544b915..06cc854f 100644 --- a/oss-licenses-plugin/src/e2eTest/kotlin/com/google/android/gms/oss/licenses/plugin/EndToEndTest.kt +++ b/oss-licenses-plugin/src/e2eTest/kotlin/com/google/android/gms/oss/licenses/plugin/EndToEndTest.kt @@ -23,6 +23,7 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.rules.TemporaryFolder +import org.semver4j.Semver import java.io.File /** @@ -41,9 +42,6 @@ abstract class EndToEndTest { ?: error("Missing ${javaClass.simpleName}.gradleVersion — add to e2eVersions in build.gradle.kts") companion object { - private val AGP_VERSION_REGEX = Regex("""agp = ".*"""") - private val KOTLIN_VERSION_REGEX = Regex("""kotlin = ".*"""") - // AGP 9+ has built-in Kotlin support; AGP 8.x requires the standalone KGP with legacy config. private val AGP_9_KOTLIN_BLOCK = """ kotlin { @@ -100,33 +98,43 @@ abstract class EndToEndTest { } private fun patchVersions() { - val agpBundlesKgp = agpVersion.substringBefore('.').toIntOrNull()?.let { it >= 9 } ?: false + val agp = Semver(agpVersion) + val agpBundlesKgp = agp.isGreaterThanOrEqualTo("9.0.0") + // Compose BOM 2026.09.00+ (Compose 1.12.1+) requires minAgpVersion 9.1.0 in AAR metadata. + val supportsLatestComposeBom = agp.isGreaterThanOrEqualTo("9.1.0") - // Patch AGP (and optionally Kotlin) version in the version catalog val tomlFile = File(projectDir, "gradle/libs.versions.toml") var tomlContent = tomlFile.readText() - check(AGP_VERSION_REGEX.containsMatchIn(tomlContent)) { - "libs.versions.toml missing expected 'agp = \"...\"' entry — has the testapp template changed?" - } - tomlContent = tomlContent.replace(AGP_VERSION_REGEX, "agp = \"$agpVersion\"") + .replaceVersionCatalogEntry("agp", agpVersion) + if (!agpBundlesKgp) { - check(KOTLIN_VERSION_REGEX.containsMatchIn(tomlContent)) { - "libs.versions.toml missing expected 'kotlin = \"...\"' entry — has the testapp template changed?" - } - tomlContent = tomlContent.replace(KOTLIN_VERSION_REGEX, "kotlin = \"2.1.10\"") + tomlContent = tomlContent.replaceVersionCatalogEntry("kotlin", "2.1.10") + patchLegacyKotlinBuildConfig() + } + if (!supportsLatestComposeBom) { + tomlContent = tomlContent.replaceVersionCatalogEntry("androidx-compose-bom", "2026.06.00") } + tomlFile.writeText(tomlContent) + } - // AGP 8.x doesn't have built-in Kotlin support — replace with standalone KGP config - if (!agpBundlesKgp) { - val buildFile = File(projectDir, "app/build.gradle.kts") - val original = buildFile.readText() - val patched = original.replace(AGP_9_KOTLIN_BLOCK, AGP_8_KOTLIN_BLOCK) - check(patched != original) { - "Failed to patch Kotlin block in app/build.gradle.kts — has the testapp template changed?" - } - buildFile.writeText(patched) + private fun String.replaceVersionCatalogEntry(key: String, version: String): String { + val regex = Regex("""${Regex.escape(key)} = ".*"""") + check(regex.containsMatchIn(this)) { + "libs.versions.toml missing expected '$key = \"...\"' entry — has the testapp template changed?" + } + return replace(regex, """$key = "$version"""") + } + + private fun patchLegacyKotlinBuildConfig() { + // AGP 8.x doesn't have built-in Kotlin support — replace with standalone KGP config. + val buildFile = File(projectDir, "app/build.gradle.kts") + val original = buildFile.readText() + val patched = original.replace(AGP_9_KOTLIN_BLOCK, AGP_8_KOTLIN_BLOCK) + check(patched != original) { + "Failed to patch Kotlin block in app/build.gradle.kts — has the testapp template changed?" } + buildFile.writeText(patched) } private fun createRunner(vararg arguments: String): GradleRunner { diff --git a/oss-licenses-plugin/testapp/app/build.gradle.kts b/oss-licenses-plugin/testapp/app/build.gradle.kts index a105a634..d80d1e4b 100644 --- a/oss-licenses-plugin/testapp/app/build.gradle.kts +++ b/oss-licenses-plugin/testapp/app/build.gradle.kts @@ -64,6 +64,11 @@ tasks.withType().configureEach { val javaToolchains = project.extensions.getByType() javaLauncher.set(javaToolchains.launcherFor { languageVersion.set(JavaLanguageVersion.of(21)) }) + // Robolectric 4.17's FileDescriptorInterceptor reflects on jdk.internal.access.SharedSecrets + // when ApplicationSharedMemory.create() initializes on SDK 36+, which requires opening + // java.base/jdk.internal.access to unnamed modules on JDK 21+. + jvmArgs("--add-opens=java.base/jdk.internal.access=ALL-UNNAMED") + // Enable parallel execution for faster Robolectric runs maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).coerceAtLeast(1) diff --git a/oss-licenses-plugin/testapp/app/src/test/resources/robolectric.properties b/oss-licenses-plugin/testapp/app/src/test/resources/robolectric.properties index 71a66445..7e4b79fc 100644 --- a/oss-licenses-plugin/testapp/app/src/test/resources/robolectric.properties +++ b/oss-licenses-plugin/testapp/app/src/test/resources/robolectric.properties @@ -1,3 +1,3 @@ # Global Robolectric Configuration -# Note: SDK 36 (Baklava) requires Java 21+ — Robolectric will fail to run it on older JVMs. -sdk=24, 33, 34, 35, 36 \ No newline at end of file +# Note: SDK 36+ requires Java 21+ — Robolectric will fail to run it on older JVMs. +sdk=24, 33, 34, 35, 36, 37 \ No newline at end of file diff --git a/oss-licenses-plugin/testapp/gradle/libs.versions.toml b/oss-licenses-plugin/testapp/gradle/libs.versions.toml index 6930c8fd..25b5148a 100644 --- a/oss-licenses-plugin/testapp/gradle/libs.versions.toml +++ b/oss-licenses-plugin/testapp/gradle/libs.versions.toml @@ -1,19 +1,19 @@ [versions] -agp = "9.4.0" +agp = "9.4.1" androidx-activity = "1.13.0" androidx-appcompat = "1.8.0" -androidx-compose-bom = "2026.06.00" +androidx-compose-bom = "2026.09.00" androidx-test = "1.7.0" androidx-test-espresso = "3.7.0" androidx-test-ext = "1.3.0" -compileSdk = "36" +compileSdk = "37" junit = "4.13.2" -kotlin = "2.4.10" +kotlin = "2.4.20" minSdk = "24" oss-licenses-plugin = "+" oss-licenses-library = "+" # Always use the latest available -robolectric = "4.16.1" -targetSdk = "36" +robolectric = "4.17" +targetSdk = "37" [libraries] androidx-activity = { module = "androidx.activity:activity", version.ref = "androidx-activity" }