Skip to content

fix(mobile): pin play-services-ads to 25.0.0 so the release build compiles - #344

Merged
thomasluizon merged 1 commit into
mainfrom
fix/android-play-services-ads-kotlin-pin
Jun 28, 2026
Merged

fix(mobile): pin play-services-ads to 25.0.0 so the release build compiles#344
thomasluizon merged 1 commit into
mainfrom
fix/android-play-services-ads-kotlin-pin

Conversation

@thomasluizon

Copy link
Copy Markdown
Owner

Problem

The Android Release (AAB) workflow (failed run) died at :react-native-google-mobile-ads:compileReleaseKotlin:

e: ...play-services-ads-25.4.0-api.jar!/META-INF/...kotlin_module
   Module was compiled with an incompatible version of Kotlin.
   The binary version of its metadata is 2.3.0, expected version is 2.1.0.

Root cause

play-services-ads resolved to 25.4.0 (released 2026-06-17), whose jars carry Kotlin 2.3.0 metadata. Expo SDK 55 / RN 0.83 compiles with Kotlin 2.1.0, which can't read 2.3.0 metadata.

react-native-google-mobile-ads@16.3.3 only asks for play-services-ads:25.0.0 (sdkVersions.android.googleMobileAds). The 25.4.0 was a transitive upgrade Gradle picked on a fresh install — which is also why the local APK still built (its Gradle cache still had the pre-25.4.0 tree). The AdMob release notes still claim "min Kotlin 2.1.0," but the 25.4.0 artifact's metadata is demonstrably 2.3.0.

Fix

Add a resolutionStrategy rule to the existing with-android-release-build-fixes config plugin that forces com.google.android.gms:play-services-ads* back to 25.0.0 — the Kotlin-2.1-safe version RNGMA targets. play-services-ads-identifier is excluded so it keeps its own (18.x) version line. Because both the local APK and the CI AAB run expo prebuild, both pick up the pin.

Verification (local, no full build needed)

gradlew :react-native-google-mobile-ads:dependencyInsight --configuration releaseCompileClasspath --dependency play-services-ads:

com.google.android.gms:play-services-ads:25.0.0
      - Selected by rule: play-services-ads 25.4.0 ships Kotlin 2.3 metadata...
com.google.android.gms:play-services-ads-api:25.0.0   (forced, was 25.4.0)
com.google.android.gms:play-services-ads-identifier:18.0.0   (untouched)
BUILD SUCCESSFUL

Parity

Android-build tooling only — no web/runtime equivalent, no app behavior change. After merge, re-dispatch the Android Release workflow to produce the signed AAB.

🤖 Generated with Claude Code

…piles

The Android Release (AAB) workflow failed at
:react-native-google-mobile-ads:compileReleaseKotlin because
play-services-ads resolved to 25.4.0, whose jars carry Kotlin 2.3.0 metadata
that the Expo SDK 55 (Kotlin 2.1) toolchain cannot read:

  Module was compiled with an incompatible version of Kotlin.
  The binary version of its metadata is 2.3.0, expected version is 2.1.0.

react-native-google-mobile-ads 16.3.3 only asks for play-services-ads 25.0.0;
25.4.0 was a transitive upgrade Gradle picked on a fresh install (a stale local
Gradle cache is why the local APK still built). Force the play-services-ads SDK
artifacts back to 25.0.0 — the Kotlin-2.1-safe version RNGMA targets — via a
resolutionStrategy rule in the existing release-build-fixes config plugin, so
both the local APK and the CI AAB builds stay on it.

play-services-ads-identifier is excluded so it keeps its own (18.x) line.

Verified via `gradlew :react-native-google-mobile-ads:dependencyInsight
--configuration releaseCompileClasspath --dependency play-services-ads`:
play-services-ads and play-services-ads-api both resolve to 25.0.0 by rule,
play-services-ads-identifier stays 18.0.0, BUILD SUCCESSFUL.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
orbit-ui-mobile-web Ignored Ignored Jun 28, 2026 2:02am

Request Review

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review: PR #344

Scope: PR #344fix(mobile): pin play-services-ads to 25.0.0 so the release build compiles
Recommendation: APPROVE

Summary

PR #344 adds a Gradle resolutionStrategy rule to the existing with-android-release-build-fixes config plugin, pinning com.google.android.gms:play-services-ads* to 25.0.0. The fix correctly targets the root cause (Gradle's transitive resolution silently upgrading to 25.4.0, which ships Kotlin 2.3.0 metadata incompatible with Expo SDK 55 / Kotlin 2.1.0). The implementation is idiomatic, idempotent, and follows the established pattern in the file. No Critical or High findings survive.

Findings

Critical

None

High

None

Medium

None

Low / Info

None

Subagents

Agent Verdict
parity-checker PAIRED — Android-only build tooling; no web equivalent exists or is expected
i18n-syncer N/A — no user-facing strings changed
contract-aligner N/A — no packages/shared types or orbit-api changes
security-reviewer N/A — no orbit-api code changed

Validation

Check Result
Lint N/A — permission not available in this environment
Type check N/A — permission not available in this environment
Tests N/A — permission not available in this environment
Build (api) N/A — orbit-api not touched

Deferred — N/A dimensions & files not verdicted

  • #8 DESIGN.md/AI-slop — gated to apps/* UI files; this is a build plugin, not a UI file.
  • #10 i18n — no user-facing strings added or removed.
  • #11 Contract drift + backward-compat — no packages/shared Zod schemas or orbit-api DTOs changed.
  • #12 Security (API side) — orbit-api not touched; frontend security categories reviewed inline (no injection risk, dependency pin is a security improvement).
  • #13 Backend hard rules — gated to orbit-api; not touched.
  • Validation — lint, typecheck, and test runs require shell permissions not available in this environment.

What's good

  • The idempotency guard (contents.includes(ADS_VERSION_PIN_MARKER)) prevents double-injection across expo prebuild runs — matches the existing pattern for ROOT_STAGING_MARKER.
  • The play-services-ads-identifier exclusion is correct: that artifact follows the independent 18.x version line and must not be forced to 25.0.0.
  • The Groovy .because clause in the resolution strategy is excellent: it explains exactly why the pin exists (Kotlin 2.3 metadata) so future maintainers know when it is safe to remove it.
  • The fix is scoped entirely to the Android build tooling layer — zero runtime behavior change, no web parity required.
  • The PR body includes a working dependencyInsight command to verify the pin, making the fix independently reproducible without a full AAB build.

Recommendation

Approve and merge. Re-dispatch the Android Release (AAB) workflow after merge to produce the signed AAB.

🤖 Generated with Claude Code

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

PR Review — #344

Recommendation: APPROVE

Severity Count
Critical (incl. old-client breaks) 0
High 0
Medium 0
Low / Info 0

Scope: Single file change — apps/mobile/plugins/with-android-release-build-fixes.js (+32/-0)

The new withProjectBuildGradle block pins play-services-ads to 25.0.0 in the Android release build. Implementation is idiomatic Expo config plugin, idempotent (marker-guarded so it won't double-insert), and correctly excludes play-services-ads-identifier from the pin. Android-only build tooling — no web parity required. All other rubric dimensions are N/A for this change.

Clean diff, no issues found.

@thomasluizon
thomasluizon merged commit e3562e9 into main Jun 28, 2026
9 checks passed
@thomasluizon
thomasluizon deleted the fix/android-play-services-ads-kotlin-pin branch June 28, 2026 02:05
@sonarqubecloud

Copy link
Copy Markdown

thomasluizon added a commit that referenced this pull request Jun 28, 2026
…1) (#345)

#344 pinned play-services-ads to 25.0.0, which compiles under Kotlin 2.1 but
predates the AgeRestrictedTreatment API that react-native-google-mobile-ads
16.3.3 references, so :react-native-google-mobile-ads:compileReleaseKotlin
then failed with "Unresolved reference 'AgeRestrictedTreatment'".

The catch: that API and the Kotlin 2.3 metadata bump both landed in 25.3.0, so
no single ads release has the API under Kotlin 2.1 — except 25.2.0, the release
right before the bump. It carries the API and is still Kotlin 2.1.

Verified by compiling the exact failing task locally against each candidate:
- 25.0.0 -> Unresolved reference 'AgeRestrictedTreatment'
- 25.3.0 -> Kotlin metadata 2.3.0 vs expected 2.1.0
- 25.2.0 -> BUILD SUCCESSFUL

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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