Skip to content

Commit

Permalink
Add demo project
Browse files Browse the repository at this point in the history
Simple project demonstrating the VERSIONS plugin issue.
It assumes running Gradle 8.10.1 and Java 17.

To see problem run:

    ./gradlew dependencyUpdates

The project is prepared in support of reported issue:
ben-manes/gradle-versions-plugin#906
  • Loading branch information
rynkowsg committed Sep 17, 2024
0 parents commit c6478a0
Show file tree
Hide file tree
Showing 19 changed files with 669 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.gradle
build/
4 changes: 4 additions & 0 deletions .plugin-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# plugin-name git-url git-ref (hash, tag, or branch)
asdf-plugin-manager https://github.com/asdf-community/asdf-plugin-manager ecd1642
gradle https://github.com/rfrancis/asdf-gradle.git dd1ecce
java https://github.com/halcyon/asdf-java.git 194f03b
8 changes: 8 additions & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# https://github.com/asdf-community/asdf-plugin-manager/releases
asdf-plugin-manager 1.3.1

# https://gradle.org/releases/
gradle 8.10.1

# https://adoptium.net/temurin/archive/?version=17
java temurin-17.0.12+7
52 changes: 52 additions & 0 deletions build-logic/convention/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import org.gradle.api.JavaVersion
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
// plugins for Gradle 8.10.1
id("org.gradle.kotlin.kotlin-dsl") version "4.5.0"
id("org.jetbrains.kotlin.jvm") version "1.9.24"
}

group = "my.buildlogic"

// Configure the build-logic plugins to target JDK 17
// This matches the JDK used to build the project, and is not related to what is running on device.
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

kotlin {
compilerOptions {
jvmTarget = JvmTarget.JVM_17
}
}

dependencies {
compileOnly("com.android.tools.build:gradle:8.6.0")
compileOnly("com.github.ben-manes:gradle-versions-plugin:0.51.0")
compileOnly("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.24") // version for Gradle 8.10.1
}

tasks {
validatePlugins {
enableStricterValidation = true
failOnWarning = true
}
}

@Suppress(
"ktlint:standard:argument-list-wrapping",
"ktlint:standard:binary-expression-wrapping",
"ktlint:standard:function-literal",
"ktlint:standard:max-line-length",
"ktlint:standard:wrapping",
)

gradlePlugin {
plugins {
register("android-library") { id = "demo.android-library"; implementationClass = "AndroidLibraryConventionPlugin" }
register("jvm-library") { id = "demo.jvm-library"; implementationClass = "JvmLibraryConventionPlugin" }
register("versions") { id = "demo.versions"; implementationClass = "VersionsConventionPlugin" }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import com.android.build.api.variant.LibraryAndroidComponentsExtension
import com.android.build.gradle.LibraryExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.logging.LogLevel
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
import org.gradle.api.JavaVersion

class AndroidLibraryConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
println("Applying AndroidLibraryConventionPlugin to $name")
pluginManager.apply("com.android.library")

extensions.configure<LibraryExtension> {
buildToolsVersion = "34.0.0"
compileSdk = 34
defaultConfig {
minSdk = 21
vectorDrawables.useSupportLibrary = true
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
testOptions.animationsDisabled = true
testOptions.targetSdk = 34
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.kotlin.dsl.configure

class JvmLibraryConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
println("Applying JvmLibraryConventionPlugin to $name")
pluginManager.apply("org.jetbrains.kotlin.jvm")
}
}
}
119 changes: 119 additions & 0 deletions build-logic/convention/src/main/kotlin/VersionsConventionPlugin.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import GuavaCheckResult.GUAVA_CANDIDATE_NEWER
import GuavaCheckResult.GUAVA_CANDIDATE_OLDER
import GuavaCheckResult.GUAVA_DIFFERENT_FLAVORS
import GuavaCheckResult.GUAVA_SAME_VERSIONS
import GuavaCheckResult.NOT_GUAVA
import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask
import com.github.benmanes.gradle.versions.updates.resolutionstrategy.ComponentSelectionWithCurrent
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.withType

val isDEBUG: Boolean = System.getenv("DEBUG").let { it in listOf("true", "1") }.also { println("DEBUG=$it") }

fun log(message: String) {
if (isDEBUG) {
println(message)
}
}

private data class VersionComparisonData(
val group: String?,
val module: String?,
val oldVersion: String,
val newVersion: String,
)

class VersionsConventionPlugin : Plugin<Project> {
override fun apply(project: Project) = with(project) {
println("Applying VersionsConventionPlugin to $name")
pluginManager.apply("com.github.ben-manes.versions")

tasks.withType<DependencyUpdatesTask>().configureEach {
checkForGradleUpdate = true
outputFormatter = "plain,html"
outputDir = "build/dependencyUpdates"
reportfileName = "report"
val filter: ComponentSelectionWithCurrent.() -> Boolean = {
val candidate = this
// log("this: $this")
// log("candidate?.module: ${candidate.candidate?.module}")
// log("candidate?.group: ${candidate.candidate?.group}")
// log("candidate?.version: ${candidate.candidate?.version}")
// log("candidate?.displayName: ${candidate.candidate?.displayName}")
// log("candidate?.moduleIdentifier: ${candidate.candidate?.moduleIdentifier}")
val comparisonData = VersionComparisonData(
group = candidate.candidate.group,
module = candidate.candidate.module,
oldVersion = candidate.currentVersion,
newVersion = candidate.candidate.version,
)
log("comparisonData: $comparisonData")
val shouldReject = !shouldApprove(comparisonData)
log("shouldReject: $shouldReject")
log("------------------------------------------------------------")
shouldReject
}
rejectVersionIf(filter)
}
}
}

private fun shouldApprove(data: VersionComparisonData): Boolean {
val foundResult = checkIfGuavaLibrary(data)
log("foundResult: $foundResult")
when (foundResult) {
GUAVA_SAME_VERSIONS -> return true // we don't want to update to the same version
// different flavours should not be compared
// e.g. 32.1.3-android, 32.1.3-jre - there is no new version in such case
GUAVA_DIFFERENT_FLAVORS -> return false
GUAVA_CANDIDATE_NEWER -> return true // approve newer version
GUAVA_CANDIDATE_OLDER -> return false // reject older version
NOT_GUAVA -> {} // do nothing
}
// approve new version if:
// - the new is stable, or
// - the current is unstable (if current is unstable, new can be either stable or unstable)
val shouldApprove = isStable(data.newVersion) || !isStable(data.oldVersion)
return shouldApprove
}

// Compares whether two versions are same just different by flavour.
// It is to deal with situation when plugin suggest to upgrade -android
// Guava version to -jre version, e.g. from `guava-25.1-android` to `guava-25.1-jre`.
private fun checkIfGuavaLibrary(data: VersionComparisonData): GuavaCheckResult {
if (data.group != "com.google.guava") {
return NOT_GUAVA
}
val (oldVer, oldFlavor) = parseGuavaVersion(data.oldVersion) ?: Pair(null, null)
val (newVer, newFlavor) = parseGuavaVersion(data.newVersion) ?: Pair(null, null)
if (oldVer == null || newVer == null || oldFlavor == null || newFlavor == null) {
return NOT_GUAVA // problems when parsing - treat as not Guava
}
if (oldFlavor != newFlavor) {
return GUAVA_DIFFERENT_FLAVORS // if not the same flavors, they should not be compared
}
val same = oldVer == newVer
if (same) return GUAVA_SAME_VERSIONS
// TODO: improve the comparison
return if (newVer > oldVer) GUAVA_CANDIDATE_NEWER else GUAVA_CANDIDATE_OLDER
}

private enum class GuavaCheckResult {
NOT_GUAVA,
GUAVA_DIFFERENT_FLAVORS,
GUAVA_SAME_VERSIONS,
GUAVA_CANDIDATE_NEWER,
GUAVA_CANDIDATE_OLDER,
}

private fun parseGuavaVersion(version: String): Pair<String?, String?>? {
val pattern = Regex("^(.*?)(-android|-jre)$").find(version)
return pattern?.let { Pair(it.groupValues[1], it.groupValues[2]) }
}

private fun isStable(version: String): Boolean {
val stableKeyword = listOf("RELEASE", "FINAL", "GA").any { it in version.uppercase() }
val regex = Regex("^[0-9,.v-]+(-r)?$")
return stableKeyword || regex.matches(version)
}
4 changes: 4 additions & 0 deletions build-logic/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Gradle properties are not passed to included builds https://github.com/gradle/gradle/issues/2534
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configureondemand=true
10 changes: 10 additions & 0 deletions build-logic/settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
dependencyResolutionManagement {
repositories {
google()
gradlePluginPortal() // for gradle-versions-plugin
mavenCentral()
}
}

rootProject.name = "build-logic"
include(":convention")
16 changes: 16 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
buildscript {
repositories {
google()
gradlePluginPortal()
}
dependencies {
classpath("com.android.tools.build:gradle:8.6.0")
classpath("com.github.ben-manes:gradle-versions-plugin:0.51.0")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.20")
}
}

plugins {
id("demo.versions")
}

Binary file added gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
7 changes: 7 additions & 0 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading

0 comments on commit c6478a0

Please sign in to comment.