Skip to content

feat(matrix): Fetch AGP<->Kotlin compat dynamically#1166

Open
romtsn wants to merge 5 commits intomainfrom
rz/feat/dynamic-agp-kotlin-compat
Open

feat(matrix): Fetch AGP<->Kotlin compat dynamically#1166
romtsn wants to merge 5 commits intomainfrom
rz/feat/dynamic-agp-kotlin-compat

Conversation

@romtsn
Copy link
Copy Markdown
Member

@romtsn romtsn commented Apr 23, 2026

#skip-changelog

Replace the static gradleToKotlin dict in scripts/generate-compat-matrix.main.kts with a fetch of the AGP ↔ Kotlin compatibility table from developer.android.com/build/kotlin-support. For each AGP version in the CI matrix we now pick the highest Kotlin whose required AGP is ≤ ours, which is a more direct semantic fit than the previous Gradle→Kotlin hand-picked map and also catches new Kotlin minors automatically.

Follow-up to #1165, which switched the AGP↔Gradle source.

The existing Kotlin→min-Gradle floor check (sourced from kotlinlang.org via fetchKotlinGradleCompatibility) stays in place, so if the chosen Kotlin needs a newer Gradle than AGP does, we still bump Gradle up.

Verified output locally against the four AGP versions the matrix generator picks today:

AGP Kotlin (before) Kotlin (after)
9.3.0-alpha01 2.3.0 2.4.0
9.2.0-rc01 2.1.0 2.4.0
9.2.0 2.1.0 2.4.0
8.13.2 1.8.20 2.3.0

Gradle versions are unchanged.

Replace the static gradleToKotlin dict with a fetch of the AGP/Kotlin
compatibility table from developer.android.com/build/kotlin-support.
For each AGP version we now pick the highest Kotlin whose required AGP
is <= ours, which is a more direct semantic fit and also catches new
Kotlin minors automatically. The existing Kotlin->min-Gradle floor
check (sourced from kotlinlang.org) stays in place.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 23, 2026

Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 059375b

Comment thread scripts/generate-compat-matrix.main.kts
val kotlinVersion =
agpToKotlin
.filter { (minAgp, _) -> agpVersion >= minAgp }
.maxByOrNull { it.first }
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maxByOrNull selects by AGP instead of Kotlin version

Medium Severity

The comment says "Pick the latest Kotlin whose required AGP <= this AGP" but maxByOrNull { it.first } maximizes by the AGP component of the pair, not the Kotlin version (it.second). When two Kotlin versions share the same minimum AGP requirement (e.g., Kotlin 1.4 and 1.5 both require AGP 7.0), maxByOrNull returns the first encountered element at that tie — which is the lower Kotlin version. Selecting by it.second (the Kotlin version) would correctly pick the highest compatible Kotlin in all cases.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit d3f7cb4. Configure here.

romtsn and others added 2 commits April 23, 2026 13:41
The developer.android.com/build/kotlin-support table lists upcoming
Kotlin minors before they ship (e.g. Kotlin 2.4 with AGP 9.1.0 while
only 2.4.0-Beta* is on Maven Central). Resolve each Kotlin minor to
its latest stable patch by reading kotlin-stdlib's maven-metadata.xml
and drop rows whose minor has no stable release yet, so the generated
matrix never references an unpublished version.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
KSP 2.1.0-1.0.29 is pinned to Kotlin compiler 2.1.0 and fails with
"ksp-2.1.0-1.0.29 is too old for kotlin-2.3.21" when the test matrix
runs the android-instrumentation-sample against newer Kotlin versions.
Bump to 2.3.7, which is the latest KSP2 release — KSP2 is decoupled
from the Kotlin compiler version and works across the Kotlin versions
the matrix now picks from developer.android.com/build/kotlin-support.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread scripts/generate-compat-matrix.main.kts
Comment thread gradle/libs.versions.toml Outdated
romtsn and others added 2 commits April 23, 2026 14:05
The pinned KSP (2.1.0-1.0.29, KSP1) is bound to the Kotlin 2.1 compiler
and fails with "ksp is too old for kotlin-X" when the test matrix picks
newer Kotlin versions from developer.android.com/build/kotlin-support.
Bumping KSP directly breaks the default build because KSP2 requires
Kotlin language version 2.0+, but the default Kotlin in Dependencies.kt
is 1.8.20.

Intercept plugin resolution in settings.gradle.kts: when VERSION_KOTLIN
is set (i.e. the matrix is driving the build), use KSP2 2.3.7, which is
decoupled from the Kotlin compiler. Otherwise leave the pinned KSP1 in
place so default / pre-merge builds keep working.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The settings.gradle.kts resolutionStrategy override didn't work because
plugin-alias requests through the version catalog bypass it — Gradle
rejected the rewrite with "the plugin is already on the classpath with
a different version". Switch to the same pattern the other Kotlin
plugins use: a `BuildPluginsVersion.KSP` field sourced from VERSION_KOTLIN
(KSP2 2.3.7 when Kotlin 2.x, KSP1 2.1.0-1.0.29 otherwise), applied via
`version BuildPluginsVersion.KSP` on both the root `apply false` and the
sample's plugins block.

Verified locally that both default builds (Kotlin 1.8.20, KSP1) and the
matrix path (VERSION_KOTLIN=2.3.21, KSP2) resolve and run
`kspStagingReleaseKotlin` successfully.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
// Pick the latest Kotlin whose required AGP <= this AGP
val kotlinVersion =
agpToKotlin
.filter { (minAgp, _) -> agpVersion >= minAgp }
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The semver comparison agpVersion >= minAgp will incorrectly evaluate to false for prerelease AGP versions, leading to an older Kotlin version being selected.
Severity: MEDIUM

Suggested Fix

Before the comparison, strip the prerelease label from the agpVersion object. This will ensure that versions like 9.3.0-alpha01 and 9.3.0 are treated as equivalent for the purpose of this check, preventing the incorrect selection of an older Kotlin version.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: scripts/generate-compat-matrix.main.kts#L108

Potential issue: The semver comparison `agpVersion >= minAgp` will evaluate to `false`
for prerelease AGP versions (e.g., `9.3.0-alpha01`) when the compatibility table's
`minAgp` has the same major, minor, and patch version (e.g., `9.3.0`). This is because
`minAgp` has its prerelease label stripped, while `agpVersion` does not. According to
SemVer rules, `9.3.0-alpha01` is less than `9.3.0`. This will cause the build matrix
generation script to silently select an older, incorrect Kotlin version for that
prerelease AGP entry.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 059375b. Configure here.

Comment thread build.gradle.kts
alias(libs.plugins.kotlinAndroid) version BuildPluginsVersion.KOTLIN apply false
alias(libs.plugins.kapt) version BuildPluginsVersion.KOTLIN apply false
alias(libs.plugins.ksp) apply false
alias(libs.plugins.ksp) version BuildPluginsVersion.KSP apply false
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compose compiler plugin version not overridden for new Kotlin versions

High Severity

The composeCompiler plugin (org.jetbrains.kotlin.plugin.compose) is declared without a version override, leaving it pinned at 2.1.0 from the catalog. The other Kotlin plugins (kotlin, kotlinAndroid, kapt) all use version BuildPluginsVersion.KOTLIN, and this PR adds version BuildPluginsVersion.KSP for KSP — but composeCompiler was missed. Since the matrix now produces Kotlin 2.3.0 and 2.4.0 for all entries, the example project that conditionally applies this plugin will hit a version mismatch, as the compose compiler plugin version must match the Kotlin version.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 059375b. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant