From f10204e609b2db5dfec17983dcf4254fdd478f11 Mon Sep 17 00:00:00 2001 From: Marcel Schnelle Date: Sun, 1 Jun 2025 16:23:33 +0900 Subject: [PATCH 1/3] Update to JUnit 5.13.0 --- build-logic/src/main/kotlin/Dependencies.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build-logic/src/main/kotlin/Dependencies.kt b/build-logic/src/main/kotlin/Dependencies.kt index 14bbcdfb..38fdb265 100644 --- a/build-logic/src/main/kotlin/Dependencies.kt +++ b/build-logic/src/main/kotlin/Dependencies.kt @@ -3,9 +3,9 @@ object libs { object versions { const val kotlin = "2.1.21" - const val junitJupiter = "5.13.0-RC1" - const val junitVintage = "5.13.0-RC1" - const val junitPlatform = "1.13.0-RC1" + const val junitJupiter = "5.13.0" + const val junitVintage = "5.13.0" + const val junitPlatform = "1.13.0" const val composeBom = "2025.03.00" const val androidXMultidex = "2.0.1" From 10f2c12ce35876d4b4241683c7c89e49928d0fd2 Mon Sep 17 00:00:00 2001 From: Marcel Schnelle Date: Sun, 1 Jun 2025 17:27:50 +0900 Subject: [PATCH 2/3] Use first-party types for Gradle & AGP version Remove the need for a third-party semver parsing library --- build-logic/src/main/kotlin/Dependencies.kt | 2 - plugin/android-junit5/build.gradle.kts | 1 - .../junit5/AndroidJUnitPlatformPlugin.kt | 28 +++--- .../junit5/internal/config/Constants.kt | 8 +- .../junit5/internal/config/PluginConfig.kt | 2 + .../junit5/internal/utils/Functions.kt | 12 ++- .../plugins/junit5/VersionCheckerTests.kt | 85 +++++++++++++------ 7 files changed, 87 insertions(+), 51 deletions(-) diff --git a/build-logic/src/main/kotlin/Dependencies.kt b/build-logic/src/main/kotlin/Dependencies.kt index 38fdb265..3582c084 100644 --- a/build-logic/src/main/kotlin/Dependencies.kt +++ b/build-logic/src/main/kotlin/Dependencies.kt @@ -19,7 +19,6 @@ object libs { const val coroutines = "1.10.2" const val dokka = "2.0.0" const val espresso = "3.6.1" - const val javaSemver = "0.10.2" const val junit4 = "4.13.2" const val konfToml = "1.1.2" const val kotlinxBinaryCompatibilityValidator = "0.17.0" @@ -51,7 +50,6 @@ object libs { const val kotlinStdLib = "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${versions.kotlin}" const val kotlinCoroutinesCore = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${versions.coroutines}" - const val javaSemver = "com.github.zafarkhaja:java-semver:${versions.javaSemver}" const val junitJupiterApi = "org.junit.jupiter:junit-jupiter-api:${versions.junitJupiter}" const val junitJupiterParams = "org.junit.jupiter:junit-jupiter-params:${versions.junitJupiter}" diff --git a/plugin/android-junit5/build.gradle.kts b/plugin/android-junit5/build.gradle.kts index 46fc94e4..6d2e0ddb 100644 --- a/plugin/android-junit5/build.gradle.kts +++ b/plugin/android-junit5/build.gradle.kts @@ -99,7 +99,6 @@ dependencies { implementation(gradleApi()) implementation(libs.kotlinStdLib) - implementation(libs.javaSemver) implementation(libs.junitPlatformCommons) testImplementation(gradleTestKit()) diff --git a/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/AndroidJUnitPlatformPlugin.kt b/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/AndroidJUnitPlatformPlugin.kt index 4963e260..8a5d97a1 100644 --- a/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/AndroidJUnitPlatformPlugin.kt +++ b/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/AndroidJUnitPlatformPlugin.kt @@ -1,6 +1,5 @@ package de.mannodermaus.gradle.plugins.junit5 -import com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION import de.mannodermaus.gradle.plugins.junit5.dsl.AndroidJUnitPlatformExtension.Companion.createJUnit5Extension import de.mannodermaus.gradle.plugins.junit5.internal.config.MIN_REQUIRED_AGP_VERSION import de.mannodermaus.gradle.plugins.junit5.internal.config.MIN_REQUIRED_GRADLE_VERSION @@ -8,9 +7,10 @@ import de.mannodermaus.gradle.plugins.junit5.internal.config.PluginConfig import de.mannodermaus.gradle.plugins.junit5.internal.configureJUnit5 import de.mannodermaus.gradle.plugins.junit5.internal.extensions.whenAndroidPluginAdded import de.mannodermaus.gradle.plugins.junit5.internal.utils.requireGradle -import de.mannodermaus.gradle.plugins.junit5.internal.utils.requireVersion +import de.mannodermaus.gradle.plugins.junit5.internal.utils.requireAgp import org.gradle.api.Plugin import org.gradle.api.Project +import org.gradle.util.GradleVersion /** * Android JUnit Platform plugin for Gradle. @@ -19,21 +19,23 @@ import org.gradle.api.Project public class AndroidJUnitPlatformPlugin : Plugin { override fun apply(project: Project) { - requireGradle(MIN_REQUIRED_GRADLE_VERSION) { - "android-junit5 plugin requires Gradle $MIN_REQUIRED_GRADLE_VERSION or later" - } - - requireVersion( - actual = ANDROID_GRADLE_PLUGIN_VERSION, - required = MIN_REQUIRED_AGP_VERSION + requireGradle( + actual = GradleVersion.current(), + required = MIN_REQUIRED_GRADLE_VERSION ) { - "android-junit5 plugin requires Android Gradle Plugin $MIN_REQUIRED_AGP_VERSION or later" + "android-junit5 plugin requires Gradle $MIN_REQUIRED_GRADLE_VERSION or later" } project.whenAndroidPluginAdded { plugin -> - val extension = project.createJUnit5Extension() - val config = PluginConfig.find(project, plugin) - if (config != null) { + PluginConfig.find(project, plugin)?.let { config -> + requireAgp( + actual = config.currentAgpVersion, + required = MIN_REQUIRED_AGP_VERSION + ) { + "android-junit5 plugin requires Android Gradle Plugin $MIN_REQUIRED_AGP_VERSION or later" + } + + val extension = project.createJUnit5Extension() configureJUnit5(project, config, extension) } } diff --git a/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/config/Constants.kt b/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/config/Constants.kt index 7ebcb064..a12d3801 100644 --- a/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/config/Constants.kt +++ b/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/config/Constants.kt @@ -2,8 +2,12 @@ package de.mannodermaus.gradle.plugins.junit5.internal.config -internal const val MIN_REQUIRED_GRADLE_VERSION = "8.2" // When updating this, check buildSrc/Tasks.kt and update it there, too -internal const val MIN_REQUIRED_AGP_VERSION = "8.2.0" +import com.android.build.api.AndroidPluginVersion +import org.gradle.util.GradleVersion + +// When updating this, check buildSrc/Tasks.kt and update it there, too +internal val MIN_REQUIRED_GRADLE_VERSION = GradleVersion.version("8.2") +internal val MIN_REQUIRED_AGP_VERSION = AndroidPluginVersion(8, 2) internal const val EXTENSION_NAME = "junitPlatform" diff --git a/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/config/PluginConfig.kt b/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/config/PluginConfig.kt index 8c80e790..759e9d7f 100644 --- a/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/config/PluginConfig.kt +++ b/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/config/PluginConfig.kt @@ -50,6 +50,8 @@ private constructor( val hasJacocoPlugin get() = project.plugins.hasPlugin("jacoco") private val hasKotlinPlugin get() = project.plugins.findPlugin("kotlin-android") != null + val currentAgpVersion get() = componentsExtension.pluginVersion + fun finalizeDsl(block: (CommonExtension<*, *, *, *, *>) -> Unit) { componentsExtension.finalizeDsl(block) } diff --git a/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/utils/Functions.kt b/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/utils/Functions.kt index 9ec901bf..9380beb9 100644 --- a/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/utils/Functions.kt +++ b/plugin/android-junit5/src/main/kotlin/de/mannodermaus/gradle/plugins/junit5/internal/utils/Functions.kt @@ -1,6 +1,6 @@ package de.mannodermaus.gradle.plugins.junit5.internal.utils -import com.github.zafarkhaja.semver.Version +import com.android.build.api.AndroidPluginVersion import org.gradle.api.GradleException import org.gradle.util.GradleVersion @@ -9,16 +9,14 @@ internal fun excludedPackagingOptions() = listOf( "/META-INF/LICENSE-notice.md" ) -internal fun requireGradle(version: String, message: () -> String) { - require(GradleVersion.current() >= GradleVersion.version(version)) { +internal fun requireGradle(actual: GradleVersion, required: GradleVersion, message: () -> String) { + require(actual >= required) { throw GradleException(message()) } } -internal fun requireVersion(actual: String, required: String, message: () -> String) { - val actualVersion = Version.parse(actual) - val requiredVersion = Version.parse(required) - require(actualVersion.isHigherThanOrEquivalentTo(requiredVersion)) { +internal fun requireAgp(actual: AndroidPluginVersion, required: AndroidPluginVersion, message: () -> String) { + require(actual >= required) { throw GradleException(message()) } } diff --git a/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/VersionCheckerTests.kt b/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/VersionCheckerTests.kt index febad8e7..f5f80e92 100644 --- a/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/VersionCheckerTests.kt +++ b/plugin/android-junit5/src/test/kotlin/de/mannodermaus/gradle/plugins/junit5/VersionCheckerTests.kt @@ -1,8 +1,9 @@ package de.mannodermaus.gradle.plugins.junit5 +import com.android.build.api.AndroidPluginVersion import com.google.common.truth.Truth.assertThat import de.mannodermaus.gradle.plugins.junit5.internal.config.MIN_REQUIRED_AGP_VERSION -import de.mannodermaus.gradle.plugins.junit5.internal.utils.requireVersion +import de.mannodermaus.gradle.plugins.junit5.internal.utils.requireAgp import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.CsvSource @@ -14,39 +15,71 @@ import org.junit.jupiter.params.provider.CsvSource class VersionCheckerTests { @CsvSource( - "7.0.0-alpha01, false", - "7.0.0-alpha01, false", - "7.0.0-beta01, false", - "7.0.0-rc01, false", - "7.0.0, false", - "8.0.0-beta01, false", - "8.0.0, false", - "8.0.1, false", - "8.0.1-alpha01, false", - "8.1.0, false", - "8.1.0-beta01, false", - "8.2.0, true", - "8.3.0-rc01, true", - "8.4.0-alpha05, true", - "8.10.1-alpha01, true", - "8.10.0, true", - "8.11.0-beta01, true", - "8.11.0, true", + "7.0.0-alpha1, false", + "7.0.0-alpha1, false", + "7.0.0-beta1, false", + "7.0.0-rc1, false", + "7.0.0, false", + "8.0.0-beta1, false", + "8.0.0, false", + "8.0.1, false", + "8.0.1-alpha1, false", + "8.1.0, false", + "8.1.0-beta1, false", + "8.2.0, true", + "8.3.0-rc1, true", + "8.4.0-alpha5, true", + "8.10.1-alpha11, true", + "8.10.0, true", + "8.11.0-beta1, true", + "8.11.0, true", ) @ParameterizedTest fun `check AGP compatibility`(version: String, compatible: Boolean) { - assertThat(versionCompatible(version)).isEqualTo(compatible) + val pluginVersion = version.toAndroidPluginVersion() + assertThat(versionCompatible(pluginVersion)).isEqualTo(compatible) } - private fun versionCompatible(version: String): Boolean { + private fun versionCompatible(version: AndroidPluginVersion): Boolean { return try { - requireVersion( - actual = version, - required = MIN_REQUIRED_AGP_VERSION, - message = { "" }) + requireAgp( + actual = version, + required = MIN_REQUIRED_AGP_VERSION, + message = { "" } + ) true - } catch (error: Throwable) { + } catch (_: Throwable) { false } } + + private fun String.toAndroidPluginVersion(): AndroidPluginVersion { + // Split into stable and optional preview parts + val firstSplit = split('-') + + // Split first part further into major, minor, patch + val stableComponents = firstSplit[0].split('.') + + var version = AndroidPluginVersion( + major = stableComponents[0].toInt(), + minor = stableComponents[1].toInt(), + micro = stableComponents.getOrNull(2)?.toInt() ?: 0 + ) + + // Attach preview part + val preview = firstSplit.getOrNull(1) + + version = when { + preview == null -> version + preview.startsWith("alpha") -> version.alpha(preview.substringAfter("alpha").toInt()) + preview.startsWith("beta") -> version.beta(preview.substringAfter("beta").toInt()) + preview.startsWith("rc") -> version.rc(preview.substringAfter("rc").toInt()) + else -> version + } + + // Validate correctness + assertThat(version.toString()).endsWith(this) + + return version + } } From aa4e81d21b78aacdeda4ea88259ec3d4005048a2 Mon Sep 17 00:00:00 2001 From: Marcel Schnelle Date: Sun, 1 Jun 2025 17:28:03 +0900 Subject: [PATCH 3/3] AGP 8.10.1, 8.12 Alpha 3 --- build-logic/src/main/kotlin/Environment.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build-logic/src/main/kotlin/Environment.kt b/build-logic/src/main/kotlin/Environment.kt index e3c08e5e..8558c97a 100644 --- a/build-logic/src/main/kotlin/Environment.kt +++ b/build-logic/src/main/kotlin/Environment.kt @@ -17,9 +17,9 @@ enum class SupportedAgp( AGP_8_7("8.7.3", gradle = "8.9"), AGP_8_8("8.8.2", gradle = "8.10.2"), AGP_8_9("8.9.3", gradle = "8.11.1"), - AGP_8_10("8.10.0", gradle = "8.11.1"), + AGP_8_10("8.10.1", gradle = "8.11.1"), AGP_8_11("8.11.0-alpha10", gradle = "8.13"), - AGP_8_12("8.12.0-alpha01", gradle = "8.13") + AGP_8_12("8.12.0-alpha03", gradle = "8.13") ; companion object {