Skip to content

Commit

Permalink
Standardise and verify the minimum supported Gradle version (Kotlin#204)
Browse files Browse the repository at this point in the history
- store the minimal supported Gradle version in libs.versions.toml
- Add a new CheckReadmeTask to check that the README is up-to-date
- update code for generating plugin constants into a new file, rather than editing the plugin file in-place
- add integration tests for checking the supported Gradle version, and logged warning
  • Loading branch information
adam-enko authored Apr 29, 2024
1 parent e037425 commit b8e07eb
Show file tree
Hide file tree
Showing 12 changed files with 158 additions and 26 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -432,4 +432,4 @@ These examples showcase various use cases and offer practical insights into the

## Contributing

We welcome contributions to `kotlinx-benchmark`! If you want to contribute, please refer to our [Contribution Guidelines](CONTRIBUTING.md).
We welcome contributions to `kotlinx-benchmark`! If you want to contribute, please refer to our [Contribution Guidelines](CONTRIBUTING.md).
12 changes: 12 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import tasks.CheckReadmeTask

buildscript {
repositories {
maven { url 'https://maven.pkg.jetbrains.space/kotlin/p/kotlinx/maven' }
Expand All @@ -13,6 +15,7 @@ buildscript {
}

plugins {
id("base")
id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.15.0-Beta.1"
}

Expand Down Expand Up @@ -72,3 +75,12 @@ apiValidation {
it.enabled = true
}
}

tasks.register("checkReadme", CheckReadmeTask) {
minSupportedGradleVersion = libs.versions.minSupportedGradle
readme = file("README.md")
}

tasks.check {
dependsOn(tasks.named("checkReadme"))
}
44 changes: 44 additions & 0 deletions buildSrc/src/main/kotlin/tasks/CheckReadmeTask.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package tasks

import org.gradle.api.*
import org.gradle.api.file.*
import org.gradle.api.provider.*
import org.gradle.api.tasks.*
import org.gradle.api.tasks.PathSensitivity.*

abstract class CheckReadmeTask : DefaultTask() {
@get:Input
abstract val minSupportedGradleVersion: Property<String>

@get:InputFile
@get:PathSensitive(RELATIVE)
abstract val readme: RegularFileProperty

@TaskAction
fun execute() {
val readme = readme.get().asFile
val readmeContents = readme.readText()

val minSupportedGradleVersion = minSupportedGradleVersion.get()

val matches = Regex("Gradle (?<version>[^ ]+) or newer").findAll(readmeContents).toList()

require(matches.size >= 1) {
"""
$readme does not contain correct min supported Gradle version.
${matches.size} matches found.
""".trimIndent()
}

matches.forEach { match ->
val version = match.groups["version"]?.value ?: error("Regex failed - could not find version")
require(minSupportedGradleVersion == version) {
"""
$readme does not contain correct min supported Gradle version
Actual: ${match.value}
Expected: Gradle $minSupportedGradleVersion or newer
""".trimIndent()
}
}
}
}
3 changes: 3 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[versions]

minSupportedGradle = "7.4"
1 change: 1 addition & 0 deletions integration/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ tasks.test {
systemProperty("runtime_repo_url", rootProject.buildDir.resolve("maven").absoluteFile.invariantSeparatorsPath)
systemProperty("kotlin_repo_url", rootProject.properties["kotlin_repo_url"])
systemProperty("kotlin_version", rootProject.properties["kotlin_version"]!!)
systemProperty("minSupportedGradleVersion", libs.versions.minSupportedGradle.get())
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ package kotlinx.benchmark.integration

enum class GradleTestVersion(val versionString: String) {
v8_0("8.0.2"),
}
MinSupportedGradleVersion("7.4"),
UnsupportedGradleVersion("7.3"),
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
package kotlinx.benchmark.integration

import org.gradle.testkit.runner.*
import java.io.*
import kotlinx.benchmark.integration.GradleTestVersion.MinSupportedGradleVersion
import org.gradle.testkit.runner.BuildResult
import org.gradle.testkit.runner.GradleRunner
import java.io.File

class Runner(
private val projectDir: File,
private val print: Boolean,
private val gradleVersion: GradleTestVersion? = null,
) {

private fun gradle(vararg tasks: String): GradleRunner =
GradleRunner.create()
.withProjectDir(projectDir)
.withArguments(*(defaultArguments() + tasks))
.withGradleVersion((gradleVersion ?: MinSupportedGradleVersion).versionString)
.run {
if (print) forwardStdOutput(System.out.bufferedWriter()) else this
}
.run {
if (gradleVersion != null) withGradleVersion(gradleVersion.versionString) else this
}

fun run(vararg tasks: String, fn: BuildResult.() -> Unit = {}) {
val gradle = gradle(*tasks)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,4 @@ private fun BuildResult.assertConfigurationCacheStored() {

private fun BuildResult.assertConfigurationCacheReused() {
assertOutputContains("Configuration cache entry reused.")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package kotlinx.benchmark.integration

import org.gradle.util.GradleVersion
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class SupportedGradleVersionTest : GradleTest() {

/** The min supported version used in build scripts, provided as a system property. */
private val minSupportedGradleVersion = System.getProperty("minSupportedGradleVersion")
private val warningMessage =
"JetBrains Gradle Benchmarks plugin requires Gradle version ${GradleTestVersion.MinSupportedGradleVersion.versionString}"

@Test
fun `test MinSupportedGradleVersion matches the version used in build scripts`() {
assertEquals(minSupportedGradleVersion, GradleTestVersion.MinSupportedGradleVersion.versionString)
}

@Test
fun `test MinSupportedGradleVersion is greater than UnsupportedGradleVersion`() {
// verify the test data is valid
assertTrue(
GradleVersion.version(GradleTestVersion.MinSupportedGradleVersion.versionString) >
GradleVersion.version(GradleTestVersion.UnsupportedGradleVersion.versionString)
)
}

@Test
fun `when using min supported Gradle version, expect no warning`() {
val runner = project("kotlin-multiplatform", gradleVersion = GradleTestVersion.MinSupportedGradleVersion)

runner.run(":help", "-q") {
assertOutputDoesNotContain(warningMessage)
}
}

@Test
fun `when using unsupported Gradle version, expect warning`() {
val runner = project("kotlin-multiplatform", gradleVersion = GradleTestVersion.UnsupportedGradleVersion)

runner.run(":help", "-q") {
assertOutputContains(warningMessage)
}
}
}
41 changes: 28 additions & 13 deletions plugin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -103,24 +103,39 @@ dependencies {
compileOnly "org.openjdk.jmh:jmh-generator-bytecode:$jmhVersion" // used in worker
}

tasks.register("overridePluginVersion") {
description = "Overrides BenchmarksPlugin.PLUGIN_VERSION during release builds"
onlyIf {
project.findProperty("releaseVersion") != null
}
def generatePluginConstants = tasks.register("generatePluginConstants") {
description = "Generates constants file used by BenchmarksPlugin"

File outputDir = temporaryDir
outputs.dir(outputDir).withPropertyName("outputDir")

File constantsKtFile = new File(outputDir, "BenchmarksPluginConstants.kt")

Provider<String> benchmarkPluginVersion = project.providers.gradleProperty("releaseVersion")
.orElse(project.version.toString())
inputs.property("benchmarkPluginVersion", benchmarkPluginVersion)

Provider<String> minSupportedGradleVersion = libs.versions.minSupportedGradle
inputs.property("minSupportedGradleVersion", minSupportedGradleVersion)

doLast {
def benchmarksPluginFile = "${projectDir}/main/src/kotlinx/benchmark/gradle/BenchmarksPlugin.kt"
def releaseVersion = project.findProperty("releaseVersion")
ant.replaceregexp(
file: benchmarksPluginFile,
match: "const val PLUGIN_VERSION = \"[\\d.]+-SNAPSHOT\"",
replace: "const val PLUGIN_VERSION = \"$releaseVersion\"",
encoding: "UTF-8"
constantsKtFile.write(
"""|package kotlinx.benchmark.gradle.internal
|
|internal object BenchmarksPluginConstants {
| const val BENCHMARK_PLUGIN_VERSION = "${benchmarkPluginVersion.get()}"
| const val MIN_SUPPORTED_GRADLE_VERSION = "${minSupportedGradleVersion.get()}"
|}
|""".stripMargin()
)
}
}

tasks.compileKotlin.dependsOn overridePluginVersion
sourceSets {
main {
kotlin.srcDir(generatePluginConstants)
}
}

if (project.findProperty("publication_repository") == "space") {
// publish to Space repository
Expand Down
9 changes: 5 additions & 4 deletions plugin/main/src/kotlinx/benchmark/gradle/BenchmarksPlugin.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package kotlinx.benchmark.gradle

import kotlinx.benchmark.gradle.internal.BenchmarksPluginConstants
import kotlinx.benchmark.gradle.internal.BenchmarksPluginConstants.MIN_SUPPORTED_GRADLE_VERSION
import kotlinx.benchmark.gradle.internal.KotlinxBenchmarkPluginInternalApi
import org.gradle.api.*
import org.gradle.util.GradleVersion
Expand All @@ -12,8 +14,7 @@ constructor() : Plugin<Project> {
companion object {
const val PLUGIN_ID = "org.jetbrains.kotlinx.benchmark"

// This value is overridden by `overridePluginVersion` task during release builds.
const val PLUGIN_VERSION = "0.5.0-SNAPSHOT"
const val PLUGIN_VERSION = BenchmarksPluginConstants.BENCHMARK_PLUGIN_VERSION

const val BENCHMARKS_TASK_GROUP = "benchmark"
const val BENCHMARK_EXTENSION_NAME = "benchmark"
Expand Down Expand Up @@ -51,8 +52,8 @@ constructor() : Plugin<Project> {
// DO NOT use properties of an extension immediately, it will not contain any user-specified data
val extension = extensions.create(BENCHMARK_EXTENSION_NAME, BenchmarksExtension::class.java, project)

if (GradleVersion.current() < GradleVersion.version("7.0")) {
logger.error("JetBrains Gradle Benchmarks plugin requires Gradle version 7.0 or higher")
if (GradleVersion.current() < GradleVersion.version(MIN_SUPPORTED_GRADLE_VERSION)) {
logger.error("JetBrains Gradle Benchmarks plugin requires Gradle version $MIN_SUPPORTED_GRADLE_VERSION or higher")
return // TODO: Do we need to fail build at this point or just ignore benchmarks?
}

Expand Down
9 changes: 9 additions & 0 deletions plugin/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,13 @@ pluginManagement {
gradlePluginPortal()
}
}

dependencyResolutionManagement {
versionCatalogs {
create("libs") {
from(files("../gradle/libs.versions.toml"))
}
}
}

rootProject.name = 'kotlinx-benchmark-plugin'

0 comments on commit b8e07eb

Please sign in to comment.