From a6dcff0b675ed1b291a9aa29984abf7ad7d2be17 Mon Sep 17 00:00:00 2001 From: Radoslaw Nowacki Date: Mon, 28 Sep 2026 15:05:16 +0200 Subject: [PATCH 1/4] fix(bgp): don't force the plugin's AGP version onto consuming apps The plugin declared AGP as an `implementation` dependency, so it ended up on the app's buildscript classpath and won version resolution. Since #448 bumped it to AGP 9.2.1, every consumer gets AGP 9.2.1 and its minimum Gradle 9.4.1, which breaks Expo SDK 57 apps (Gradle 9.3.1): "Minimum supported Gradle version is 9.4.1. Current version is 9.3.1." Compile against AGP but let the app provide it at runtime. Also drop the leftover version matrix from the Expo 57 Android build job, which ran the same Expo 57 build twice. --- .github/workflows/ci.yml | 5 ----- gradle-plugins/react/brownfield/build.gradle.kts | 9 +++++++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d8682592..4be24aea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -217,11 +217,6 @@ jobs: needs.filter.outputs.ci == 'true' ) && (needs.build-lint.result == 'success' || needs.build-lint.result == 'skipped') - strategy: - matrix: - include: - - version: '58' - - version: '57' steps: - name: Checkout diff --git a/gradle-plugins/react/brownfield/build.gradle.kts b/gradle-plugins/react/brownfield/build.gradle.kts index b73354d7..2965bb81 100644 --- a/gradle-plugins/react/brownfield/build.gradle.kts +++ b/gradle-plugins/react/brownfield/build.gradle.kts @@ -104,10 +104,15 @@ repositories { } dependencies { - implementation(libs.agp) - implementation(libs.common) + // AGP is provided by the consuming app's build. Declaring it as `implementation` puts it on the + // app's buildscript classpath, where it wins version resolution and forces this AGP (and its minimum + // Gradle version) onto the app + compileOnly(libs.agp) + compileOnly(libs.common) implementation(libs.asm.commons) implementation(libs.versioncompare) + testImplementation(libs.agp) + testImplementation(libs.common) testImplementation(libs.junit.jupiter) testImplementation(gradleTestKit()) testImplementation(kotlin("test")) From f0541ef0cb336f9ba9fc035b8e076aaa55ecfca3 Mon Sep 17 00:00:00 2001 From: Radoslaw Nowacki Date: Mon, 28 Sep 2026 15:28:14 +0200 Subject: [PATCH 2/4] test(bgp): put AGP on the TestKit plugin classpath GradleRunner.withPluginClasspath() is built from the runtime classpath, which no longer has AGP now that it is compileOnly, so LegacyConsumerConfigurationTest could not apply com.android.library. --- gradle-plugins/react/brownfield/build.gradle.kts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/gradle-plugins/react/brownfield/build.gradle.kts b/gradle-plugins/react/brownfield/build.gradle.kts index 2965bb81..032bb973 100644 --- a/gradle-plugins/react/brownfield/build.gradle.kts +++ b/gradle-plugins/react/brownfield/build.gradle.kts @@ -103,6 +103,10 @@ repositories { google() } +// AGP for GradleRunner.withPluginClasspath(), which only sees runtime dependencies, so TestKit +// projects can still apply com.android.library +val testKitPluginClasspath: Configuration by configurations.creating + dependencies { // AGP is provided by the consuming app's build. Declaring it as `implementation` puts it on the // app's buildscript classpath, where it wins version resolution and forces this AGP (and its minimum @@ -116,6 +120,11 @@ dependencies { testImplementation(libs.junit.jupiter) testImplementation(gradleTestKit()) testImplementation(kotlin("test")) + testKitPluginClasspath(libs.agp) +} + +tasks.pluginUnderTestMetadata { + pluginClasspath.from(testKitPluginClasspath) } tasks.test { From 670090de9b1b0fe3356a5ff9dff12ded165d114b Mon Sep 17 00:00:00 2001 From: Radoslaw Nowacki Date: Tue, 29 Sep 2026 13:38:28 +0200 Subject: [PATCH 3/4] test(e2e): rename AndroidApp Jest config for Expo 58 #467 renamed the Expo 56 app and AppleApp's jest.config.expo56.cjs to expo58, but not AndroidApp's, so .detoxrc.expo58.cjs points at a file that doesn't exist and Detox E2E (AndroidApp - Expo 58) fails with "Can't find a root directory while resolving a config file path". --- .../e2e/{jest.config.expo56.cjs => jest.config.expo58.cjs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/AndroidApp/e2e/{jest.config.expo56.cjs => jest.config.expo58.cjs} (100%) diff --git a/apps/AndroidApp/e2e/jest.config.expo56.cjs b/apps/AndroidApp/e2e/jest.config.expo58.cjs similarity index 100% rename from apps/AndroidApp/e2e/jest.config.expo56.cjs rename to apps/AndroidApp/e2e/jest.config.expo58.cjs From 5e9e0336746cf364e6503c9ad373a1c58014d8ff Mon Sep 17 00:00:00 2001 From: Radoslaw Nowacki Date: Tue, 29 Sep 2026 13:38:28 +0200 Subject: [PATCH 4/4] fix(bgp): compile against AGP 8.5.2 With AGP compileOnly the app provides AGP at runtime, but a plugin built against AGP 9.2.1 references AGP 9 only classes and fails on AGP 8 apps: Expo 57 (AGP 8.12) failed with NoClassDefFoundError com/android/build/api/dsl/AndroidLibrarySourceSet. Built against 8.5.2 (the version before #448) it applies on both AGP 8.12.0 and 9.2.1. --- gradle-plugins/react/brownfield/gradle/libs.versions.toml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gradle-plugins/react/brownfield/gradle/libs.versions.toml b/gradle-plugins/react/brownfield/gradle/libs.versions.toml index 6ce14827..e117de2d 100644 --- a/gradle-plugins/react/brownfield/gradle/libs.versions.toml +++ b/gradle-plugins/react/brownfield/gradle/libs.versions.toml @@ -2,8 +2,10 @@ kotlinJvm = "2.2.21" ktlint = "12.1.1" detekt = "1.23.7" -agp = "9.2.1" -common = "32.2.0" +# Compile against the oldest supported AGP: AGP is compileOnly, so the app provides it at runtime, +# and a plugin built against AGP 9 fails on AGP 8 apps (e.g. Expo 57) with NoClassDefFoundError +agp = "8.5.2" +common = "31.2.2" # do not bump it for now, as it throws an error for incompatible AGP used asm-commons = "9.7" versioncompare = "1.5.0" junit = "5.11.4"