From 55f4a5b6dfb8adcd1573dab7e543bbd65e34168e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp?= Date: Fri, 14 Jul 2023 20:35:07 +0100 Subject: [PATCH 1/8] Fix #228: reduce parallelism in task and increase parallelism between tasks (#246) * Enable configuration cache * Remove parallelism inside compatTest tasks. * Remove kotlin-dsl and only use what is used in this project (kotlin-dsl dependency and sam with receiver). This prevents us from needing to fight with kotlin-dsl overriding language versions. * Move to new KGP DSL for setting up versions. (kotlinOptions to compilerOptions) * Make compatTest past without kotlin-dsl * Revert to kotlin-dsl, it does too many things apart from the forceful version. * Fix kotlin versioning * Simplify * Un-nest * Make a change to trigger rerun of tests --- build.gradle.kts | 59 ++++++++++++------- gradle.properties | 1 + .../publishplugin/TestExtensions.kt | 8 +-- 3 files changed, 43 insertions(+), 25 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 714d7e78..c47bc67c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,7 @@ import org.gradle.initialization.IGradlePropertiesLoader.ENV_PROJECT_PROPERTIES_PREFIX import org.gradle.initialization.IGradlePropertiesLoader.SYSTEM_PROJECT_PROPERTIES_PREFIX -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.dsl.KotlinVersion plugins { `kotlin-dsl` @@ -161,28 +162,44 @@ sourceSets { } } -tasks { - afterEvaluate { - // This needs to be in an afterEvaluate block, - // because otherwise KotlinDslCompilerPlugins would win, and override what we've set to Kotlin 1.8. - withType().configureEach { - kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8.toString() - // Supporting Gradle 6.0+ needs to use Kotlin 1.3. - // See https://docs.gradle.org/current/userguide/compatibility.html - kotlinOptions.apiVersion = "1.3" - // Theoretically we could use newer language version here, - // but sadly the @kotlin.Metadata created on the classes would be incompatible with Kotlin 1.3 consumers. - kotlinOptions.languageVersion = "1.3" - doFirst { - if (kotlinOptions.apiVersion == "1.3") { - // Suppress "Language version 1.3 is deprecated and its support will be removed in a future version of Kotlin". - kotlinOptions.freeCompilerArgs += "-Xsuppress-version-warnings" - } else { - TODO("Remove -Xsuppress-version-warnings suppression, or change the condition to ${kotlinOptions.languageVersion}") - } +kotlin.target.compilations.configureEach { + // Supporting Gradle 6.0+ needs to use Kotlin 1.3. + // See https://docs.gradle.org/current/userguide/compatibility.html + // For future maintainer: Kotlin 1.9.0 dropped support for Kotlin 1.3, it'll only support 1.4+. + // This means Gradle 7.0 will be the lowest supportable version for plugins. + val usedKotlinVersion = @Suppress("DEPRECATION") KotlinVersion.KOTLIN_1_3 + + compilerOptions.configure { + // Gradle fully supports running on Java 8: https://docs.gradle.org/current/userguide/compatibility.html, + // so we should allow users to do that too. + jvmTarget = JvmTarget.fromTarget(JavaVersion.VERSION_1_8.toString()) + + // Suppress "Language version 1.3 is deprecated and its support will be removed in a future version of Kotlin". + freeCompilerArgs.add("-Xsuppress-version-warnings") + } + compileTaskProvider.configure { + // These two (api & lang) needs to be here instead of in compilations.compilerOptions.configure { }, + // to prevent KotlinDslCompilerPlugins overriding to Kotlin 1.8. + compilerOptions.apiVersion = usedKotlinVersion + // Theoretically we could use newer language version here, + // but sadly the @kotlin.Metadata created on the classes would be incompatible with older consumers. + compilerOptions.languageVersion = usedKotlinVersion + + // Validate that we're using the right version. + doFirst { + val api = compilerOptions.apiVersion.get() + val language = compilerOptions.languageVersion.get() + if (api != usedKotlinVersion || language != usedKotlinVersion) { + TODO( + "There's mismatch between configured and actual versions:\n" + + "apiVersion=${api}, languageVersion=${language}, configured=${usedKotlinVersion}." + ) } } } +} + +tasks { shadowJar { exclude("META-INF/maven/**", "META-INF/proguard/**", "META-INF/*.kotlin_module") manifest { @@ -228,7 +245,7 @@ tasks { withType().configureEach { dependsOn(shadowJar) useJUnitPlatform() - maxParallelForks = 8 + maxParallelForks = if (name.startsWith("compatTest")) 1 else 8 } withType().matching { it.name.startsWith("compatTest") }.configureEach { systemProperty("plugin.version", project.version) diff --git a/gradle.properties b/gradle.properties index aec0a559..8c5fc5cf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,3 @@ org.gradle.caching=true org.gradle.parallel=true +org.gradle.configuration-cache=true diff --git a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/TestExtensions.kt b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/TestExtensions.kt index 0d39361e..3f3d9a8b 100644 --- a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/TestExtensions.kt +++ b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/TestExtensions.kt @@ -20,13 +20,13 @@ import java.nio.file.Files import java.nio.file.Path fun Path.write(text: String): Path { - Files.createDirectories(parent) - toFile().writeText(text) + Files.createDirectories(this.parent) + this.toFile().writeText(text) return this } fun Path.append(text: String): Path { - Files.createDirectories(parent) - toFile().appendText(text) + Files.createDirectories(this.parent) + this.toFile().appendText(text) return this } From 38aed1bf52a8c8420fb2604a8deb9477a117d6b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp?= Date: Sat, 15 Jul 2023 09:32:03 +0100 Subject: [PATCH 2/8] Random fixes (#245) * gradlew stutterWriteLocks to get Gradle 8.2.1 * Assumption always holds * Minor fixes in Readme * Fix platform type warnings in project * Simplify comment * Reduce "yellow" in build.gradle.kts * Break long lines * Never executed on Gradle 5.x any more. * Use simpler API * Remove outdated comment * Simplify ConfigurableFileCollection setup --- README.md | 4 +-- build.gradle.kts | 32 ++++++++++++------- .../BaseNexusPublishPluginTests.kt | 17 ++-------- stutter.lockfile | 6 ++-- 4 files changed, 29 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 50168a39..c906e93b 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This Gradle plugin is a turn-key solution for publishing to Nexus. You can use it to publish your artifacts to any Nexus instance (internal or public). It is great for publishing your open source to Sonatype, and then to Maven Central, in a fully automated fashion. -Vanilla Gradle is great but it cannot fully automate publications to Nexus. This plugin enables isolation of staging repositories so that you can reliably publish from CI, and each publication uses a brand new, explicitly created staging repo ([more](https://github.com/gradle-nexus/publish-plugin/issues/63)). Moreover, the plugin provides tasks to close and release staging repositories, covering the whole releasing process to Maven Central. +Vanilla Gradle is great, but it cannot fully automate publications to Nexus. This plugin enables isolation of staging repositories so that you can reliably publish from CI, and each publication uses a brand new, explicitly created staging repo ([more](https://github.com/gradle-nexus/publish-plugin/issues/63)). Moreover, the plugin provides tasks to close and release staging repositories, covering the whole releasing process to Maven Central. This plugin is intended as a replacement of the [Gradle Nexus Staging Plugin](https://github.com/Codearte/gradle-nexus-staging-plugin/) and [Nexus Publish Plugin](https://github.com/marcphilipp/nexus-publish-plugin) duo. See a dedicated [migration guide](https://github.com/gradle-nexus/publish-plugin/wiki/Migration-from-gradle_nexus_staging-plugin---nexus_publish-plugin-duo). @@ -202,7 +202,7 @@ By default, `initialize${repository.name.capitalize()}StagingRepository` task ad The description can be customized via: * `io.github.gradlenexus.publishplugin.NexusPublishExtension.getRepositoryDescription` property (default: `$group:$module:$version` of the root project) * `io.github.gradlenexus.publishplugin.InitializeNexusStagingRepository.repositoryDescription` property -* `io.github.gradlenexus.publishplugin.FindStagingRepository.getDescriptionRegex` property (regex, default: `"\\b" + Regex.escape(repositoryDescription) + "(\\s|$)"`) +* `io.github.gradlenexus.publishplugin.FindStagingRepository.descriptionRegex` property (regex, default: `"\\b" + Regex.escape(repositoryDescription) + "(\\s|$)"`) So the steps to publish and release in different Gradle invocations are: 1. Publish the artifacts to the staging repository: `./gradlew publishToSonatype` diff --git a/build.gradle.kts b/build.gradle.kts index c47bc67c..c138310b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,5 @@ +@file:Suppress("UnstableApiUsage") // Property assignment is incubating in Gradle 8.1/8.2. + import org.gradle.initialization.IGradlePropertiesLoader.ENV_PROJECT_PROPERTIES_PREFIX import org.gradle.initialization.IGradlePropertiesLoader.SYSTEM_PROJECT_PROPERTIES_PREFIX import org.jetbrains.kotlin.gradle.dsl.JvmTarget @@ -6,8 +8,6 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinVersion plugins { `kotlin-dsl` id("com.gradle.plugin-publish") version "1.2.0" - // From 6.14.0 onwards Spotless requires Gradle to be on Java 11, - // but we still use Java 8 in .github/workflows/java-versions.yml. id("com.diffplug.spotless") version "6.19.0" id("com.github.johnrengelman.shadow") version "8.1.1" id("org.jetbrains.gradle.plugin.idea-ext") @@ -131,7 +131,8 @@ stutter { } } -val e2eTest by sourceSets.creating { //separate infrastructure as compatTest is called multiple times with different Java versions +// Separate infrastructure as compatTest is called multiple times with different Java versions. +val e2eTest: SourceSet by sourceSets.creating { compileClasspath += sourceSets["compatTest"].output compileClasspath += sourceSets["main"].output runtimeClasspath += sourceSets["compatTest"].output @@ -214,25 +215,34 @@ tasks { dependsOn(shadowJar) } pluginUnderTestMetadata { - pluginClasspath.from.clear() - pluginClasspath.from(shadowJar) + pluginClasspath.setFrom(shadowJar) } register("e2eTest") { description = "Run E2E tests." group = "Verification" testClassesDirs = e2eTest.output.classesDirs classpath = e2eTest.runtimeClasspath - //pass E2E releasing properties to tests. Prefer environment variables which are not displayed with --info - // (unless non CI friendly properties with "." are used) - listOf("sonatypeUsername", "sonatypePassword", "signingKey", "signingPassword", "signing.gnupg.homeDir", "signing.gnupg.keyName", "signing.gnupg.passphrase").forEach { + // Pass E2E releasing properties to tests. + // Prefer environment variables which are not displayed with --info + // (unless non CI friendly properties with "." are used). + listOf( + "sonatypeUsername", + "sonatypePassword", + "signingKey", + "signingPassword", + "signing.gnupg.homeDir", + "signing.gnupg.keyName", + "signing.gnupg.passphrase" + ).forEach { val e2eName = "${it}E2E" val e2eEnvName = "${ENV_PROJECT_PROPERTIES_PREFIX}${e2eName}" - //properties defined using ORG_GRADLE_PROJECT_ are accessible in child process anyway + // Properties defined using ORG_GRADLE_PROJECT_ are accessible in child process anyway. if (project.hasProperty(e2eName) && System.getenv(e2eEnvName) == null) { + val e2eValue = project.property(e2eName)!! if (e2eName.contains(".")) { - systemProperties.put("${SYSTEM_PROJECT_PROPERTIES_PREFIX}${e2eName}", project.property(e2eName)) + systemProperty("${SYSTEM_PROJECT_PROPERTIES_PREFIX}${e2eName}", e2eValue) } else { - environment("$ENV_PROJECT_PROPERTIES_PREFIX${e2eName}", project.property(e2eName)!!) + environment("${ENV_PROJECT_PROPERTIES_PREFIX}${e2eName}", e2eValue) } } } diff --git a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/BaseNexusPublishPluginTests.kt b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/BaseNexusPublishPluginTests.kt index fdeba797..3f429764 100644 --- a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/BaseNexusPublishPluginTests.kt +++ b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/BaseNexusPublishPluginTests.kt @@ -26,7 +26,6 @@ import org.gradle.testkit.runner.BuildResult import org.gradle.testkit.runner.GradleRunner import org.gradle.testkit.runner.TaskOutcome import org.gradle.util.GradleVersion -import org.junit.jupiter.api.Assumptions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test @@ -60,7 +59,7 @@ abstract class BaseNexusPublishPluginTests { private val gson = Gson() - protected val gradleVersion = + protected val gradleVersion: GradleVersion = System.getProperty("compat.gradle.version")?.let { GradleVersion.version(it) } ?: GradleVersion.current() private val gradleRunner = GradleRunner.create() @@ -540,11 +539,6 @@ abstract class BaseNexusPublishPluginTests { @Test @Disabled("Fails on my Fedora...") fun `uses configured connect timeout`() { - Assumptions.assumeTrue( - gradleVersion >= GradleVersion.version("5.0"), - "Task timeouts were added in Gradle 5.0" - ) - // Taken from https://stackoverflow.com/a/904609/5866817 val nonRoutableAddress = "10.255.255.1" @@ -1037,15 +1031,10 @@ abstract class BaseNexusPublishPluginTests { gradleRunner(*arguments).buildAndFail() private fun gradleRunner(vararg arguments: String): GradleRunner { - val warnings = when { - // Failing only became an option at Gradle 5.6. - gradleVersion >= GradleVersion.version("5.6") -> "fail" - else -> "all" - } return gradleRunner -// .withDebug(true) +// .withDebug(true) .withProjectDir(projectDir.toFile()) - .withArguments(*arguments, "--stacktrace", "--warning-mode=$warnings") + .withArguments(*arguments, "--stacktrace", "--warning-mode=fail") .forwardOutput() } diff --git a/stutter.lockfile b/stutter.lockfile index e073792d..6f46d4df 100644 --- a/stutter.lockfile +++ b/stutter.lockfile @@ -1,4 +1,4 @@ # DO NOT MODIFY: Generated by Stutter plugin. -java11=6.0.1,6.9.4,7.0.2,7.6.2,8.0.2,8.2 -java17=7.3.3,7.6.2,8.0.2,8.2 -java8=6.0.1,6.9.4,7.0.2,7.6.2,8.0.2,8.2 +java11=6.0.1,6.9.4,7.0.2,7.6.2,8.0.2,8.2.1 +java17=7.3.3,7.6.2,8.0.2,8.2.1 +java8=6.0.1,6.9.4,7.0.2,7.6.2,8.0.2,8.2.1 From 700bd5f724abc2f6cb38a265670d38837bd421b9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 15 Jul 2023 10:46:36 +0200 Subject: [PATCH 3/8] chore(deps): update plugin com.gradle.enterprise to v3.13.4 (#233) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index fc8a473b..45942be0 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("com.gradle.enterprise") version "3.13.3" + id("com.gradle.enterprise") version "3.13.4" id("org.gradle.toolchains.foojay-resolver-convention") version "0.6.0" } From 1f1108bda774473139010e76bb177f8c2d357736 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Sat, 8 Jul 2023 15:55:25 +0100 Subject: [PATCH 4/8] Bump minimum version to Gradle 6.1 --- .github/workflows/java-versions.yml | 2 +- README.md | 2 +- build.gradle.kts | 6 +++--- .../github/gradlenexus/publishplugin/NexusPublishPlugin.kt | 4 ++-- stutter.lockfile | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/java-versions.yml b/.github/workflows/java-versions.yml index 98e4e0fc..b65f5fb2 100644 --- a/.github/workflows/java-versions.yml +++ b/.github/workflows/java-versions.yml @@ -29,7 +29,7 @@ jobs: - name: Reduce number of Gradle regressions builds run: | # Keep only the last Gradle version per Stutter matrix; for each line this transformation is done: - # java11=6.0.1,6.9.4,7.0.2,7.6.1,8.0.2,8.1.1,8.2-rc-1 + # java11=6.1.1,6.9.4,7.0.2,7.6.1,8.0.2,8.1.1,8.2-rc-1 # -> # java11=8.2-rc-1 # The trick is that \2 will greedily eat everything before the last comma. diff --git a/README.md b/README.md index c906e93b..b2953036 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This plugin is intended as a replacement of the [Gradle Nexus Staging Plugin](ht ### Applying the plugin -The plugin must be applied to the root project and requires Gradle 6.0 or later. It is important to +The plugin must be applied to the root project and requires Gradle 6.1 or later. It is important to set the group and the version to the root project, so the plugin can detect if it is a snapshot version or not in order to select the correct repository where artifacts will be published. diff --git a/build.gradle.kts b/build.gradle.kts index c138310b..ece16fce 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -109,7 +109,7 @@ stutter { languageVersion = JavaLanguageVersion.of(8) } gradleVersions { - compatibleRange("6.0") + compatibleRange("6.1") } } register("java11") { @@ -117,7 +117,7 @@ stutter { languageVersion = JavaLanguageVersion.of(11) } gradleVersions { - compatibleRange("6.0") + compatibleRange("6.1") } } register("java17") { @@ -164,7 +164,7 @@ sourceSets { } kotlin.target.compilations.configureEach { - // Supporting Gradle 6.0+ needs to use Kotlin 1.3. + // Supporting Gradle 6.1+ needs to use Kotlin 1.3. // See https://docs.gradle.org/current/userguide/compatibility.html // For future maintainer: Kotlin 1.9.0 dropped support for Kotlin 1.3, it'll only support 1.4+. // This means Gradle 7.0 will be the lowest supportable version for plugins. diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt index 313b4d26..90fcbe1e 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt @@ -54,8 +54,8 @@ class NexusPublishPlugin : Plugin { "Plugin must be applied to the root project but was applied to ${project.path}" } - require(GradleVersion.current() >= GradleVersion.version("6.0")) { - "The plugin requires Gradle version 6.0+" + require(GradleVersion.current() >= GradleVersion.version("6.1")) { + "The plugin requires Gradle version 6.1+" } val registry = createRegistry(project) diff --git a/stutter.lockfile b/stutter.lockfile index 6f46d4df..7c3e10d0 100644 --- a/stutter.lockfile +++ b/stutter.lockfile @@ -1,4 +1,4 @@ # DO NOT MODIFY: Generated by Stutter plugin. -java11=6.0.1,6.9.4,7.0.2,7.6.2,8.0.2,8.2.1 +java11=6.1.1,6.9.4,7.0.2,7.6.2,8.0.2,8.2.1 java17=7.3.3,7.6.2,8.0.2,8.2.1 -java8=6.0.1,6.9.4,7.0.2,7.6.2,8.0.2,8.2.1 +java8=6.1.1,6.9.4,7.0.2,7.6.2,8.0.2,8.2.1 From 5d14d631e4eb52373c65cbc0f3956e946d20893f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Sat, 8 Jul 2023 16:11:12 +0100 Subject: [PATCH 5/8] Use build service all the way (Gradle 6.1) --- .../publishplugin/FindStagingRepository.kt | 7 +-- .../InitializeNexusStagingRepository.kt | 7 +-- .../publishplugin/NexusPublishPlugin.kt | 53 ++++++++++--------- 3 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/FindStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/FindStagingRepository.kt index 2c6a6bbf..16a054f7 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/FindStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/FindStagingRepository.kt @@ -16,8 +16,8 @@ package io.github.gradlenexus.publishplugin -import io.github.gradlenexus.publishplugin.internal.InvalidatingStagingRepositoryDescriptorRegistry import io.github.gradlenexus.publishplugin.internal.NexusClient +import io.github.gradlenexus.publishplugin.internal.StagingRepositoryDescriptorRegistryBuildService import org.gradle.api.GradleException import org.gradle.api.Incubating import org.gradle.api.provider.Property @@ -30,7 +30,8 @@ import org.gradle.api.tasks.TaskAction abstract class FindStagingRepository : AbstractNexusStagingRepositoryTask() { @get:Internal - abstract val registry: Property + // TODO use @ServiceReference instead of @Internal when minimum is Gradle 8.0. + abstract val registry: Property @get:Optional @get:Input @@ -59,7 +60,7 @@ abstract class FindStagingRepository : AbstractNexusStagingRepositoryTask() { val descriptor = client.findStagingRepository(stagingProfileId, Regex(descriptionRegex)) logger.lifecycle("Staging repository for {} at {}, stagingProfileId '{}', descriptionRegex '{}' is '{}'", repository.name, serverUrl, stagingProfileId, descriptionRegex, descriptor.stagingRepositoryId) stagingRepositoryId.set(descriptor.stagingRepositoryId) - registry.get()[repository.name] = descriptor + registry.get().registry[repository.name] = descriptor } // TODO: Duplication with InitializeNexusStagingRepository diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt index 0357e79c..1a0b05f7 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt @@ -16,8 +16,8 @@ package io.github.gradlenexus.publishplugin -import io.github.gradlenexus.publishplugin.internal.InvalidatingStagingRepositoryDescriptorRegistry import io.github.gradlenexus.publishplugin.internal.NexusClient +import io.github.gradlenexus.publishplugin.internal.StagingRepositoryDescriptorRegistryBuildService import okhttp3.HttpUrl import org.gradle.api.GradleException import org.gradle.api.provider.Property @@ -29,7 +29,8 @@ import org.gradle.api.tasks.TaskAction abstract class InitializeNexusStagingRepository : AbstractNexusStagingRepositoryTask() { @get:Internal - abstract val registry: Property + // TODO use @ServiceReference instead of @Internal when minimum is Gradle 8.0. + abstract val registry: Property @get:Optional @get:Input @@ -45,7 +46,7 @@ abstract class InitializeNexusStagingRepository : AbstractNexusStagingRepository val descriptor = client.createStagingRepository(stagingProfileId, repositoryDescription.get()) val consumerUrl = HttpUrl.get(serverUrl)!!.newBuilder().addEncodedPathSegments("repositories/${descriptor.stagingRepositoryId}/content/").build() logger.lifecycle("Created staging repository '{}' at {}", descriptor.stagingRepositoryId, consumerUrl) - registry.get()[repository.name] = descriptor + registry.get().registry[repository.name] = descriptor } private fun determineStagingProfileId(repository: NexusRepository, client: NexusClient): String { diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt index 90fcbe1e..7d179e83 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt @@ -17,7 +17,6 @@ package io.github.gradlenexus.publishplugin import io.github.gradlenexus.publishplugin.NexusRepository.PublicationType -import io.github.gradlenexus.publishplugin.internal.InvalidatingStagingRepositoryDescriptorRegistry import io.github.gradlenexus.publishplugin.internal.StagingRepositoryDescriptorRegistryBuildService import org.gradle.api.Action import org.gradle.api.Plugin @@ -78,19 +77,18 @@ class NexusPublishPlugin : Plugin { } } - private fun createRegistry(rootProject: Project): Provider { - if (GradleVersion.current() >= GradleVersion.version("6.1")) { - return rootProject.gradle.sharedServices.registerIfAbsent( - "stagingRepositoryUrlRegistry", - StagingRepositoryDescriptorRegistryBuildService::class, - Action { } - ).map { it.registry } - } - val registry = InvalidatingStagingRepositoryDescriptorRegistry() - return rootProject.provider { registry } - } + private fun createRegistry(rootProject: Project): Provider = + rootProject.gradle.sharedServices.registerIfAbsent( + "stagingRepositoryUrlRegistry", + StagingRepositoryDescriptorRegistryBuildService::class, + Action { } + ) - private fun configureNexusTasks(rootProject: Project, extension: NexusPublishExtension, registry: Provider) { + private fun configureNexusTasks( + rootProject: Project, + extension: NexusPublishExtension, + registryService: Provider + ) { rootProject.tasks.withType(AbstractNexusStagingRepositoryTask::class.java).configureEach { clientTimeout.convention(extension.clientTimeout) connectTimeout.convention(extension.connectTimeout) @@ -100,13 +98,14 @@ class NexusPublishPlugin : Plugin { } rootProject.tasks.withType(AbstractTransitionNexusStagingRepositoryTask::class.java).configureEach { transitionCheckOptions.convention(extension.transitionCheckOptions) - stagingRepositoryId.convention(registry.map { it[repository.get().name].stagingRepositoryId }) + usesService(registryService) + stagingRepositoryId.convention(registryService.map { it.registry[repository.get().name].stagingRepositoryId }) } extension.repositories.all { username.convention(rootProject.provider { rootProject.findProperty("${name}Username") as? String }) password.convention(rootProject.provider { rootProject.findProperty("${name}Password") as? String }) publicationType.convention(PublicationType.MAVEN) - configureRepositoryTasks(rootProject.tasks, extension, this, registry) + configureRepositoryTasks(rootProject.tasks, extension, this, registryService) } extension.repositories.whenObjectRemoved { rootProject.tasks.named("initialize${capitalizedName}StagingRepository").configure { @@ -136,7 +135,7 @@ class NexusPublishPlugin : Plugin { tasks: TaskContainer, extension: NexusPublishExtension, repo: NexusRepository, - registryProvider: Provider + registryService: Provider ) { @Suppress("UNUSED_VARIABLE") // Keep it consistent. val retrieveStagingProfileTask = tasks.register( @@ -154,7 +153,8 @@ class NexusPublishPlugin : Plugin { ) { group = PublishingPlugin.PUBLISH_TASK_GROUP description = "Initializes the staging repository in '${repo.name}' Nexus instance." - registry.set(registryProvider) + registry.set(registryService) + usesService(registryService) repository.convention(repo) packageGroup.convention(extension.packageGroup) } @@ -163,7 +163,8 @@ class NexusPublishPlugin : Plugin { ) { group = PublishingPlugin.PUBLISH_TASK_GROUP description = "Finds the staging repository for ${repo.name}" - registry.set(registryProvider) + registry.set(registryService) + usesService(registryService) repository.convention(repo) packageGroup.convention(extension.packageGroup) descriptionRegex.convention(extension.repositoryDescription.map { "\\b" + Regex.escape(it) + "(\\s|$)" }) @@ -203,7 +204,11 @@ class NexusPublishPlugin : Plugin { } } - private fun configurePublishingForAllProjects(rootProject: Project, extension: NexusPublishExtension, registry: Provider) { + private fun configurePublishingForAllProjects( + rootProject: Project, + extension: NexusPublishExtension, + registry: Provider + ) { rootProject.afterEvaluate { allprojects { val publishingProject = this @@ -242,7 +247,7 @@ class NexusPublishPlugin : Plugin { private fun addPublicationRepositories( project: Project, extension: NexusPublishExtension, - registry: Provider + registry: Provider ): Map = extension.repositories.associateWith { nexusRepo -> createArtifactRepository(nexusRepo.publicationType.get(), project, nexusRepo, extension, registry) } @@ -252,7 +257,7 @@ class NexusPublishPlugin : Plugin { project: Project, nexusRepo: NexusRepository, extension: NexusPublishExtension, - registry: Provider + registry: Provider ): ArtifactRepository = when (publicationType) { PublicationType.MAVEN -> project.theExtension().repositories.maven { configureArtifactRepo(nexusRepo, extension, registry, false) @@ -271,7 +276,7 @@ class NexusPublishPlugin : Plugin { private fun T.configureArtifactRepo( nexusRepo: NexusRepository, extension: NexusPublishExtension, - registry: Provider, + registry: Provider, provideFallback: Boolean ) where T : UrlArtifactRepository, T : ArtifactRepository, T : AuthenticationSupported { name = nexusRepo.name @@ -327,13 +332,13 @@ class NexusPublishPlugin : Plugin { private fun getRepoUrl( nexusRepo: NexusRepository, extension: NexusPublishExtension, - registry: Provider, + registry: Provider, provideFallback: Boolean, artifactRepo: ArtifactRepository ): Provider = extension.useStaging.flatMap { useStaging -> if (useStaging) { - registry.map { descriptorRegistry -> + registry.map { it.registry }.map { descriptorRegistry -> if (provideFallback) { descriptorRegistry.invalidateLater(nexusRepo.name, artifactRepo) descriptorRegistry.tryGet(nexusRepo.name)?.stagingRepositoryUrl ?: nexusRepo.nexusUrl.get() From 93e0e7795c6adfdfd3ffc2ad355abf3047f81867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Thu, 13 Jul 2023 09:37:14 +0100 Subject: [PATCH 6/8] Bump minimum version to Gradle 6.2 --- .github/workflows/java-versions.yml | 2 +- README.md | 2 +- build.gradle.kts | 6 +++--- .../github/gradlenexus/publishplugin/NexusPublishPlugin.kt | 4 ++-- stutter.lockfile | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/java-versions.yml b/.github/workflows/java-versions.yml index b65f5fb2..91467e4f 100644 --- a/.github/workflows/java-versions.yml +++ b/.github/workflows/java-versions.yml @@ -29,7 +29,7 @@ jobs: - name: Reduce number of Gradle regressions builds run: | # Keep only the last Gradle version per Stutter matrix; for each line this transformation is done: - # java11=6.1.1,6.9.4,7.0.2,7.6.1,8.0.2,8.1.1,8.2-rc-1 + # java11=6.2.2,6.9.4,7.0.2,7.6.1,8.0.2,8.1.1,8.2-rc-1 # -> # java11=8.2-rc-1 # The trick is that \2 will greedily eat everything before the last comma. diff --git a/README.md b/README.md index b2953036..1e6cdbe4 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This plugin is intended as a replacement of the [Gradle Nexus Staging Plugin](ht ### Applying the plugin -The plugin must be applied to the root project and requires Gradle 6.1 or later. It is important to +The plugin must be applied to the root project and requires Gradle 6.2 or later. It is important to set the group and the version to the root project, so the plugin can detect if it is a snapshot version or not in order to select the correct repository where artifacts will be published. diff --git a/build.gradle.kts b/build.gradle.kts index ece16fce..896610bf 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -109,7 +109,7 @@ stutter { languageVersion = JavaLanguageVersion.of(8) } gradleVersions { - compatibleRange("6.1") + compatibleRange("6.2") } } register("java11") { @@ -117,7 +117,7 @@ stutter { languageVersion = JavaLanguageVersion.of(11) } gradleVersions { - compatibleRange("6.1") + compatibleRange("6.2") } } register("java17") { @@ -164,7 +164,7 @@ sourceSets { } kotlin.target.compilations.configureEach { - // Supporting Gradle 6.1+ needs to use Kotlin 1.3. + // Supporting Gradle 6.2+ needs to use Kotlin 1.3. // See https://docs.gradle.org/current/userguide/compatibility.html // For future maintainer: Kotlin 1.9.0 dropped support for Kotlin 1.3, it'll only support 1.4+. // This means Gradle 7.0 will be the lowest supportable version for plugins. diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt index 7d179e83..399218cd 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt @@ -53,8 +53,8 @@ class NexusPublishPlugin : Plugin { "Plugin must be applied to the root project but was applied to ${project.path}" } - require(GradleVersion.current() >= GradleVersion.version("6.1")) { - "The plugin requires Gradle version 6.1+" + require(GradleVersion.current() >= GradleVersion.version("6.2")) { + "The plugin requires Gradle version 6.2+" } val registry = createRegistry(project) diff --git a/stutter.lockfile b/stutter.lockfile index 7c3e10d0..bff6f5cf 100644 --- a/stutter.lockfile +++ b/stutter.lockfile @@ -1,4 +1,4 @@ # DO NOT MODIFY: Generated by Stutter plugin. -java11=6.1.1,6.9.4,7.0.2,7.6.2,8.0.2,8.2.1 +java11=6.2.2,6.9.4,7.0.2,7.6.2,8.0.2,8.2.1 java17=7.3.3,7.6.2,8.0.2,8.2.1 -java8=6.1.1,6.9.4,7.0.2,7.6.2,8.0.2,8.2.1 +java8=6.2.2,6.9.4,7.0.2,7.6.2,8.0.2,8.2.1 From 0a3ba207cac921cc1bdb15a4f48fdb42c769547d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Sat, 8 Jul 2023 11:28:03 +0100 Subject: [PATCH 7/8] Use providers.gradleProperty (Gradle 6.2) --- .../io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt index 399218cd..d4024591 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt @@ -102,8 +102,8 @@ class NexusPublishPlugin : Plugin { stagingRepositoryId.convention(registryService.map { it.registry[repository.get().name].stagingRepositoryId }) } extension.repositories.all { - username.convention(rootProject.provider { rootProject.findProperty("${name}Username") as? String }) - password.convention(rootProject.provider { rootProject.findProperty("${name}Password") as? String }) + username.convention(rootProject.providers.gradleProperty("${name}Username")) + password.convention(rootProject.providers.gradleProperty("${name}Password")) publicationType.convention(PublicationType.MAVEN) configureRepositoryTasks(rootProject.tasks, extension, this, registryService) } From fc62497ff2821a41e0c5f3c2541910d796d99dda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Thu, 13 Jul 2023 10:39:20 +0100 Subject: [PATCH 8/8] forUseAtConfigurationTime compatibility --- .../publishplugin/NexusPublishPlugin.kt | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt index d4024591..5f1c14b7 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt @@ -102,8 +102,8 @@ class NexusPublishPlugin : Plugin { stagingRepositoryId.convention(registryService.map { it.registry[repository.get().name].stagingRepositoryId }) } extension.repositories.all { - username.convention(rootProject.providers.gradleProperty("${name}Username")) - password.convention(rootProject.providers.gradleProperty("${name}Password")) + username.convention(rootProject.providers.gradleProperty("${name}Username").forUseAtConfigurationTimeCompat()) + password.convention(rootProject.providers.gradleProperty("${name}Password").forUseAtConfigurationTimeCompat()) publicationType.convention(PublicationType.MAVEN) configureRepositoryTasks(rootProject.tasks, extension, this, registryService) } @@ -380,3 +380,17 @@ private inline fun Project.theExtension(): T = this.extensions.findByType(it) ?: error("The plugin cannot be applied without the publishing plugin") } + +private fun Provider.forUseAtConfigurationTimeCompat(): Provider = + if (GradleVersion.current() < GradleVersion.version("6.5")) { + // Gradle < 6.5 doesn't have this function. + this + } else if (GradleVersion.current() < GradleVersion.version("7.4")) { + // Gradle 6.5 - 7.3 requires this function to be called. + @Suppress("DEPRECATION") + this.forUseAtConfigurationTime() + } else { + // Gradle >= 7.4 deprecated this function in favor of not calling it (became no-op, and will eventually nag). + // https://docs.gradle.org/current/userguide/upgrading_version_7.html#for_use_at_configuration_time_deprecation + this + }