build: update to AGP 9.1.0
authorDa Risk <da_risk@geekorum.com>
Mon, 09 Mar 2026 16:20:21 -0400
changeset 100 9ec927c219b0
parent 99 641b0bfe5292
child 101 75cae5a2f7d9
build: update to AGP 9.1.0
buildSrc/src/main/kotlin/AndroidPlayStorePublisher.kt
buildSrc/src/main/kotlin/AndroidSigning.kt
buildSrc/src/main/kotlin/AndroidTests.kt
buildSrc/src/main/kotlin/RepositoryChangeset.kt
geekdroid-firebase/build.gradle.kts
geekdroid/build.gradle.kts
gradle/libs.versions.toml
gradle/wrapper/gradle-wrapper.properties
--- a/buildSrc/src/main/kotlin/AndroidPlayStorePublisher.kt	Mon Mar 09 14:41:46 2026 -0400
+++ b/buildSrc/src/main/kotlin/AndroidPlayStorePublisher.kt	Mon Mar 09 16:20:21 2026 -0400
@@ -21,7 +21,7 @@
  */
 package com.geekorum.build
 
-import com.android.build.gradle.AppExtension
+import com.android.build.api.dsl.ApplicationExtension
 import com.github.triplet.gradle.play.PlayPublisherExtension
 import org.gradle.api.NamedDomainObjectContainer
 import org.gradle.api.Project
@@ -47,7 +47,7 @@
         serviceAccountCredentials.set(file(properties["PLAY_STORE_JSON_KEY_FILE"]!!))
     }
 
-    val android = the<AppExtension>() as ExtensionAware
+    val android = the<ApplicationExtension>() as ExtensionAware
 
     tasks.apply {
         register("publishToGooglePlayStore") {
--- a/buildSrc/src/main/kotlin/AndroidSigning.kt	Mon Mar 09 14:41:46 2026 -0400
+++ b/buildSrc/src/main/kotlin/AndroidSigning.kt	Mon Mar 09 16:20:21 2026 -0400
@@ -21,22 +21,17 @@
  */
 package com.geekorum.build
 
-import com.android.build.api.dsl.*
+import com.android.build.api.dsl.ApplicationExtension
 import org.gradle.api.Project
 
-private typealias AppExtensionWithSigning = CommonExtension<*, ApplicationBuildType, *, *, *, *>
-private typealias LibExtensionWithSigning = CommonExtension<*, LibraryBuildType, *, *, *, *>
-private typealias TestExtensionWithSigning = CommonExtension<*, TestBuildType, *, *, *, *>
 
-// TODO  This implicitly supports only the AppPlugin
-//  should we support other android plugins: LibraryPlugin TestPlugin ?
 internal fun Project.configureReleaseSigningConfig() {
     val releaseStoreFile = findProperty("RELEASE_STORE_FILE") as? String ?: ""
     val releaseStorePassword = findProperty("RELEASE_STORE_PASSWORD") as? String ?: ""
     val releaseKeyAlias= findProperty("RELEASE_KEY_ALIAS") as? String ?: ""
     val releaseKeyPassword= findProperty("RELEASE_KEY_PASSWORD") as? String ?: ""
 
-    extensions.configure<AppExtensionWithSigning>("android") {
+    extensions.configure<ApplicationExtension>("android") {
         signingConfigs {
             register("release") {
                 storeFile =  file(releaseStoreFile)
--- a/buildSrc/src/main/kotlin/AndroidTests.kt	Mon Mar 09 14:41:46 2026 -0400
+++ b/buildSrc/src/main/kotlin/AndroidTests.kt	Mon Mar 09 16:20:21 2026 -0400
@@ -21,10 +21,9 @@
  */
 package com.geekorum.build
 
+import com.android.build.api.dsl.ApplicationExtension
 import com.android.build.api.dsl.CommonExtension
-import com.android.build.api.dsl.DefaultConfig
-import com.android.build.gradle.BaseExtension
-import com.android.build.gradle.internal.dsl.TestOptions
+import com.android.build.api.dsl.LibraryExtension
 import org.gradle.api.Project
 import org.gradle.api.artifacts.Dependency
 import org.gradle.api.artifacts.DependencyConstraint
@@ -33,28 +32,37 @@
 import org.gradle.api.artifacts.dsl.DependencyHandler
 import org.gradle.kotlin.dsl.*
 
-const val espressoVersion = "3.5.1"
-const val androidxTestRunnerVersion = "1.5.2"
-const val androidxTestCoreVersion = "1.5.0"
-const val robolectricVersion = "4.10.2"
+const val espressoVersion = "3.6.1"
+const val androidxTestRunnerVersion = "1.6.2"
+const val androidxTestCoreVersion = "1.6.1"
+const val robolectricVersion = "4.14.1"
 
-private typealias BaseExtension = CommonExtension<*, *, DefaultConfig, *, *, *>
 
 /*
  * Configuration for espresso and robolectric usage in an Android project
  */
-@Suppress("UnstableApiUsage")
 internal fun Project.configureTests() {
-    extensions.configure<BaseExtension>("android") {
-        defaultConfig {
+    extensions.configure<CommonExtension>("android") {
+        if (this is ApplicationExtension) {
+            defaultConfig {
             testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
-            testInstrumentationRunnerArguments += mapOf(
-                "clearPackageData" to "true",
-                "disableAnalytics" to "true"
-            )
+                testInstrumentationRunnerArguments += mapOf(
+                    "clearPackageData" to "true",
+                    "disableAnalytics" to "true"
+                )
+            }
+        }
+        if (this is LibraryExtension) {
+            defaultConfig {
+            testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+                testInstrumentationRunnerArguments += mapOf(
+                    "clearPackageData" to "true",
+                    "disableAnalytics" to "true"
+                )
+            }
         }
 
-        testOptions {
+        testOptions.apply {
             execution = "ANDROIDX_TEST_ORCHESTRATOR"
             animationsDisabled = true
 
@@ -64,20 +72,20 @@
         }
     }
 
-
     dependencies {
         dualTestImplementation(kotlin("test-junit"))
 
-        androidTestUtil("androidx.test:orchestrator:1.4.2")
+        androidTestUtil("androidx.test:orchestrator:1.5.1")
         androidTestImplementation("androidx.test:runner:$androidxTestRunnerVersion")
-        dualTestImplementation("androidx.test.ext:junit-ktx:1.1.1")
+        dualTestImplementation("androidx.test.ext:junit-ktx:1.2.1")
 
         dualTestImplementation("androidx.test:core-ktx:$androidxTestCoreVersion")
-        dualTestImplementation("androidx.test:rules:1.5.0")
+        dualTestImplementation("androidx.test:rules:1.6.1")
+
         // fragment testing is usually declared on debugImplementation configuration and need these dependencies
         constraints {
             debugImplementation("androidx.test:core:$androidxTestCoreVersion")
-            debugImplementation("androidx.test:monitor:$androidxTestRunnerVersion")
+            debugImplementation("androidx.test:monitor:1.7.2")
         }
 
         dualTestImplementation("androidx.test.espresso:espresso-core:$espressoVersion")
@@ -87,12 +95,12 @@
         dualTestImplementation("androidx.test.espresso:espresso-intents:$espressoVersion")
 
         // assertions
-        dualTestImplementation("com.google.truth:truth:1.0")
-        dualTestImplementation("androidx.test.ext:truth:1.3.0-alpha01")
+        dualTestImplementation("com.google.truth:truth:1.4.4")
+        dualTestImplementation("androidx.test.ext:truth:1.6.0")
 
         // mock
-        testImplementation("io.mockk:mockk:1.13.5")
-        androidTestImplementation("io.mockk:mockk-android:1.13.5")
+        testImplementation("io.mockk:mockk:1.13.8")
+        androidTestImplementation("io.mockk:mockk-android:1.13.8")
         testImplementation("org.robolectric:robolectric:$robolectricVersion")
 
         constraints {
--- a/buildSrc/src/main/kotlin/RepositoryChangeset.kt	Mon Mar 09 14:41:46 2026 -0400
+++ b/buildSrc/src/main/kotlin/RepositoryChangeset.kt	Mon Mar 09 16:20:21 2026 -0400
@@ -42,7 +42,12 @@
 
 internal fun ExecOperations.getHgSha1(projectDir: File): String? = runCommand("hg id --debug -i -r .", workingDir = projectDir)?.trim()
 
-internal fun ExecOperations.getHgLocalRevisionNumber(projectDir: File): String? = runCommand("hg id -n -r .", workingDir = projectDir)?.trim()
+internal fun ExecOperations.getHgLocalRevisionNumber(projectDir: File): String? {
+    val hg = File(projectDir, ".hg")
+    return if (hg.exists()) {
+        runCommand("hg id -n -r .", workingDir = projectDir)?.trim()
+    } else null
+}
 
 private fun ExecOperations.getChangeSet(projectDir: File): String {
     val git = File(projectDir, ".git")
@@ -132,7 +137,7 @@
         val mainOutput = it.outputs.single { it.outputType == OutputType.SINGLE }
 
         // create version Code generating task
-        val versionCodeTask = project.tasks.register<VersionCodeTask>("computeVersionCodeFor${it.name.replaceFirstChar { it.titlecase() }}") {
+        val versionCodeTask = project.tasks.register<VersionCodeTask>("computeVersionCodeFor${it.name.capitalized()}") {
             this.major.set(major)
             this.minor.set(minor)
             this.patch.set(patch)
@@ -154,3 +159,5 @@
         })
     }
 }
+
+private fun String.capitalized() = replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }
--- a/geekdroid-firebase/build.gradle.kts	Mon Mar 09 14:41:46 2026 -0400
+++ b/geekdroid-firebase/build.gradle.kts	Mon Mar 09 16:20:21 2026 -0400
@@ -1,6 +1,5 @@
 plugins {
     id("com.android.library")
-    kotlin("android")
     id("com.geekorum.build.android-tests")
     id("com.geekorum.build.android-avdl")
     `maven-publish`
@@ -18,7 +17,7 @@
     buildTypes {
         getByName("release") {
             isMinifyEnabled = false
-            proguardFiles(getDefaultProguardFile("proguard-android.txt"),
+            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"),
                 "proguard-rules.pro")
         }
     }
--- a/geekdroid/build.gradle.kts	Mon Mar 09 14:41:46 2026 -0400
+++ b/geekdroid/build.gradle.kts	Mon Mar 09 16:20:21 2026 -0400
@@ -21,12 +21,11 @@
  */
 plugins {
     id("com.android.library")
-    kotlin("android")
-    kotlin("kapt")
     id("com.geekorum.build.android-tests")
     id("com.geekorum.build.android-avdl")
     `maven-publish`
     alias(libs.plugins.compose.compiler)
+    alias(libs.plugins.kotlin.ksp)
 }
 
 
@@ -42,7 +41,7 @@
     buildTypes {
         getByName("release") {
             isMinifyEnabled = false
-            proguardFiles(getDefaultProguardFile("proguard-android.txt"),
+            proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"),
                     "proguard-rules.pro")
         }
     }
@@ -88,7 +87,7 @@
     api(libs.okhttp)
 
     implementation(libs.dagger.compiler)
-    kapt(libs.dagger.compiler)
+    ksp(libs.dagger.compiler)
 
     implementation(platform(libs.kotlinx.coroutines.bom))
     implementation(libs.kotlinx.coroutines.core)
--- a/gradle/libs.versions.toml	Mon Mar 09 14:41:46 2026 -0400
+++ b/gradle/libs.versions.toml	Mon Mar 09 16:20:21 2026 -0400
@@ -1,5 +1,5 @@
 [versions]
-android-gradle-plugin = "8.13.0"
+android-gradle-plugin = "9.1.0"
 annotation = "1.9.1"
 androidx-activity = "1.12.4"
 androidx-compose-bom = "2026.02.01"
@@ -12,6 +12,7 @@
 firebase-bom = "34.10.0"
 fragment = "1.8.9"
 kotlin = "2.2.20"
+kotlin-ksp = "2.3.5"
 kotlinx-coroutines-bom = "1.10.2"
 lifecycle = "2.10.0"
 material = "1.13.0"
@@ -29,6 +30,7 @@
 android-application = { id = "com.android.application", version.ref = "android-gradle-plugin" }
 kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
 compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
+kotlin-ksp = { id = "com.google.devtools.ksp", version.ref = "kotlin-ksp" }
 
 
 [libraries]
--- a/gradle/wrapper/gradle-wrapper.properties	Mon Mar 09 14:41:46 2026 -0400
+++ b/gradle/wrapper/gradle-wrapper.properties	Mon Mar 09 16:20:21 2026 -0400
@@ -1,6 +1,6 @@
 #Sat May 06 19:25:31 AST 2023
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.0-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists