Skip to content

Commit

Permalink
Adapt the plugin to recent changes in Gradle (#74)
Browse files Browse the repository at this point in the history
* Handle new architectures and operating systems
* Run detekt on more code
* Make functional tests cross-versioned
  • Loading branch information
jbartok authored Oct 22, 2024
1 parent d0d2a64 commit 3a365b2
Show file tree
Hide file tree
Showing 12 changed files with 218 additions and 38 deletions.
14 changes: 10 additions & 4 deletions foojay-resolver/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@file:Suppress("UnusedPrivateProperty", "UnstableApiUsage")

import java.io.FileNotFoundException

plugins {
Expand All @@ -19,8 +21,10 @@ java {

detekt {
buildUponDefaultConfig = true // preconfigure defaults
allRules = true
config.setFrom(project.rootProject.file("gradle/detekt.yml"))

// also check the project build file
source.from(project.buildFile)
}

dependencies {
Expand Down Expand Up @@ -95,9 +99,7 @@ val readReleaseNotes by tasks.registering {
throw FileNotFoundException("Couldn't find release notes file $releaseNotesFile.absolutePath")
}
val releaseNotes = releaseNotesFile.readText().trim()
if (releaseNotes.isBlank()) {
throw IllegalArgumentException("Release notes file $releaseNotesFile.absolutePath is empty")
}
require(releaseNotes.isBlank()) { "Release notes file $releaseNotesFile.absolutePath is empty" }
gradlePlugin.plugins["discoToolchains"].description = releaseNotes
gradlePlugin.plugins["discoToolchainsConvenience"].description = releaseNotes
}
Expand All @@ -106,3 +108,7 @@ val readReleaseNotes by tasks.registering {
tasks.publishPlugins {
dependsOn(readReleaseNotes)
}

tasks.check {
dependsOn(tasks.named("detektTest"), tasks.named("detektFunctionalTest"))
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package org.gradle.toolchains.foojay

import org.gradle.testkit.runner.BuildResult
import org.gradle.testkit.runner.GradleRunner
import org.gradle.testkit.runner.TaskOutcome
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.io.TempDir
import java.io.File
import kotlin.test.assertTrue

abstract class AbstractFoojayToolchainsPluginFunctionalTest {

Expand All @@ -16,6 +19,7 @@ abstract class AbstractFoojayToolchainsPluginFunctionalTest {
private val settingsFile by lazy { projectDir.resolve("settings.gradle.kts") }
private val propertiesFile by lazy { projectDir.resolve("gradle.properties") }
private val buildFile by lazy { projectDir.resolve("build.gradle.kts") }
private val sourceFolder by lazy { projectDir.resolve("src/main/java/") }

@BeforeEach
internal fun setUp() {
Expand All @@ -29,6 +33,16 @@ abstract class AbstractFoojayToolchainsPluginFunctionalTest {
settingsFile.writeText(settings)
buildFile.writeText(buildScript.trimIndent())

sourceFolder.mkdirs()
val sourceFile = File(sourceFolder, "Java.java")
sourceFile.writeText("""
public class Java {
public static void main(String[] args) {
System.out.println();
}
}
""".trimIndent())

return GradleRunner.create()
.forwardOutput()
.withPluginClasspath()
Expand All @@ -40,4 +54,20 @@ abstract class AbstractFoojayToolchainsPluginFunctionalTest {
System.getProperty("java.version").startsWith("11.") -> "16"
else -> "11"
}
}

protected fun assertProvisioningSuccessful(buildResult: BuildResult) {
val successfulTasks = buildResult.tasks(TaskOutcome.SUCCESS)
assertTrue(":compileJava" in successfulTasks.map { it.path })
}

protected companion object {
@JvmStatic
@Suppress("MagicNumber")
fun getGradleTestVersions(): List<String> {
val versions = GradleTestVersions.getVersions()
val latestVersions = versions.take(3)
val oldestVersion = versions.takeLast(1)
return latestVersions + oldestVersion // compromise, testing takes too long with all versions
}
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package org.gradle.toolchains.foojay

import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.MethodSource
import kotlin.test.Test
import kotlin.test.assertTrue

class FoojayToolchainsConventionPluginFunctionalTest: AbstractFoojayToolchainsPluginFunctionalTest() {

@Test
fun `can use convention plugin`() {
@ParameterizedTest(name = "gradle version: {0}")
@MethodSource("getGradleTestVersions")
fun `can use convention plugin`(gradleVersion: String) {
val settings = """
plugins {
id("org.gradle.toolchains.foojay-resolver-convention")
Expand All @@ -24,9 +27,10 @@ class FoojayToolchainsConventionPluginFunctionalTest: AbstractFoojayToolchainsPl
}
}
"""
val result = runner(settings, buildScript).build()

assertTrue("Installed toolchain from https://api.foojay.io/disco/" in result.output)
val result = runner(settings, buildScript)
.withGradleVersion(gradleVersion)
.build()
assertProvisioningSuccessful(result)
}

@Test
Expand All @@ -49,14 +53,15 @@ class FoojayToolchainsConventionPluginFunctionalTest: AbstractFoojayToolchainsPl
}
"""
val result = runner(settings, buildScript)
.withGradleVersion("7.5")
.buildAndFail()
.withGradleVersion("7.5")
.buildAndFail()

assertTrue("FoojayToolchainsPlugin needs Gradle version 7.6 or higher" in result.output)
}

@Test
fun `provides meaningful error when applied as a project plugin`() {
@ParameterizedTest(name = "gradle version: {0}")
@MethodSource("getGradleTestVersions")
fun `provides meaningful error when applied as a project plugin`(gradleVersion: String) {
val settings = ""

val buildScript = """
Expand All @@ -71,10 +76,14 @@ class FoojayToolchainsConventionPluginFunctionalTest: AbstractFoojayToolchainsPl
}
}
"""
val result = runner(settings, buildScript).buildAndFail()
val result = runner(settings, buildScript)
.withGradleVersion(gradleVersion)
.buildAndFail()

assertTrue("> Failed to apply plugin 'org.gradle.toolchains.foojay-resolver-convention'.\n" +
" > Settings plugins must be applied in the settings script." in result.output)
assertTrue(
"> Failed to apply plugin 'org.gradle.toolchains.foojay-resolver-convention'.\n" +
" > Settings plugins must be applied in the settings script." in result.output
)
}

}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package org.gradle.toolchains.foojay

import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.MethodSource
import kotlin.test.Test
import kotlin.test.assertTrue

class FoojayToolchainsPluginFunctionalTest: AbstractFoojayToolchainsPluginFunctionalTest() {

@Test
fun `can use base plugin`() {
@ParameterizedTest(name = "gradle version: {0}")
@MethodSource("getGradleTestVersions")
fun `can use base plugin`(gradleVersion: String) {
val settings = """
plugins {
id("org.gradle.toolchains.foojay-resolver")
Expand Down Expand Up @@ -34,9 +37,10 @@ class FoojayToolchainsPluginFunctionalTest: AbstractFoojayToolchainsPluginFuncti
}
}
"""
val result = runner(settings, buildScript).build()

assertTrue("Installed toolchain from https://api.foojay.io/disco/" in result.output)
val result = runner(settings, buildScript)
.withGradleVersion(gradleVersion)
.build()
assertProvisioningSuccessful(result)
}

@Test
Expand Down Expand Up @@ -69,14 +73,15 @@ class FoojayToolchainsPluginFunctionalTest: AbstractFoojayToolchainsPluginFuncti
}
"""
val result = runner(settings, buildScript)
.withGradleVersion("7.5")
.buildAndFail()
.withGradleVersion("7.5")
.buildAndFail()

assertTrue("FoojayToolchainsPlugin needs Gradle version 7.6 or higher" in result.output)
}

@Test
fun `provides meaningful error when applied as a project plugin`() {
@ParameterizedTest(name = "gradle version: {0}")
@MethodSource("getGradleTestVersions")
fun `provides meaningful error when applied as a project plugin`(gradleVersion: String) {
val settings = ""

val buildScript = """
Expand All @@ -101,9 +106,11 @@ class FoojayToolchainsPluginFunctionalTest: AbstractFoojayToolchainsPluginFuncti
}
}
"""
val result = runner(settings, buildScript).buildAndFail()
val result = runner(settings, buildScript)
.withGradleVersion(gradleVersion)
.buildAndFail()

assertTrue("> Failed to apply plugin 'org.gradle.toolchains.foojay-resolver'.\n" +
" > Settings plugins must be applied in the settings script." in result.output)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package org.gradle.toolchains.foojay

import org.gradle.internal.impldep.com.google.gson.Gson
import org.gradle.util.GradleVersion
import java.net.URL


internal
object GradleTestVersions {

private val smallestVersionOfInterest = GradleVersion.version("7.6")

internal
fun getVersions(): List<String> {
val releasedVersions = getReleasedVersions()

val testVersions = keepOnlyLatestMinor(releasedVersions)
.toMutableList()
testVersions.add(getLatestNightlyVersion())

return testVersions
.sortedByDescending { it.majorVersion }
.map { it.gradleVersion.version }
.toList()
}

private fun getLatestNightlyVersion(): VersionInfo {
val jsonText = URL("https://services.gradle.org/versions/nightly").readText()
return VersionInfo(Gson().fromJson(jsonText, VersionJsonBlock::class.java).version)
}

private fun getReleasedVersions(): List<VersionInfo> {
val jsonText = URL("https://services.gradle.org/versions/all").readText()
val allVersions = Gson().fromJson(jsonText, Array<VersionJsonBlock>::class.java)
.asSequence()
.filter { !it.snapshot }
.filter { !it.nightly }
.filter { it.rcFor.isBlank() }
.filter { it.milestoneFor.isBlank() }
.map { VersionInfo(it.version) }
.filter { it.gradleVersion >= smallestVersionOfInterest }
.toList()
return allVersions
}

private fun keepOnlyLatestMinor(versions: List<VersionInfo>): MutableList<VersionInfo> {
val filteredVersions = versions
.sortedWith(compareBy<VersionInfo> { it.majorVersion }.thenBy { it.gradleVersion })
.toMutableList()
var i = 0
while (i < filteredVersions.size - 1) {
if (filteredVersions[i].majorVersion == filteredVersions[i + 1].majorVersion) {
filteredVersions.removeAt(i)
} else {
i++
}
}
return filteredVersions
}
}

fun main() {
val versions = GradleTestVersions.getVersions()
println("versions = $versions")
}

@Suppress("MagicNumber")
private class VersionInfo(val version: String) {
val gradleVersion: GradleVersion = GradleVersion.version(version)
val majorVersion: GradleVersion = GradleVersion.version(getMajorVersion(version))
private fun getMajorVersion(version: String): String {
val majorVersionParts = version.split("\\.".toRegex())
return when (majorVersionParts.size) {
2 -> version
3 -> "${majorVersionParts[0]}.${majorVersionParts[1]}"
else -> error("Unexpected version number: $version")
}
}

override fun toString(): String = version

}

data class VersionJsonBlock(
val version: String,
val snapshot: Boolean,
val nightly: Boolean,
val rcFor: String,
val milestoneFor: String,
)
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ import java.net.URI
val architectures32Bit = setOf("x32", "i386", "x86")
val architectures64Bit = setOf("x64", "x86_64", "amd64", "ia64")
val architecturesArm64Bit = setOf("aarch64", "arm64")
val architecturesPpc64Bit = setOf("ppc64")
val architecturesPpc64BitLe = setOf("ppc64le")
val architecturesS390 = setOf("s390x")
val architecturesSparkV9 = setOf("sparcv9")

// "aarch64,aarch32,arm,arm32,armhf,armel,arm64,mips,mipsel,ppc,ppc64,ppc64le,riscv64,s390x,sparc,sparcv9,x64,x32,i386,i386,i386,x86,x86_64,amd64,ia64"

val handledArchiveTypes = setOf("tar", "tar.gz", "tgz", "zip")

fun parsePackages(json: String): List<Package> {
Expand All @@ -32,13 +39,18 @@ fun OperatingSystem.toApiValue(): String =
OperatingSystem.MAC_OS -> "macos"
OperatingSystem.SOLARIS -> "solaris"
OperatingSystem.FREE_BSD -> "linux"
OperatingSystem.AIX -> "aix"
}

private fun matches(p: Package, architecture: Architecture): Boolean =
when (architecture) {
Architecture.X86 -> p.architecture in architectures32Bit
Architecture.X86_64 -> p.architecture in architectures64Bit
Architecture.AARCH64 -> p.architecture in architecturesArm64Bit
Architecture.PPC64 -> p.architecture in architecturesPpc64Bit
Architecture.PPC64LE -> p.architecture in architecturesPpc64BitLe
Architecture.S390X -> p.architecture in architecturesS390
Architecture.SPARC_V9 -> p.architecture in architecturesSparkV9
}

private fun hasHandledArchiveType(p: Package): Boolean {
Expand Down
Loading

0 comments on commit 3a365b2

Please sign in to comment.