Skip to content

Commit 83d86bf

Browse files
romtsnclaude
andauthored
fix(ci): Fallback to AGP release notes for Gradle version lookup (#1128)
* fix(ci): Fallback to AGP release notes for Gradle version lookup When an AGP version (e.g. 9.2.0) is not yet listed in the compatibility table at about-agp, fetch the minimum Gradle version from the AGP release notes page instead of falling back to the latest table entry. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(ci): Format script and add Kotlin 2.3.10 for Gradle 9.5+ AGP 9.2.0-alpha06 depends on Kotlin 2.3.10, so Gradle 9.5+ needs to use that version instead of 2.1.0 to avoid dependency resolution conflicts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(ci): Use pre-release key for Kotlin 2.3.10 Gradle mapping 9.5.0-milestone-5 < 9.5.0 in semver (pre-releases have lower precedence), so use 9.5.0-0 as the map key to ensure milestone versions match. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(ci): Try Kotlin 2.3.0 for Gradle 9.5+ Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(ci): Dynamically set Kotlin language version based on compiler Kotlin 2.3+ dropped support for language version 1.8. Use 2.0 when building with Kotlin 2.3+, otherwise keep 1.8. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(ci): Continue searching tables when version parse fails in release notes Fixed-issues tables can have cells like "Android Gradle Plugin" that match the "Gradle" check but aren't version strings. Continue the loop instead of returning null so the actual compatibility table is found. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(ci): Validate table headers and match exact "Gradle" cell in release notes Skip tables without "version" in headers (e.g. fixed-issues tables) and match cells[0] exactly as "Gradle" instead of contains-check to avoid false matches like "Android Gradle Plugin". Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * compile against a static AGP version --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8d98ebc commit 83d86bf

3 files changed

Lines changed: 58 additions & 15 deletions

File tree

.github/workflows/test-matrix-agp-gradle.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ jobs:
5151
name: Test Matrix - AGP ${{ matrix.agp }} - Gradle ${{ matrix.gradle }} - Java ${{ matrix.java }} - Kotlin ${{ matrix.kotlin }}
5252
env:
5353
VERSION_AGP: ${{ matrix.agp }}
54-
VERSION_GROOVY: ${{ matrix.groovy }}
5554
VERSION_KOTLIN: ${{ matrix.kotlin }}
5655
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
5756

plugin-build/build.gradle.kts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import java.util.Properties
55
import org.gradle.api.tasks.testing.logging.TestLogEvent
66
import org.jetbrains.kotlin.config.KotlinCompilerVersion
77
import org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11
8-
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_8
8+
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
99
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
1010

1111
plugins {
@@ -31,7 +31,7 @@ val fixtureClasspath: Configuration by configurations.creating
3131

3232
dependencies {
3333
compileOnly(libs.gradleApi)
34-
compileOnly(Libs.AGP)
34+
compileOnly(libs.agp)
3535
compileOnly(libs.proguard)
3636

3737
implementation(libs.asm)
@@ -91,8 +91,15 @@ tasks.withType<KotlinCompile>().configureEach {
9191

9292
compilerOptions {
9393
jvmTarget.set(JVM_11)
94-
languageVersion.set(KOTLIN_1_8)
95-
apiVersion.set(KOTLIN_1_8)
94+
// Kotlin supports current + 3 previous language versions.
95+
// We want 1.8, but if the compiler no longer supports it, use the oldest it does support.
96+
// e.g. Kotlin 2.1 oldest=1.8, Kotlin 2.3 oldest=2.0
97+
val compilerParts = KotlinCompilerVersion.VERSION.split(".")
98+
val compilerFlat = compilerParts[0].toInt() * 10 + compilerParts[1].toInt()
99+
val oldestFlat = maxOf(compilerFlat - 3, 18) // 18 = Kotlin 1.8
100+
val kotlinLangVersion = KotlinVersion.valueOf("KOTLIN_${oldestFlat / 10}_${oldestFlat % 10}")
101+
languageVersion.set(kotlinLangVersion)
102+
apiVersion.set(kotlinLangVersion)
96103
}
97104
}
98105

scripts/generate-compat-matrix.main.kts

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,12 @@ class GenerateMatrix : CliktCommand() {
6363
val (currentVersions, latestVersion) = fetchAgpCompatibilityTable(agpVersions)
6464
buildMap<Version, Version> {
6565
for (agpVersion in agpVersions) {
66-
put(
67-
agpVersion,
68-
legacyVersions[agpVersion] ?: currentVersions[agpVersion] ?: latestVersion,
69-
)
66+
val gradleVersion =
67+
legacyVersions[agpVersion]
68+
?: currentVersions[agpVersion]
69+
?: fetchGradleVersionFromReleaseNotes(agpVersion)
70+
?: latestVersion
71+
put(agpVersion, gradleVersion)
7072
}
7173
}
7274
} catch (e: Exception) {
@@ -86,12 +88,11 @@ class GenerateMatrix : CliktCommand() {
8688
}
8789

8890
// TODO: for now this is manual, but we could try get it from Gradle's github in the future
89-
val gradleToGroovy =
90-
mapOf("7.5".toVersion(strict = false) to "1.2", "8.11".toVersion(strict = false) to "1.7.1")
9191
val gradleToKotlin =
9292
mapOf(
9393
"7.5".toVersion(strict = false) to "1.8.20",
9494
"9.0.0".toVersion(strict = false) to "2.1.0",
95+
"9.5.0-0".toVersion(strict = false) to "2.3.0",
9596
)
9697
// TODO: make it dynamic too
9798
val kotlinVersion = "2.1.0".toVersion()
@@ -128,10 +129,6 @@ class GenerateMatrix : CliktCommand() {
128129
)
129130
// TODO: if needed we can test against different Java versions
130131
put("java", "17")
131-
val groovy = gradleToGroovy.entries.findLast { finalGradle >= it.key }?.value
132-
if (groovy != null) {
133-
put("groovy", groovy)
134-
}
135132
val kotlin = gradleToKotlin.entries.findLast { finalGradle >= it.key }?.value
136133
if (kotlin != null) {
137134
put("kotlin", kotlin)
@@ -346,6 +343,46 @@ class GenerateMatrix : CliktCommand() {
346343

347344
return gradleVersions to latest.value
348345
}
346+
347+
/**
348+
* Fetches the minimum required Gradle version from the AGP release notes page. This is used as a
349+
* fallback when the AGP version is not yet listed in the compatibility table.
350+
*
351+
* @param agpVersion the AGP version to look up
352+
* @return the minimum required Gradle version, or null if the release notes page doesn't exist
353+
*/
354+
private fun fetchGradleVersionFromReleaseNotes(agpVersion: Version): Version? {
355+
// Release notes URLs are per-minor version and always use patch 0
356+
// e.g. agp-9-2-0-release-notes covers all 9.2.x versions
357+
val url =
358+
"https://developer.android.com/build/releases/agp-${agpVersion.major}-${agpVersion.minor}-0-release-notes"
359+
val html =
360+
try {
361+
URL(url).readText()
362+
} catch (e: Throwable) {
363+
echo("Warning: Could not fetch release notes from $url")
364+
return null
365+
}
366+
val doc = Jsoup.parse(html)
367+
val tables = doc.select("table")
368+
for (table in tables) {
369+
val headers = table.select("tr").firstOrNull()?.select("th")?.map { it.text() } ?: continue
370+
// The compatibility table has "Minimum version" and "Default version" columns
371+
if (headers.none { it.contains("version", ignoreCase = true) }) continue
372+
for (row in table.select("tr")) {
373+
val cells = row.select("td").map { it.text() }
374+
if (cells.size >= 2 && cells[0].trim().equals("Gradle", ignoreCase = true)) {
375+
return try {
376+
Version.parse(cells[1], strict = false)
377+
} catch (e: Throwable) {
378+
echo("Warning: Could not parse Gradle version '${cells[1]}' from release notes")
379+
null
380+
}
381+
}
382+
}
383+
}
384+
return null
385+
}
349386
}
350387

351388
GenerateMatrix().main(args)

0 commit comments

Comments
 (0)