From 6ce5c2b3ec501cb01471ea722a1b313f5fa44612 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 11 Jan 2020 14:52:45 +0100 Subject: [PATCH] Don't share state via NexusRepository - Remove stagingProfileId from close/release tasks as it is not needed - Wire stagingRepositoryId for close/release task in plugin - Remove mutable state from NexusRepository - Rename CLI option to --staging-repository-id to make it more idiomatic --- .../publishplugin/NexusPublishPluginTests.kt | 34 +----------- .../AbstractNexusStagingRepositoryTask.kt | 53 +++++-------------- .../CloseNexusStagingRepository.kt | 21 +++----- .../InitializeNexusStagingRepository.kt | 34 ++++++++++-- .../publishplugin/NexusPublishExtension.kt | 10 ++-- .../publishplugin/NexusPublishPlugin.kt | 10 +++- .../publishplugin/NexusRepository.kt | 38 +++++-------- ...NexusStagingRepositoryMutableTaskConfig.kt | 32 ----------- .../ReleaseNexusStagingRepository.kt | 21 +++----- 9 files changed, 85 insertions(+), 168 deletions(-) delete mode 100644 src/main/kotlin/io/github/gradlenexus/publishplugin/NexusStagingRepositoryMutableTaskConfig.kt diff --git a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt index 96cf71e9..e9e9a51e 100644 --- a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt +++ b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt @@ -706,7 +706,7 @@ class NexusPublishPluginTests { //and stubCloseStagingRepoRequestWithSubsequentQueryAboutItsState(server, OVERRIDDEN_STAGED_REPOSITORY_ID) - val result = run("closeSonatypeStagingRepository", "--stagingRepositoryId=$OVERRIDDEN_STAGED_REPOSITORY_ID") + val result = run("closeSonatypeStagingRepository", "--staging-repository-id=$OVERRIDDEN_STAGED_REPOSITORY_ID") assertSuccess(result, ":closeSonatypeStagingRepository") assertCloseOfStagingRepo(server, OVERRIDDEN_STAGED_REPOSITORY_ID) @@ -719,7 +719,7 @@ class NexusPublishPluginTests { //and stubReleaseStagingRepoRequestWithSubsequentQueryAboutItsState(server, OVERRIDDEN_STAGED_REPOSITORY_ID) - val result = run("releaseSonatypeStagingRepository", "--stagingRepositoryId=$OVERRIDDEN_STAGED_REPOSITORY_ID") + val result = run("releaseSonatypeStagingRepository", "--staging-repository-id=$OVERRIDDEN_STAGED_REPOSITORY_ID") assertSuccess(result, ":releaseSonatypeStagingRepository") assertReleaseOfStagingRepo(server, OVERRIDDEN_STAGED_REPOSITORY_ID) @@ -762,36 +762,6 @@ class NexusPublishPluginTests { assertGetStagingProfile(server, 1) } - @Test - internal fun `close task should resolve stagingProfileId if not provided and keep it for release task`(@Wiremock server: WireMockServer) { - gradleRunner.withDebug(true) - - writeDefaultSingleProjectConfiguration() - //and - buildGradle.append(""" - nexusPublishing { - repositories { - sonatype { - nexusUrl = uri('${server.baseUrl()}') - //No staging profile defined - } - } - } - """) - //and - stubGetStagingProfilesForOneProfileIdGivenId(server, STAGING_PROFILE_ID) - stubCreateStagingRepoRequest(server, "/staging/profiles/$STAGING_PROFILE_ID/start", STAGED_REPOSITORY_ID) - stubCloseStagingRepoRequestWithSubsequentQueryAboutItsState(server) - stubReleaseStagingRepoRequestWithSubsequentQueryAboutItsState(server) - - val result = run("closeSonatypeStagingRepository", "--stagingRepositoryId=$STAGED_REPOSITORY_ID", "releaseSonatypeStagingRepository") - - assertSuccess(result, ":closeSonatypeStagingRepository") - assertSuccess(result, ":releaseSonatypeStagingRepository") - //and - assertGetStagingProfile(server, 1) - } - // TODO: To be used also in other tests private fun writeDefaultSingleProjectConfiguration() { projectDir.resolve("settings.gradle").write(""" diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt index 286979c0..d25ac0ec 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt @@ -16,15 +16,10 @@ package io.github.gradlenexus.publishplugin -import io.github.gradlenexus.publishplugin.internal.NexusClient import org.gradle.api.DefaultTask -import org.gradle.api.GradleException import org.gradle.api.model.ObjectFactory -import org.gradle.api.provider.Property -import org.gradle.api.tasks.Input import org.gradle.api.tasks.Internal import org.gradle.api.tasks.Nested -import org.gradle.api.tasks.Optional import org.gradle.kotlin.dsl.property import java.time.Duration import javax.inject.Inject @@ -33,47 +28,23 @@ import javax.inject.Inject abstract class AbstractNexusStagingRepositoryTask @Inject constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository: NexusRepository) : DefaultTask() { - @get:Optional - @get:Input - protected val packageGroup: Property = objects.property() - - @get:Internal - protected val clientTimeout: Property = objects.property() - - @get:Internal - protected val connectTimeout: Property = objects.property() - - //TODO: Expose externally as interface with getters only - @get:Nested - protected val repository: Property = objects.property() - - init { - packageGroup.set(extension.packageGroup) - clientTimeout.set(extension.clientTimeout) - connectTimeout.set(extension.connectTimeout) - this.repository.set(repository) - this.onlyIf { extension.useStaging.getOrElse(false) } + @Internal + val clientTimeout = objects.property().apply { + set(extension.clientTimeout) } - protected fun determineAndCacheStagingProfileId(client: NexusClient): String { - //NexusRepository.stagingProfileId is already finalized by Gradle at a time tasks are executed - workaround with non-property values is needed - var stagingProfileId = repository.get().stagingRepositoryMutableTaskConfig.orNull?.profileId - ?: repository.get().stagingProfileId.orNull - if (stagingProfileId == null) { - val packageGroup = packageGroup.get() - logger.debug("No stagingProfileId set, querying for packageGroup '{}'", packageGroup) - stagingProfileId = client.findStagingProfileId(packageGroup) - ?: throw GradleException("Failed to find staging profile for package group: $packageGroup") - cacheStagingProfileIdForOtherTasks(stagingProfileId) - } - return stagingProfileId + @Internal + val connectTimeout = objects.property().apply { + set(extension.connectTimeout) } - private fun cacheStagingProfileIdForOtherTasks(stagingProfileId: String) { - repository.get().stagingRepositoryMutableTaskConfig.get().profileId = stagingProfileId + //TODO: Expose externally as interface with getters only + @Nested + val repository = objects.property().apply { + set(repository) } - protected fun cacheStagingRepositoryForOtherTasks(stagingRepositoryId: String) { - repository.get().stagingRepositoryMutableTaskConfig.get().repositoryId = stagingRepositoryId + init { + this.onlyIf { extension.useStaging.getOrElse(false) } } } diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt index e90e8069..d25239cf 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt @@ -18,8 +18,7 @@ package io.github.gradlenexus.publishplugin import io.github.gradlenexus.publishplugin.internal.NexusClient import org.gradle.api.model.ObjectFactory -import org.gradle.api.provider.Property -import org.gradle.api.tasks.Nested +import org.gradle.api.tasks.Input import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.options.Option import org.gradle.kotlin.dsl.property @@ -30,25 +29,19 @@ open class CloseNexusStagingRepository @Inject constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository: NexusRepository) : AbstractNexusStagingRepositoryTask(objects, extension, repository) { - @get:Nested - val stagingRepositoryConfig: Property = objects.property() + @Input + val stagingRepositoryId = objects.property() - @Option(option = "stagingRepositoryId", description = "stagingRepositoryId to close") + @Option(option = "staging-repository-id", description = "staging repository id to close") fun setStagingRepositoryId(stagingRepositoryId: String) { - stagingRepositoryConfig.get().repositoryId = stagingRepositoryId - } - - init { - // TODO: Replace with convention() once only Gradle 5.1+ is supported - stagingRepositoryConfig.set(repository.stagingRepositoryMutableTaskConfig) + this.stagingRepositoryId.set(stagingRepositoryId) } @TaskAction fun closeStagingRepo() { val client = NexusClient(repository.get().nexusUrl.get(), repository.get().username.orNull, repository.get().password.orNull, clientTimeout.orNull, connectTimeout.orNull) - val stagingProfileId = determineAndCacheStagingProfileId(client) - logger.info("Closing staging repository with id '{}' for stagingProfileId '{}'", stagingRepositoryConfig.get().repositoryId, stagingProfileId) - client.closeStagingRepository(stagingRepositoryConfig.get().repositoryId!!) //should be checked by @Input + logger.info("Closing staging repository with id '{}'", stagingRepositoryId.get()) + client.closeStagingRepository(stagingRepositoryId.get()) //should be checked by @Input // TODO: Broken with real Nexus - waiting for effective execution is also required https://github.com/gradle-nexus/publish-plugin/issues/7 } } diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt index e2883a3f..4eb39793 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt @@ -18,18 +18,33 @@ package io.github.gradlenexus.publishplugin import io.codearte.gradle.nexus.NexusStagingExtension import io.github.gradlenexus.publishplugin.internal.NexusClient +import org.gradle.api.GradleException import org.gradle.api.artifacts.repositories.MavenArtifactRepository import org.gradle.api.model.ObjectFactory import org.gradle.api.publish.PublishingExtension +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional import org.gradle.api.tasks.TaskAction +import org.gradle.kotlin.dsl.property import org.gradle.kotlin.dsl.the import java.net.URI import javax.inject.Inject @Suppress("UnstableApiUsage") open class InitializeNexusStagingRepository @Inject -constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository: NexusRepository, private val serverUrlToStagingRepoUrl: MutableMap) : - AbstractNexusStagingRepositoryTask(objects, extension, repository) { +constructor( + objects: ObjectFactory, + extension: NexusPublishExtension, + repository: NexusRepository, + private val serverUrlToStagingRepoUrl: MutableMap, + private val stagingRepositoryId: (String) -> Unit +) : AbstractNexusStagingRepositoryTask(objects, extension, repository) { + + @Optional + @Input + val packageGroup = objects.property().apply { + set(extension.packageGroup) + } @TaskAction fun createStagingRepoAndReplacePublishingRepoUrl() { @@ -40,10 +55,10 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository internal fun createStagingRepo(): URI { return serverUrlToStagingRepoUrl.computeIfAbsent(repository.get().nexusUrl.get()) { serverUrl -> val client = NexusClient(serverUrl, repository.get().username.orNull, repository.get().password.orNull, clientTimeout.orNull, connectTimeout.orNull) - val stagingProfileId = determineAndCacheStagingProfileId(client) + val stagingProfileId = determineStagingProfileId(client) logger.info("Creating staging repository for stagingProfileId '{}'", stagingProfileId) val stagingRepositoryIdAsString = client.createStagingRepository(stagingProfileId) - cacheStagingRepositoryForOtherTasks(stagingRepositoryIdAsString) + stagingRepositoryId.invoke(stagingRepositoryIdAsString) //TODO: To be removed in next iteration project.rootProject.plugins.withId("io.codearte.nexus-staging") { @@ -61,6 +76,17 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository } } + private fun determineStagingProfileId(client: NexusClient): String { + var stagingProfileId = repository.get().stagingProfileId.orNull + if (stagingProfileId == null) { + val packageGroup = packageGroup.get() + logger.debug("No stagingProfileId set, querying for packageGroup '{}'", packageGroup) + stagingProfileId = client.findStagingProfileId(packageGroup) + ?: throw GradleException("Failed to find staging profile for package group: $packageGroup") + } + return stagingProfileId + } + private fun replacePublishingRepoUrl(url: URI) { val publishing = project.the() val repository = publishing.repositories.getByName(repository.get().name) as MavenArtifactRepository diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishExtension.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishExtension.kt index dee2ee6c..5f25f9aa 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishExtension.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishExtension.kt @@ -18,11 +18,9 @@ package io.github.gradlenexus.publishplugin import org.gradle.api.Action import org.gradle.api.Project -import org.gradle.api.provider.Property import org.gradle.kotlin.dsl.container import org.gradle.kotlin.dsl.newInstance import org.gradle.kotlin.dsl.property - import java.time.Duration @Suppress("UnstableApiUsage") @@ -32,19 +30,19 @@ open class NexusPublishExtension(project: Project) { internal const val NAME = "nexusPublishing" } - val useStaging: Property = project.objects.property().apply { + val useStaging = project.objects.property().apply { set(project.provider { !project.version.toString().endsWith("-SNAPSHOT") }) } - val packageGroup: Property = project.objects.property().apply { + val packageGroup = project.objects.property().apply { set(project.provider { project.group.toString() }) } - val clientTimeout: Property = project.objects.property().apply { + val clientTimeout = project.objects.property().apply { set(Duration.ofMinutes(1)) } - val connectTimeout: Property = project.objects.property().apply { + val connectTimeout = project.objects.property().apply { set(Duration.ofMinutes(1)) } diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt index 2510efce..b274e4e0 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt @@ -30,6 +30,7 @@ import org.gradle.api.publish.plugins.PublishingPlugin import org.gradle.api.tasks.TaskProvider import org.gradle.kotlin.dsl.apply import org.gradle.kotlin.dsl.create +import org.gradle.kotlin.dsl.property import org.gradle.kotlin.dsl.register import org.gradle.kotlin.dsl.the import org.gradle.kotlin.dsl.withType @@ -55,16 +56,23 @@ class NexusPublishPlugin : Plugin { val extension = project.extensions.create(NexusPublishExtension.NAME, project) extension.repositories.all { + val stagingRepositoryId = project.objects.property() project.tasks.register("publishTo${capitalizedName()}") { description = "Publishes all Maven publications produced by this project to the '${this@all.name}' Nexus repository." group = PublishingPlugin.PUBLISH_TASK_GROUP } project.tasks - .register("initialize${capitalizedName()}StagingRepository", project.objects, extension, this, serverUrlToStagingRepoUrl) + .register("initialize${capitalizedName()}StagingRepository", project.objects, extension, this, serverUrlToStagingRepoUrl, { id: String -> stagingRepositoryId.set(id) }) project.tasks .register("close${capitalizedName()}StagingRepository", project.objects, extension, this) + .configure { + this.stagingRepositoryId.set(stagingRepositoryId) + } project.tasks .register("release${capitalizedName()}StagingRepository", project.objects, extension, this) + .configure { + this.stagingRepositoryId.set(stagingRepositoryId) + } } extension.repositories.whenObjectRemoved { project.tasks.remove(project.tasks.named("publishTo${capitalizedName()}") as Any) diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt index 11df2aaf..9639d893 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt @@ -17,46 +17,36 @@ package io.github.gradlenexus.publishplugin import org.gradle.api.Project -import org.gradle.api.provider.Property import org.gradle.api.tasks.Input -import org.gradle.api.tasks.Internal import org.gradle.api.tasks.Optional import org.gradle.kotlin.dsl.property import java.net.URI import javax.inject.Inject @Suppress("UnstableApiUsage") -open class NexusRepository @Inject constructor(@get:Input val name: String, project: Project) { +open class NexusRepository @Inject constructor(@Input val name: String, project: Project) { - @get:Input - val nexusUrl: Property = project.objects.property() + @Input + val nexusUrl = project.objects.property() - @get:Input - val snapshotRepositoryUrl: Property = project.objects.property() + @Input + val snapshotRepositoryUrl = project.objects.property() - @get:Optional - @get:Input - val username: Property = project.objects.property().apply { + @Optional + @Input + val username = project.objects.property().apply { set(project.provider { project.findProperty("${name}Username") as? String }) } - @get:Optional - @get:Input - val password: Property = project.objects.property().apply { + @Optional + @Input + val password = project.objects.property().apply { set(project.provider { project.findProperty("${name}Password") as? String }) } - @get:Optional - @get:Input - val stagingProfileId: Property = project.objects.property() - - @get:Internal - val stagingRepositoryMutableTaskConfig: Property = project.objects.property() - - init { - // TODO: Replace with convention() once only Gradle 5.1+ is supported - stagingRepositoryMutableTaskConfig.set(NexusStagingRepositoryMutableTaskConfig.empty()) - } + @Optional + @Input + val stagingProfileId = project.objects.property() internal fun capitalizedName(): String { return name.capitalize() diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusStagingRepositoryMutableTaskConfig.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusStagingRepositoryMutableTaskConfig.kt deleted file mode 100644 index bb0e290f..00000000 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusStagingRepositoryMutableTaskConfig.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package io.github.gradlenexus.publishplugin - -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.Optional - -open class NexusStagingRepositoryMutableTaskConfig constructor( - @get:Input var repositoryId: String?, - @get:Input @get:Optional var profileId: String? -) { - - companion object { - fun empty(): NexusStagingRepositoryMutableTaskConfig { - return NexusStagingRepositoryMutableTaskConfig(null, null) - } - } -} diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt index d1e3a9c3..e6293dbe 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt @@ -18,8 +18,7 @@ package io.github.gradlenexus.publishplugin import io.github.gradlenexus.publishplugin.internal.NexusClient import org.gradle.api.model.ObjectFactory -import org.gradle.api.provider.Property -import org.gradle.api.tasks.Nested +import org.gradle.api.tasks.Input import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.options.Option import org.gradle.kotlin.dsl.property @@ -31,25 +30,19 @@ open class ReleaseNexusStagingRepository @Inject constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository: NexusRepository) : AbstractNexusStagingRepositoryTask(objects, extension, repository) { - @get:Nested - val stagingRepositoryConfig: Property = objects.property() + @Input + val stagingRepositoryId = objects.property() - @Option(option = "stagingRepositoryId", description = "stagingRepositoryId to release") + @Option(option = "staging-repository-id", description = "staging repository id to release") fun setStagingRepositoryId(stagingRepositoryId: String) { - stagingRepositoryConfig.get().repositoryId = stagingRepositoryId - } - - init { - // TODO: Replace with convention() once only Gradle 5.1+ is supported - stagingRepositoryConfig.set(repository.stagingRepositoryMutableTaskConfig) + this.stagingRepositoryId.set(stagingRepositoryId) } @TaskAction fun releaseStagingRepo() { val client = NexusClient(repository.get().nexusUrl.get(), repository.get().username.orNull, repository.get().password.orNull, clientTimeout.orNull, connectTimeout.orNull) - val stagingProfileId = determineAndCacheStagingProfileId(client) // TODO: Will it update value in extension? - logger.info("Releasing staging repository with id '{}' for stagingProfileId '{}'", stagingRepositoryConfig.get().repositoryId, stagingProfileId) - client.releaseStagingRepository(stagingRepositoryConfig.get().repositoryId!!) + logger.info("Releasing staging repository with id '{}'", stagingRepositoryId.get()) + client.releaseStagingRepository(stagingRepositoryId.get()) // TODO: Broken with real Nexus - waiting for effective execution is also required https://github.com/gradle-nexus/publish-plugin/issues/7 } }