From b92668aef6b262b195392380a4901e0e11c4bd24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Zaj=C4=85czkowski?= Date: Wed, 16 Oct 2019 11:58:58 +0200 Subject: [PATCH 01/18] [#4] Base class for staging repository operations --- .../BaseOperationOnNexusStagingRepository.kt | 73 +++++++++++++++++++ .../InitializeNexusStagingRepository.kt | 50 +------------ 2 files changed, 75 insertions(+), 48 deletions(-) create mode 100644 src/main/kotlin/io/github/gradlenexus/publishplugin/BaseOperationOnNexusStagingRepository.kt diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/BaseOperationOnNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/BaseOperationOnNexusStagingRepository.kt new file mode 100644 index 00000000..7665ae5a --- /dev/null +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/BaseOperationOnNexusStagingRepository.kt @@ -0,0 +1,73 @@ +/* + * 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.DefaultTask +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.Optional +import org.gradle.kotlin.dsl.property +import java.net.URI +import java.time.Duration +import javax.inject.Inject + +@Suppress("UnstableApiUsage") +abstract class BaseOperationOnNexusStagingRepository @Inject +constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository: NexusRepository) : DefaultTask() { + + @get:Input + protected val serverUrl: Property = objects.property() + + @get:Optional + @get:Input + protected val username: Property = objects.property() + + @get:Optional + @get:Input + protected val password: Property = objects.property() + + @get:Optional + @get:Input + protected val packageGroup: Property = objects.property() + + @get:Optional + @get:Input + protected val stagingProfileId: Property = objects.property() + + @get:Input + protected val repositoryName: Property = objects.property() + + @get:Internal + protected val clientTimeout: Property = objects.property() + + @get:Internal + protected val connectTimeout: Property = objects.property() + + init { + serverUrl.set(repository.nexusUrl) + username.set(repository.username) + password.set(repository.password) + packageGroup.set(extension.packageGroup) + stagingProfileId.set(repository.stagingProfileId) + repositoryName.set(repository.name) + clientTimeout.set(extension.clientTimeout) + connectTimeout.set(extension.connectTimeout) + this.onlyIf { extension.useStaging.getOrElse(false) } + } +} diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt index 06a590b2..5eeed67c 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt @@ -18,65 +18,19 @@ package io.github.gradlenexus.publishplugin import io.github.gradlenexus.publishplugin.internal.NexusClient import io.codearte.gradle.nexus.NexusStagingExtension -import org.gradle.api.DefaultTask import org.gradle.api.GradleException import org.gradle.api.artifacts.repositories.MavenArtifactRepository import org.gradle.api.model.ObjectFactory -import org.gradle.api.provider.Property import org.gradle.api.publish.PublishingExtension -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.Internal -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 java.time.Duration import javax.inject.Inject @Suppress("UnstableApiUsage") open class InitializeNexusStagingRepository @Inject -constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository: NexusRepository, private val serverUrlToStagingRepoUrl: MutableMap) : DefaultTask() { - - @get:Input - val serverUrl: Property = objects.property() - - @get:Optional - @get:Input - val username: Property = objects.property() - - @get:Optional - @get:Input - val password: Property = objects.property() - - @get:Optional - @get:Input - val packageGroup: Property = objects.property() - - @get:Optional - @get:Input - val stagingProfileId: Property = objects.property() - - @get:Input - val repositoryName: Property = objects.property() - - @get:Internal - val clientTimeout: Property = objects.property() - - @get:Internal - val connectTimeout: Property = objects.property() - - init { - serverUrl.set(repository.nexusUrl) - username.set(repository.username) - password.set(repository.password) - packageGroup.set(extension.packageGroup) - stagingProfileId.set(repository.stagingProfileId) - repositoryName.set(repository.name) - clientTimeout.set(extension.clientTimeout) - connectTimeout.set(extension.connectTimeout) - this.onlyIf { extension.useStaging.getOrElse(false) } - } +constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository: NexusRepository, private val serverUrlToStagingRepoUrl: MutableMap) : + BaseOperationOnNexusStagingRepository(objects, extension, repository) { @TaskAction fun createStagingRepoAndReplacePublishingRepoUrl() { From 48db8ad72f8c903fe2d931b506699118f51f601a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Zaj=C4=85czkowski?= Date: Fri, 18 Oct 2019 18:52:49 +0200 Subject: [PATCH 02/18] [#4] Close and release tasks Initial version. --- .stutter/java11.lock | 4 + .stutter/java8.lock | 7 +- build.gradle.kts | 6 +- .../publishplugin/NexusPublishPluginTests.kt | 110 +++++++++++++++++- .../publishplugin/TestExtensions.kt | 9 +- .../BaseOperationOnNexusStagingRepository.kt | 13 +++ .../CloseNexusStagingRepository.kt | 47 ++++++++ .../InitializeNexusStagingRepository.kt | 31 +++-- .../publishplugin/NexusPublishPlugin.kt | 43 +++++-- .../publishplugin/NexusRepository.kt | 6 + .../ReleaseNexusStagingRepository.kt | 47 ++++++++ .../publishplugin/internal/NexusClient.kt | 36 ++++++ .../StagingPluginIntegrationTest.kt | 1 + .../publishplugin/TaskOrchestrationTest.kt | 109 +++++++++++++++++ 14 files changed, 433 insertions(+), 36 deletions(-) create mode 100644 .stutter/java11.lock create mode 100644 src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt create mode 100644 src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt create mode 100644 src/test/kotlin/io/github/gradlenexus/publishplugin/TaskOrchestrationTest.kt diff --git a/.stutter/java11.lock b/.stutter/java11.lock new file mode 100644 index 00000000..13ae7251 --- /dev/null +++ b/.stutter/java11.lock @@ -0,0 +1,4 @@ +# DO NOT MODIFY: Generated by Stutter plugin. +4.10.3 +5.0 +5.6.3 diff --git a/.stutter/java8.lock b/.stutter/java8.lock index 04cefca3..13ae7251 100644 --- a/.stutter/java8.lock +++ b/.stutter/java8.lock @@ -1,9 +1,4 @@ # DO NOT MODIFY: Generated by Stutter plugin. 4.10.3 5.0 -5.1.1 -5.2.1 -5.3.1 -5.4.1 -5.5.1 -5.6.2 +5.6.3 diff --git a/build.gradle.kts b/build.gradle.kts index 4ea31c51..ee812d3f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -51,7 +51,7 @@ repositories { val licenseHeaderFile = file("gradle/license-header.txt") spotless { kotlin { - ktlint() + ktlint().userData(mapOf("disabled_rules" to "comment-spacing")) licenseHeaderFile(licenseHeaderFile) } } @@ -98,9 +98,13 @@ dependencies { } stutter { + isSparse = (findProperty("stutter.sparce")?.toString()?.toBoolean()) ?: true java(8) { compatibleRange("4.10") } + java(11) { + compatibleRange("4.10") + } } configurations { diff --git a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt index 772c1632..cfdcd7e4 100644 --- a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt +++ b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt @@ -35,8 +35,10 @@ import org.gradle.testkit.runner.TaskOutcome import org.gradle.testkit.runner.TaskOutcome.FAILED import org.gradle.testkit.runner.TaskOutcome.SKIPPED import org.gradle.testkit.runner.TaskOutcome.SUCCESS +import org.gradle.util.GradleVersion import org.gradle.util.VersionNumber import org.junit.jupiter.api.Assumptions.assumeTrue +import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.junit.jupiter.api.io.TempDir @@ -45,6 +47,7 @@ import ru.lanwen.wiremock.ext.WiremockResolver.Wiremock import java.nio.file.Files import java.nio.file.Path +@Suppress("FunctionName") // TODO: How to suppress "kotlin:S100" from SonarLint? @ExtendWith(WiremockResolver::class) class NexusPublishPluginTests { @@ -55,7 +58,7 @@ class NexusPublishPluginTests { private val gson = Gson() - private val gradleVersion = System.getProperty("compat.gradle.version") + private val gradleVersion = System.getProperty("compat.gradle.version") ?: GradleVersion.current().version private val gradleRunner = GradleRunner.create() .withPluginClasspath() @@ -67,6 +70,13 @@ class NexusPublishPluginTests { @TempDir lateinit var projectDir: Path + lateinit var buildGradle: Path + + @BeforeEach + internal fun setUp() { + buildGradle = projectDir.resolve("build.gradle") + } + @Test fun `publish task depends on correct tasks`() { projectDir.resolve("settings.gradle").write(""" @@ -615,6 +625,94 @@ class NexusPublishPluginTests { .contains("b.snapshotRepositoryUrl = https://oss.sonatype.org/content/repositories/snapshots/") } + @Test + fun `should close staging repository`(@Wiremock server: WireMockServer) { + writeDefaultSingleProjectConfiguration() + buildGradle.append(""" + nexusPublishing { + repositories { + sonatype { + nexusUrl = uri('${server.baseUrl()}') + stagingProfileId = '$STAGING_PROFILE_ID' + } + } + } + """) + + stubCreateStagingRepoRequest(server, "/staging/profiles/$STAGING_PROFILE_ID/start", STAGED_REPOSITORY_ID) + server.stubFor(post(urlEqualTo("/staging/bulk/close")) + .withRequestBody(matchingJsonPath("\$.data[?(@.stagedRepositoryIds[0] == '$STAGED_REPOSITORY_ID')]")) + .withRequestBody(matchingJsonPath("\$.data[?(@.autoDropAfterRelease == true)]")) + .willReturn(aResponse().withHeader("Content-Type", "application/json").withBody("{}"))) + server.stubFor(get(urlEqualTo("/staging/repository/$STAGED_REPOSITORY_ID")) + .willReturn(aResponse().withHeader("Content-Type", "application/json").withBody("{\"transitioning\":false,\"type\":\"CLOSED\"}"))) + + val result = run("initializeSonatypeStagingRepository", "closeSonatypeStagingRepository") + + assertSuccess(result, ":initializeSonatypeStagingRepository") + assertSuccess(result, ":closeSonatypeStagingRepository") + assertCloseOfStagingRepo(server) + } + + @Test + fun `should close and release staging repository`(@Wiremock server: WireMockServer) { + writeDefaultSingleProjectConfiguration() + buildGradle.append(""" + nexusPublishing { + repositories { + sonatype { + nexusUrl = uri('${server.baseUrl()}') + stagingProfileId = '$STAGING_PROFILE_ID' + } + } + } + """) + + stubCreateStagingRepoRequest(server, "/staging/profiles/$STAGING_PROFILE_ID/start", STAGED_REPOSITORY_ID) + server.stubFor(post(urlEqualTo("/staging/bulk/promote")) + .withRequestBody(matchingJsonPath("\$.data[?(@.stagedRepositoryIds[0] == '$STAGED_REPOSITORY_ID')]")) + .withRequestBody(matchingJsonPath("\$.data[?(@.autoDropAfterRelease == true)]")) + .willReturn(aResponse().withHeader("Content-Type", "application/json").withBody("{}"))) + server.stubFor(get(urlEqualTo("/staging/repository/$STAGED_REPOSITORY_ID")) + .willReturn(aResponse().withHeader("Content-Type", "application/json").withBody("{\"transitioning\":false,\"type\":\"RELEASED\"}"))) + + val result = run("tasks", "initializeSonatypeStagingRepository", "releaseSonatypeStagingRepository") + + assertSuccess(result, ":initializeSonatypeStagingRepository") + assertSuccess(result, ":releaseSonatypeStagingRepository") + assertReleaseOfStagingRepo(server) + } + + // TODO: To be used also in other tests + private fun writeDefaultSingleProjectConfiguration() { + projectDir.resolve("settings.gradle").write(""" + rootProject.name = 'sample' + """) + projectDir.resolve("build.gradle").write(""" + buildscript { + repositories { + gradlePluginPortal() + } + dependencies { + classpath files($pluginClasspathAsString) + } + } + plugins { + id('java-library') + } + apply plugin: 'io.github.gradle-nexus.publish-plugin' + group = 'org.example' + version = '0.0.1' + publishing { + publications { + mavenJava(MavenPublication) { + from(components.java) + } + } + } + """) + } + private fun run(vararg arguments: String): BuildResult { return gradleRunner(*arguments).build() } @@ -673,7 +771,15 @@ class NexusPublishPluginTests { } private fun assertCloseOfStagingRepo(server: WireMockServer) { - server.verify(postRequestedFor(urlMatching("/staging/bulk/close")) + assertGivenTransitionOperationOfStagingRepo(server, "close") + } + + private fun assertReleaseOfStagingRepo(server: WireMockServer) { + assertGivenTransitionOperationOfStagingRepo(server, "promote") + } + + private fun assertGivenTransitionOperationOfStagingRepo(server: WireMockServer, transitionOperation: String) { + server.verify(postRequestedFor(urlMatching("/staging/bulk/$transitionOperation")) .withRequestBody(matchingJsonPath("\$.data[?(@.stagedRepositoryIds[0] == '$STAGED_REPOSITORY_ID')]"))) } } diff --git a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/TestExtensions.kt b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/TestExtensions.kt index 484e57f4..c25e3bfa 100644 --- a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/TestExtensions.kt +++ b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/TestExtensions.kt @@ -19,7 +19,14 @@ package io.github.gradlenexus.publishplugin import java.nio.file.Files import java.nio.file.Path -fun Path.write(text: String) { +fun Path.write(text: String): Path { Files.createDirectories(parent) toFile().writeText(text) + return this +} + +fun Path.append(text: String): Path { + Files.createDirectories(parent) + toFile().appendText(text) + return this } diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/BaseOperationOnNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/BaseOperationOnNexusStagingRepository.kt index 7665ae5a..6d0f6383 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/BaseOperationOnNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/BaseOperationOnNexusStagingRepository.kt @@ -16,7 +16,9 @@ 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 @@ -70,4 +72,15 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository connectTimeout.set(extension.connectTimeout) this.onlyIf { extension.useStaging.getOrElse(false) } } + + protected fun determineStagingProfileId(client: NexusClient): String { + var stagingProfileId = 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 + } } diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt new file mode 100644 index 00000000..eaaec2d5 --- /dev/null +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt @@ -0,0 +1,47 @@ +/* + * 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 io.github.gradlenexus.publishplugin.internal.NexusClient +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.TaskAction +import org.gradle.kotlin.dsl.property +import javax.inject.Inject + +@Suppress("UnstableApiUsage") +open class CloseNexusStagingRepository @Inject +constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository: NexusRepository) : + BaseOperationOnNexusStagingRepository(objects, extension, repository) { + + @get:Input + val stagingRepositoryId: Property = objects.property() + + init { + stagingRepositoryId.set(repository.stagingRepositoryId) + } + + @TaskAction + fun closeStagingRepo() { + val client = NexusClient(serverUrl.get(), username.orNull, password.orNull, clientTimeout.orNull, connectTimeout.orNull) + val stagingProfileId = determineStagingProfileId(client) + logger.info("Closing staging repository with id '{}' for stagingProfileId '{}'", stagingRepositoryId.get(), stagingProfileId) + client.closeStagingRepository(stagingRepositoryId.get()) + // 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 5eeed67c..8186dfbf 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt @@ -16,11 +16,11 @@ package io.github.gradlenexus.publishplugin -import io.github.gradlenexus.publishplugin.internal.NexusClient import io.codearte.gradle.nexus.NexusStagingExtension -import org.gradle.api.GradleException +import io.github.gradlenexus.publishplugin.internal.NexusClient import org.gradle.api.artifacts.repositories.MavenArtifactRepository import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property import org.gradle.api.publish.PublishingExtension import org.gradle.api.tasks.TaskAction import org.gradle.kotlin.dsl.the @@ -32,6 +32,8 @@ open class InitializeNexusStagingRepository @Inject constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository: NexusRepository, private val serverUrlToStagingRepoUrl: MutableMap) : BaseOperationOnNexusStagingRepository(objects, extension, repository) { + private val stagingRepositoryId: Property = repository.stagingRepositoryId + @TaskAction fun createStagingRepoAndReplacePublishingRepoUrl() { val url = createStagingRepo() @@ -41,13 +43,15 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository internal fun createStagingRepo(): URI { return serverUrlToStagingRepoUrl.computeIfAbsent(serverUrl.get()) { serverUrl -> val client = NexusClient(serverUrl, username.orNull, password.orNull, clientTimeout.orNull, connectTimeout.orNull) - val stagingProfileId = determineStagingProfileId(client) + val stagingProfileId = determineStagingProfileId(client) // TODO: It would be good to keep/cache value in Extension/Repository logger.info("Creating staging repository for stagingProfileId '{}'", stagingProfileId) - val stagingRepositoryId = client.createStagingRepository(stagingProfileId) + val stagingRepositoryIdAsString = client.createStagingRepository(stagingProfileId) + keppStagingRepositoyIdInExtension(stagingRepositoryIdAsString) + project.rootProject.plugins.withId("io.codearte.nexus-staging") { val nexusStagingExtension = project.rootProject.the() try { - nexusStagingExtension.stagingRepositoryId.set(stagingRepositoryId) + nexusStagingExtension.stagingRepositoryId.set(stagingRepositoryIdAsString) } catch (e: NoSuchMethodError) { logger.warn("For increased publishing reliability please update the io.codearte.nexus-staging plugin to at least version 0.20.0.\n" + "If your version is at least 0.20.0, try to update the io.github.gradle-nexus.publish-plugin plugin to its latest version.\n" + @@ -55,25 +59,18 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository logger.debug("getStagingRepositoryId method not found on nexusStagingExtension", e) } } - client.getStagingRepositoryUri(stagingRepositoryId) + client.getStagingRepositoryUri(stagingRepositoryIdAsString) } } - private fun determineStagingProfileId(client: NexusClient): String { - var stagingProfileId = 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(repositoryName.get()) as MavenArtifactRepository logger.info("Updating URL of publishing repository '{}' to '{}'", repository.name, url) repository.setUrl(url.toString()) } + + private fun keppStagingRepositoyIdInExtension(stagingRepositoryIdAsString: String) { + stagingRepositoryId.set(stagingRepositoryIdAsString) + } } diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt index 09fcf7bb..2510efce 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPlugin.kt @@ -30,7 +30,6 @@ 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.named import org.gradle.kotlin.dsl.register import org.gradle.kotlin.dsl.the import org.gradle.kotlin.dsl.withType @@ -56,25 +55,35 @@ class NexusPublishPlugin : Plugin { val extension = project.extensions.create(NexusPublishExtension.NAME, project) extension.repositories.all { - project.tasks.register("publishTo${name.capitalize()}") { + 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${name.capitalize()}StagingRepository", project.objects, extension, this, serverUrlToStagingRepoUrl) + .register("initialize${capitalizedName()}StagingRepository", project.objects, extension, this, serverUrlToStagingRepoUrl) + project.tasks + .register("close${capitalizedName()}StagingRepository", project.objects, extension, this) + project.tasks + .register("release${capitalizedName()}StagingRepository", project.objects, extension, this) } extension.repositories.whenObjectRemoved { - project.tasks.remove(project.tasks.named("publishTo${name.capitalize()}") as Any) - project.tasks.remove(project.tasks.named("initialize${name.capitalize()}StagingRepository") as Any) + project.tasks.remove(project.tasks.named("publishTo${capitalizedName()}") as Any) + project.tasks.remove(project.tasks.named("initialize${capitalizedName()}StagingRepository") as Any) + project.tasks.remove(project.tasks.named("close${capitalizedName()}StagingRepository") as Any) + project.tasks.remove(project.tasks.named("release${capitalizedName()}StagingRepository") as Any) } project.afterEvaluate { val nexusRepositories = addMavenRepositories(project, extension) nexusRepositories.forEach { (nexusRepo, mavenRepo) -> - val publishToNexusTask = project.tasks.named("publishTo${nexusRepo.name.capitalize()}") + val publishToNexusTask = project.tasks.named("publishTo${nexusRepo.capitalizedName()}") val initializeTask = project.tasks.withType(InitializeNexusStagingRepository::class) - .named("initialize${nexusRepo.name.capitalize()}StagingRepository") - configureTaskDependencies(project, publishToNexusTask, initializeTask, mavenRepo) + .named("initialize${nexusRepo.capitalizedName()}StagingRepository") + val closeTask = project.tasks.withType(CloseNexusStagingRepository::class) + .named("close${nexusRepo.capitalizedName()}StagingRepository") + val releaseTask = project.tasks.withType(ReleaseNexusStagingRepository::class) + .named("release${nexusRepo.capitalizedName()}StagingRepository") + configureTaskDependencies(project, publishToNexusTask, initializeTask, closeTask, releaseTask, mavenRepo) } } @@ -109,7 +118,14 @@ class NexusPublishPlugin : Plugin { } } - private fun configureTaskDependencies(project: Project, publishToNexusTask: TaskProvider, initializeTask: TaskProvider, nexusRepository: MavenArtifactRepository) { + private fun configureTaskDependencies( + project: Project, + publishToNexusTask: TaskProvider, + initializeTask: TaskProvider, + closeTask: TaskProvider, + releaseTask: TaskProvider, + nexusRepository: MavenArtifactRepository + ) { val publishTasks = project.tasks .withType() .matching { it.repository == nexusRepository } @@ -121,6 +137,15 @@ class NexusPublishPlugin : Plugin { doFirst { logger.info("Uploading to {}", repository.url) } } } + closeTask.configure { + mustRunAfter(initializeTask) + mustRunAfter(publishTasks) + } + releaseTask.configure { + mustRunAfter(initializeTask) + mustRunAfter(closeTask) + mustRunAfter(publishTasks) + } } private fun getRepoUrl(nexusRepo: NexusRepository, extension: NexusPublishExtension): URI { diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt index 0562fcc8..b7b37696 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt @@ -38,4 +38,10 @@ open class NexusRepository @Inject constructor(val name: String, project: Projec } val stagingProfileId: Property = project.objects.property() + + val stagingRepositoryId: Property = project.objects.property() + + fun capitalizedName(): String { + return name.capitalize() + } } diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt new file mode 100644 index 00000000..3bf4cca4 --- /dev/null +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt @@ -0,0 +1,47 @@ +/* + * 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 io.github.gradlenexus.publishplugin.internal.NexusClient +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.TaskAction +import org.gradle.kotlin.dsl.property +import javax.inject.Inject + +@Suppress("UnstableApiUsage") +open class ReleaseNexusStagingRepository @Inject +constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository: NexusRepository) : + BaseOperationOnNexusStagingRepository(objects, extension, repository) { + + @get:Input + val stagingRepositoryId: Property = objects.property() + + init { + stagingRepositoryId.set(repository.stagingRepositoryId) + } + + @TaskAction + fun releaseStagingRepo() { + val client = NexusClient(serverUrl.get(), username.orNull, password.orNull, clientTimeout.orNull, connectTimeout.orNull) + val stagingProfileId = determineStagingProfileId(client) // TODO: Will it update value in extension? + logger.info("Releasing staging repository with id '{}' for stagingProfileId '{}'", stagingRepositoryId.get(), stagingProfileId) + 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 + } +} diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/NexusClient.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/NexusClient.kt index e698ebe8..1ca5184d 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/NexusClient.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/NexusClient.kt @@ -97,6 +97,28 @@ class NexusClient(private val baseUrl: URI, username: String?, password: String? } } + fun closeStagingRepository(stagingRepositoryId: String) { + try { + val response = api.closeStagingRepo(Dto(StagingRepositoryToTransit(listOf(stagingRepositoryId), "Closed by io.github.gradle-nexus.publish-plugin Gradle plugin"))).execute() + if (!response.isSuccessful) { + throw failure("close staging repository", response) + } + } catch (e: IOException) { + throw UncheckedIOException(e) + } + } + + fun releaseStagingRepository(stagingRepositoryId: String) { + try { + val response = api.releaseStagingRepo(Dto(StagingRepositoryToTransit(listOf(stagingRepositoryId), "Release by io.github.gradle-nexus.publish-plugin Gradle plugin"))).execute() + if (!response.isSuccessful) { + throw failure("release staging repository", response) + } + } catch (e: IOException) { + throw UncheckedIOException(e) + } + } + fun getStagingRepositoryUri(stagingRepositoryId: String): URI = URI.create("${baseUrl.toString().removeSuffix("/")}/staging/deployByRepositoryId/$stagingRepositoryId") @@ -115,6 +137,10 @@ class NexusClient(private val baseUrl: URI, username: String?, password: String? private interface NexusApi { + companion object { + private const val RELEASE_OPERATION_NAME_IN_NEXUS = "promote" // promote and release use the same operation, used body parameters matter + } + @get:Headers("Accept: application/json") @get:GET("staging/profiles") val stagingProfiles: Call>> @@ -122,6 +148,14 @@ class NexusClient(private val baseUrl: URI, username: String?, password: String? @Headers("Content-Type: application/json") @POST("staging/profiles/{stagingProfileId}/start") fun startStagingRepo(@Path("stagingProfileId") stagingProfileId: String, @Body description: Dto): Call> + + @Headers("Content-Type: application/json") + @POST("staging/bulk/close") + fun closeStagingRepo(@Body stagingRepositoryToClose: Dto): Call + + @Headers("Content-Type: application/json") + @POST("staging/bulk/$RELEASE_OPERATION_NAME_IN_NEXUS") + fun releaseStagingRepo(@Body stagingRepositoryToClose: Dto): Call } data class Dto(var data: T) @@ -131,4 +165,6 @@ class NexusClient(private val baseUrl: URI, username: String?, password: String? data class Description(val description: String) data class StagingRepository(var stagedRepositoryId: String) + + data class StagingRepositoryToTransit(val stagedRepositoryIds: List, val description: String, val autoDropAfterRelease: Boolean = true) } diff --git a/src/test/kotlin/io/github/gradlenexus/publishplugin/StagingPluginIntegrationTest.kt b/src/test/kotlin/io/github/gradlenexus/publishplugin/StagingPluginIntegrationTest.kt index f52eb4fc..3fead2cb 100644 --- a/src/test/kotlin/io/github/gradlenexus/publishplugin/StagingPluginIntegrationTest.kt +++ b/src/test/kotlin/io/github/gradlenexus/publishplugin/StagingPluginIntegrationTest.kt @@ -37,6 +37,7 @@ import ru.lanwen.wiremock.ext.WiremockResolver import ru.lanwen.wiremock.ext.WiremockResolver.Wiremock import java.net.URI +@Suppress("UnstableApiUsage") @ExtendWith(WiremockResolver::class) class StagingPluginIntegrationTest { diff --git a/src/test/kotlin/io/github/gradlenexus/publishplugin/TaskOrchestrationTest.kt b/src/test/kotlin/io/github/gradlenexus/publishplugin/TaskOrchestrationTest.kt new file mode 100644 index 00000000..fedf0df6 --- /dev/null +++ b/src/test/kotlin/io/github/gradlenexus/publishplugin/TaskOrchestrationTest.kt @@ -0,0 +1,109 @@ +/* + * 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.assertj.core.api.Assertions.assertThat +import org.gradle.api.Action +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.publish.PublishingExtension +import org.gradle.api.publish.maven.MavenPublication +import org.gradle.testfixtures.ProjectBuilder +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.io.TempDir +import java.nio.file.Path + +class TaskOrchestrationTest { + + @TempDir + lateinit var projectDir: Path + + private lateinit var project: Project + + @BeforeEach + internal fun setUp() { + project = ProjectBuilder.builder().withProjectDir(projectDir.toFile()).build() + } + + @Test + internal fun `close task should run after init`() { + initSingleProjectWithDefaultConfiguration() + assertGivenTaskMustRunAfterAnother("closeSonatypeStagingRepository", "initializeSonatypeStagingRepository") + } + + @Test + @Disabled("Broken - must run only after publishMavenJavaPublicationToSonatypeRepository not publishToSonatypeRepository") + internal fun `close task should run after related publish`() { + initSingleProjectWithDefaultConfiguration() + assertGivenTaskMustRunAfterAnother("closeSonatypeStagingRepository", "publishToSonatypeRepository") + } + + @Test + @Disabled("TODO") + internal fun `close task should not run after non-related publish`() {} + + @Test + @Disabled("TODO") + internal fun `close task should run after all related publish tasks in multi-project build`() {} + + @Test + internal fun `release task should run after init`() { + initSingleProjectWithDefaultConfiguration() + assertGivenTaskMustRunAfterAnother("releaseSonatypeStagingRepository", "initializeSonatypeStagingRepository") + } + + @Test + @Disabled("Broken - must run only after publishMavenJavaPublicationToSonatypeRepository not publishToSonatypeRepository") + internal fun `release task should run after related publish`() { + initSingleProjectWithDefaultConfiguration() + assertGivenTaskMustRunAfterAnother("releaseSonatypeStagingRepository", "publishToSonatypeRepository") + } + + @Test + internal fun `release task should run after close`() { + initSingleProjectWithDefaultConfiguration() + assertGivenTaskMustRunAfterAnother("releaseSonatypeStagingRepository", "closeSonatypeStagingRepository") + } + + private fun initSingleProjectWithDefaultConfiguration() { + project.apply(mapOf("plugin" to NexusPublishPlugin::class.java)) + val extension = project.extensions.findByType(NexusPublishExtension::class.java) + extension?.repositories(Action { + sonatype() + }) + val publishingExtension = project.extensions.findByType(PublishingExtension::class.java) + publishingExtension?.publications(Action { + create("mavenJava", MavenPublication::class.java) { +// from(components.java) //fails to compile + } + }) + } + + private fun assertGivenTaskMustRunAfterAnother(taskName: String, expectedPredecessorName: String) { + val task = getJustOneTaskByNameOrFail(taskName) + val expectedPredecessor = getJustOneTaskByNameOrFail(expectedPredecessorName) + assertThat(task.mustRunAfter.getDependencies(task)).contains(expectedPredecessor) + } + + private fun getJustOneTaskByNameOrFail(taskName: String): Task { + val tasks = project.getTasksByName(taskName, true) // forces project evaluation" + assertThat(tasks.size).describedAs("Expected just one task: $taskName. Found: ${project.tasks}").isOne() + return tasks.first() + } +} From 225637e1ab68a9543dc4bacd30af8f48cca2fb4b Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 18 Oct 2019 19:42:59 +0200 Subject: [PATCH 03/18] Use Kotlin DSL extensions --- .../publishplugin/TaskOrchestrationTest.kt | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/test/kotlin/io/github/gradlenexus/publishplugin/TaskOrchestrationTest.kt b/src/test/kotlin/io/github/gradlenexus/publishplugin/TaskOrchestrationTest.kt index fedf0df6..2227d79b 100644 --- a/src/test/kotlin/io/github/gradlenexus/publishplugin/TaskOrchestrationTest.kt +++ b/src/test/kotlin/io/github/gradlenexus/publishplugin/TaskOrchestrationTest.kt @@ -22,6 +22,10 @@ import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.publish.PublishingExtension import org.gradle.api.publish.maven.MavenPublication +import org.gradle.kotlin.dsl.apply +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.create +import org.gradle.kotlin.dsl.get import org.gradle.testfixtures.ProjectBuilder import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Disabled @@ -82,17 +86,15 @@ class TaskOrchestrationTest { } private fun initSingleProjectWithDefaultConfiguration() { - project.apply(mapOf("plugin" to NexusPublishPlugin::class.java)) - val extension = project.extensions.findByType(NexusPublishExtension::class.java) - extension?.repositories(Action { - sonatype() - }) - val publishingExtension = project.extensions.findByType(PublishingExtension::class.java) - publishingExtension?.publications(Action { - create("mavenJava", MavenPublication::class.java) { -// from(components.java) //fails to compile + project.apply() + project.extensions.configure { + repositories.sonatype() + } + project.extensions.configure { + publications.create("mavenJava") { + from(project.components["java"]) } - }) + } } private fun assertGivenTaskMustRunAfterAnother(taskName: String, expectedPredecessorName: String) { @@ -102,7 +104,7 @@ class TaskOrchestrationTest { } private fun getJustOneTaskByNameOrFail(taskName: String): Task { - val tasks = project.getTasksByName(taskName, true) // forces project evaluation" + val tasks = project.getTasksByName(taskName, true) // forces project evaluation assertThat(tasks.size).describedAs("Expected just one task: $taskName. Found: ${project.tasks}").isOne() return tasks.first() } From 50a46d76a285733a8842017c26ba934d80a8af11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Zaj=C4=85czkowski?= Date: Fri, 18 Oct 2019 19:51:16 +0200 Subject: [PATCH 04/18] Apply also java plugin in tests --- .../github/gradlenexus/publishplugin/TaskOrchestrationTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/kotlin/io/github/gradlenexus/publishplugin/TaskOrchestrationTest.kt b/src/test/kotlin/io/github/gradlenexus/publishplugin/TaskOrchestrationTest.kt index 2227d79b..98ddf58f 100644 --- a/src/test/kotlin/io/github/gradlenexus/publishplugin/TaskOrchestrationTest.kt +++ b/src/test/kotlin/io/github/gradlenexus/publishplugin/TaskOrchestrationTest.kt @@ -17,7 +17,6 @@ package io.github.gradlenexus.publishplugin import org.assertj.core.api.Assertions.assertThat -import org.gradle.api.Action import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.publish.PublishingExtension @@ -86,6 +85,7 @@ class TaskOrchestrationTest { } private fun initSingleProjectWithDefaultConfiguration() { + project.apply(plugin = "java") project.apply() project.extensions.configure { repositories.sonatype() From a958502292fd1932b8830f42bd7f6752697b545a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Zaj=C4=85czkowski?= Date: Sat, 19 Oct 2019 16:11:56 +0200 Subject: [PATCH 05/18] [#4] Simplify IO error handling --- .../publishplugin/internal/NexusClient.kt | 65 +++++++------------ 1 file changed, 25 insertions(+), 40 deletions(-) diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/NexusClient.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/NexusClient.kt index 1ca5184d..9064e54d 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/NexusClient.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/NexusClient.kt @@ -64,64 +64,49 @@ class NexusClient(private val baseUrl: URI, username: String?, password: String? } fun findStagingProfileId(packageGroup: String): String? { - try { - val response = api.stagingProfiles.execute() - if (!response.isSuccessful) { - throw failure("load staging profiles", response) - } - return response.body() - ?.data - ?.filter { profile -> - // profile.name either matches exactly - // or it is a prefix of a packageGroup - packageGroup.startsWith(profile.name) && - (packageGroup.length == profile.name.length || - packageGroup[profile.name.length] == '.') - } - ?.maxBy { it.name.length } - ?.id - } catch (e: IOException) { - throw UncheckedIOException(e) + val response = api.stagingProfiles.execute() + if (!response.isSuccessful) { + throw failure("load staging profiles", response) } + return response.body() + ?.data + ?.filter { profile -> + // profile.name either matches exactly + // or it is a prefix of a packageGroup + packageGroup.startsWith(profile.name) && + (packageGroup.length == profile.name.length || + packageGroup[profile.name.length] == '.') + } + ?.maxBy { it.name.length } + ?.id } fun createStagingRepository(stagingProfileId: String): String { - try { - val response = api.startStagingRepo(stagingProfileId, Dto(Description("Created by io.github.gradle-nexus.publish-plugin Gradle plugin"))).execute() - if (!response.isSuccessful) { - throw failure("create staging repository", response) - } - return response.body()?.data?.stagedRepositoryId ?: throw RuntimeException("No response body") - } catch (e: IOException) { - throw UncheckedIOException(e) + val response = api.startStagingRepo(stagingProfileId, Dto(Description("Created by io.github.gradle-nexus.publish-plugin Gradle plugin"))).execute() + if (!response.isSuccessful) { + throw failure("create staging repository", response) } + return response.body()?.data?.stagedRepositoryId ?: throw RuntimeException("No response body") } fun closeStagingRepository(stagingRepositoryId: String) { - try { - val response = api.closeStagingRepo(Dto(StagingRepositoryToTransit(listOf(stagingRepositoryId), "Closed by io.github.gradle-nexus.publish-plugin Gradle plugin"))).execute() - if (!response.isSuccessful) { - throw failure("close staging repository", response) - } - } catch (e: IOException) { - throw UncheckedIOException(e) + val response = api.closeStagingRepo(Dto(StagingRepositoryToTransit(listOf(stagingRepositoryId), "Closed by io.github.gradle-nexus.publish-plugin Gradle plugin"))).execute() + if (!response.isSuccessful) { + throw failure("close staging repository", response) } } fun releaseStagingRepository(stagingRepositoryId: String) { - try { - val response = api.releaseStagingRepo(Dto(StagingRepositoryToTransit(listOf(stagingRepositoryId), "Release by io.github.gradle-nexus.publish-plugin Gradle plugin"))).execute() - if (!response.isSuccessful) { - throw failure("release staging repository", response) - } - } catch (e: IOException) { - throw UncheckedIOException(e) + val response = api.releaseStagingRepo(Dto(StagingRepositoryToTransit(listOf(stagingRepositoryId), "Release by io.github.gradle-nexus.publish-plugin Gradle plugin"))).execute() + if (!response.isSuccessful) { + throw failure("release staging repository", response) } } fun getStagingRepositoryUri(stagingRepositoryId: String): URI = URI.create("${baseUrl.toString().removeSuffix("/")}/staging/deployByRepositoryId/$stagingRepositoryId") + // TODO: Cover all API calls with unified error handling (including unexpected IOExceptions) private fun failure(action: String, response: Response<*>): RuntimeException { var message = "Failed to " + action + ", server responded with status code " + response.code() val errorBody = response.errorBody() From 00d875edd301efa20b9b0543096df1f18e593516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Zaj=C4=85czkowski?= Date: Sat, 19 Oct 2019 16:12:49 +0200 Subject: [PATCH 06/18] [#4] Review suggestions --- .../publishplugin/InitializeNexusStagingRepository.kt | 4 ++-- .../io/github/gradlenexus/publishplugin/NexusRepository.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt index 8186dfbf..ed8c224f 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt @@ -46,7 +46,7 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository val stagingProfileId = determineStagingProfileId(client) // TODO: It would be good to keep/cache value in Extension/Repository logger.info("Creating staging repository for stagingProfileId '{}'", stagingProfileId) val stagingRepositoryIdAsString = client.createStagingRepository(stagingProfileId) - keppStagingRepositoyIdInExtension(stagingRepositoryIdAsString) + keepStagingRepositoyIdInExtension(stagingRepositoryIdAsString) project.rootProject.plugins.withId("io.codearte.nexus-staging") { val nexusStagingExtension = project.rootProject.the() @@ -70,7 +70,7 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository repository.setUrl(url.toString()) } - private fun keppStagingRepositoyIdInExtension(stagingRepositoryIdAsString: String) { + private fun keepStagingRepositoyIdInExtension(stagingRepositoryIdAsString: String) { stagingRepositoryId.set(stagingRepositoryIdAsString) } } diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt index b7b37696..c54bce55 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt @@ -41,7 +41,7 @@ open class NexusRepository @Inject constructor(val name: String, project: Projec val stagingRepositoryId: Property = project.objects.property() - fun capitalizedName(): String { + internal fun capitalizedName(): String { return name.capitalize() } } From afbb6f426c1b63a397d53cd39a5ff8d0534bfd15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Zaj=C4=85czkowski?= Date: Mon, 4 Nov 2019 21:00:22 +0100 Subject: [PATCH 07/18] [#4] Review suggestions --- .stutter/java11.lock | 4 ---- build.gradle.kts | 3 --- 2 files changed, 7 deletions(-) delete mode 100644 .stutter/java11.lock diff --git a/.stutter/java11.lock b/.stutter/java11.lock deleted file mode 100644 index 13ae7251..00000000 --- a/.stutter/java11.lock +++ /dev/null @@ -1,4 +0,0 @@ -# DO NOT MODIFY: Generated by Stutter plugin. -4.10.3 -5.0 -5.6.3 diff --git a/build.gradle.kts b/build.gradle.kts index ee812d3f..c9c72b21 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -102,9 +102,6 @@ stutter { java(8) { compatibleRange("4.10") } - java(11) { - compatibleRange("4.10") - } } configurations { From 05b4e81691e122b24d279c1495f622105086cbbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Zaj=C4=85czkowski?= Date: Mon, 4 Nov 2019 21:02:41 +0100 Subject: [PATCH 08/18] [#4] Rename base task class --- ...agingRepository.kt => AbstractNexusStagingRepositoryTask.kt} | 2 +- .../gradlenexus/publishplugin/CloseNexusStagingRepository.kt | 2 +- .../publishplugin/InitializeNexusStagingRepository.kt | 2 +- .../gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename src/main/kotlin/io/github/gradlenexus/publishplugin/{BaseOperationOnNexusStagingRepository.kt => AbstractNexusStagingRepositoryTask.kt} (98%) diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/BaseOperationOnNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt similarity index 98% rename from src/main/kotlin/io/github/gradlenexus/publishplugin/BaseOperationOnNexusStagingRepository.kt rename to src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt index 6d0f6383..6988d459 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/BaseOperationOnNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt @@ -30,7 +30,7 @@ import java.time.Duration import javax.inject.Inject @Suppress("UnstableApiUsage") -abstract class BaseOperationOnNexusStagingRepository @Inject +abstract class AbstractNexusStagingRepositoryTask @Inject constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository: NexusRepository) : DefaultTask() { @get:Input diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt index eaaec2d5..fe089539 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt @@ -27,7 +27,7 @@ import javax.inject.Inject @Suppress("UnstableApiUsage") open class CloseNexusStagingRepository @Inject constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository: NexusRepository) : - BaseOperationOnNexusStagingRepository(objects, extension, repository) { + AbstractNexusStagingRepositoryTask(objects, extension, repository) { @get:Input val stagingRepositoryId: Property = objects.property() diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt index ed8c224f..0a6b9226 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt @@ -30,7 +30,7 @@ import javax.inject.Inject @Suppress("UnstableApiUsage") open class InitializeNexusStagingRepository @Inject constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository: NexusRepository, private val serverUrlToStagingRepoUrl: MutableMap) : - BaseOperationOnNexusStagingRepository(objects, extension, repository) { + AbstractNexusStagingRepositoryTask(objects, extension, repository) { private val stagingRepositoryId: Property = repository.stagingRepositoryId diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt index 3bf4cca4..3221c75a 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt @@ -27,7 +27,7 @@ import javax.inject.Inject @Suppress("UnstableApiUsage") open class ReleaseNexusStagingRepository @Inject constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository: NexusRepository) : - BaseOperationOnNexusStagingRepository(objects, extension, repository) { + AbstractNexusStagingRepositoryTask(objects, extension, repository) { @get:Input val stagingRepositoryId: Property = objects.property() From 2f10cfc8685e70cebef29a058f46b9cd07d8a1ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Zaj=C4=85czkowski?= Date: Mon, 4 Nov 2019 22:20:00 +0100 Subject: [PATCH 09/18] [#4] Simplify InitializeNexusStagingRepository By keeping a reference to NexusRepository. --- .../publishplugin/AbstractNexusStagingRepositoryTask.kt | 7 +++++++ .../publishplugin/InitializeNexusStagingRepository.kt | 9 +-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt index 6988d459..b71b3271 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt @@ -61,6 +61,8 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository @get:Internal protected val connectTimeout: Property = objects.property() + private val repository: Property = objects.property() + init { serverUrl.set(repository.nexusUrl) username.set(repository.username) @@ -70,6 +72,7 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository repositoryName.set(repository.name) clientTimeout.set(extension.clientTimeout) connectTimeout.set(extension.connectTimeout) + this.repository.set(repository) this.onlyIf { extension.useStaging.getOrElse(false) } } @@ -83,4 +86,8 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository } return stagingProfileId } + + protected fun keepStagingRepositoryIdInExtension(stagingRepositoryIdAsString: String) { + repository.get().stagingRepositoryId.set(stagingRepositoryIdAsString) + } } diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt index 0a6b9226..e3ef7ace 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt @@ -20,7 +20,6 @@ import io.codearte.gradle.nexus.NexusStagingExtension import io.github.gradlenexus.publishplugin.internal.NexusClient import org.gradle.api.artifacts.repositories.MavenArtifactRepository import org.gradle.api.model.ObjectFactory -import org.gradle.api.provider.Property import org.gradle.api.publish.PublishingExtension import org.gradle.api.tasks.TaskAction import org.gradle.kotlin.dsl.the @@ -32,8 +31,6 @@ open class InitializeNexusStagingRepository @Inject constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository: NexusRepository, private val serverUrlToStagingRepoUrl: MutableMap) : AbstractNexusStagingRepositoryTask(objects, extension, repository) { - private val stagingRepositoryId: Property = repository.stagingRepositoryId - @TaskAction fun createStagingRepoAndReplacePublishingRepoUrl() { val url = createStagingRepo() @@ -46,7 +43,7 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository val stagingProfileId = determineStagingProfileId(client) // TODO: It would be good to keep/cache value in Extension/Repository logger.info("Creating staging repository for stagingProfileId '{}'", stagingProfileId) val stagingRepositoryIdAsString = client.createStagingRepository(stagingProfileId) - keepStagingRepositoyIdInExtension(stagingRepositoryIdAsString) + keepStagingRepositoryIdInExtension(stagingRepositoryIdAsString) project.rootProject.plugins.withId("io.codearte.nexus-staging") { val nexusStagingExtension = project.rootProject.the() @@ -69,8 +66,4 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository logger.info("Updating URL of publishing repository '{}' to '{}'", repository.name, url) repository.setUrl(url.toString()) } - - private fun keepStagingRepositoyIdInExtension(stagingRepositoryIdAsString: String) { - stagingRepositoryId.set(stagingRepositoryIdAsString) - } } From 6f2c93cf39c8f990efb9d70ae3cfe99c7b6f214d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Zaj=C4=85czkowski?= Date: Tue, 5 Nov 2019 22:00:06 +0100 Subject: [PATCH 10/18] [#4] @Option for stagingRepositoryId in close and release --- .../gradlenexus/publishplugin/NexusPublishPluginTests.kt | 8 ++++++++ .../publishplugin/CloseNexusStagingRepository.kt | 3 +++ .../publishplugin/ReleaseNexusStagingRepository.kt | 3 +++ 3 files changed, 14 insertions(+) diff --git a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt index cfdcd7e4..4fcb0fb8 100644 --- a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt +++ b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt @@ -683,6 +683,14 @@ class NexusPublishPluginTests { assertReleaseOfStagingRepo(server) } + @Test + @Disabled("TODO") + fun `should allow to override stagingRepositoryId to close from command line`() {} + + @Test + @Disabled("TODO") + fun `should allow to override stagingRepositoryId to release from command line`() {} + // 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/CloseNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt index fe089539..e3955247 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt @@ -21,6 +21,7 @@ import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Property 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 import javax.inject.Inject @@ -30,9 +31,11 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository AbstractNexusStagingRepositoryTask(objects, extension, repository) { @get:Input + @get:Option(option = "stagingRepositoryId", description = "stagingRepositoryId to close") val stagingRepositoryId: Property = objects.property() init { + // TODO: Replace with convention() once only Gradle 5.1+ is supported stagingRepositoryId.set(repository.stagingRepositoryId) } diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt index 3221c75a..a7dd1a0e 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt @@ -21,6 +21,7 @@ import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Property 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 import javax.inject.Inject @@ -30,9 +31,11 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository AbstractNexusStagingRepositoryTask(objects, extension, repository) { @get:Input + @get:Option(option = "stagingRepositoryId", description = "stagingRepositoryId to release") val stagingRepositoryId: Property = objects.property() init { + // TODO: Replace with convention() once only Gradle 5.1+ is supported stagingRepositoryId.set(repository.stagingRepositoryId) } From ef5a14fcb3af590889e4bea6174dba08b282ba47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Zaj=C4=85czkowski?= Date: Tue, 5 Nov 2019 22:43:05 +0100 Subject: [PATCH 11/18] Bump spotless version to effectively enable disabled_rules See: https://github.com/diffplug/spotless/issues/476 As a side effect import-ordering has been disabled to do not break the build. It changed to fail after upgrade. I don't want to mix that PR with global import reordering. --- build.gradle.kts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index c9c72b21..61b3d73b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ plugins { `maven-publish` id("com.gradle.build-scan") version "2.4.2" id("com.gradle.plugin-publish") version "0.10.1" - id("com.diffplug.gradle.spotless") version "3.24.2" + id("com.diffplug.gradle.spotless") version "3.25.0" id("com.github.johnrengelman.shadow") version "5.1.0" id("org.jetbrains.gradle.plugin.idea-ext") id("com.github.ben-manes.versions") version "0.25.0" @@ -51,7 +51,8 @@ repositories { val licenseHeaderFile = file("gradle/license-header.txt") spotless { kotlin { - ktlint().userData(mapOf("disabled_rules" to "comment-spacing")) + //"import-ordering" required here as it started to fail after spotless plugin upgrade to 0.35.0 - resolve in separate PR + ktlint().userData(mapOf("disabled_rules" to "comment-spacing,import-ordering")) licenseHeaderFile(licenseHeaderFile) } } From 092b31737e5d3bda9bceff96fe468bfa243ac7a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Zaj=C4=85czkowski?= Date: Tue, 5 Nov 2019 22:46:03 +0100 Subject: [PATCH 12/18] [#4] Fix issue with imports --- .../github/gradlenexus/publishplugin/NexusPublishPluginTests.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt index 4fcb0fb8..f0cf9b22 100644 --- a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt +++ b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt @@ -39,6 +39,7 @@ import org.gradle.util.GradleVersion import org.gradle.util.VersionNumber import org.junit.jupiter.api.Assumptions.assumeTrue import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.junit.jupiter.api.io.TempDir From 2531bacdcaa6c2bbd6aaad5f05854eab18654796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Zaj=C4=85czkowski?= Date: Fri, 27 Dec 2019 15:25:26 +0100 Subject: [PATCH 13/18] [#4] Reuse common properties from NexUsRepository in Task --- .../AbstractNexusStagingRepositoryTask.kt | 30 +++---------------- .../CloseNexusStagingRepository.kt | 2 +- .../DefaultNexusRepositoryContainer.kt | 1 + .../InitializeNexusStagingRepository.kt | 6 ++-- .../publishplugin/NexusRepository.kt | 14 ++++++++- .../ReleaseNexusStagingRepository.kt | 2 +- 6 files changed, 23 insertions(+), 32 deletions(-) diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt index b71b3271..3959b1b3 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt @@ -25,7 +25,6 @@ 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 java.time.Duration import javax.inject.Inject @@ -33,43 +32,22 @@ import javax.inject.Inject abstract class AbstractNexusStagingRepositoryTask @Inject constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository: NexusRepository) : DefaultTask() { - @get:Input - protected val serverUrl: Property = objects.property() - - @get:Optional - @get:Input - protected val username: Property = objects.property() - - @get:Optional - @get:Input - protected val password: Property = objects.property() - @get:Optional @get:Input protected val packageGroup: Property = objects.property() - @get:Optional - @get:Input - protected val stagingProfileId: Property = objects.property() - - @get:Input - protected val repositoryName: Property = objects.property() - @get:Internal protected val clientTimeout: Property = objects.property() @get:Internal protected val connectTimeout: Property = objects.property() - private val repository: Property = objects.property() + //TODO: Expose externally as interface with getters only + //@get:Nested //FIXME: @Nested switch values in NexusRepository to state = Final which prevent settings stagingRepositoryId in init task + protected val repository: Property = objects.property() init { - serverUrl.set(repository.nexusUrl) - username.set(repository.username) - password.set(repository.password) packageGroup.set(extension.packageGroup) - stagingProfileId.set(repository.stagingProfileId) - repositoryName.set(repository.name) clientTimeout.set(extension.clientTimeout) connectTimeout.set(extension.connectTimeout) this.repository.set(repository) @@ -77,7 +55,7 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository } protected fun determineStagingProfileId(client: NexusClient): String { - var stagingProfileId = stagingProfileId.orNull + var stagingProfileId = repository.get().stagingProfileId.orNull if (stagingProfileId == null) { val packageGroup = packageGroup.get() logger.debug("No stagingProfileId set, querying for packageGroup '{}'", packageGroup) diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt index e3955247..eca2c27d 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt @@ -41,7 +41,7 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository @TaskAction fun closeStagingRepo() { - val client = NexusClient(serverUrl.get(), username.orNull, password.orNull, clientTimeout.orNull, connectTimeout.orNull) + val client = NexusClient(repository.get().nexusUrl.get(), repository.get().username.orNull, repository.get().password.orNull, clientTimeout.orNull, connectTimeout.orNull) val stagingProfileId = determineStagingProfileId(client) logger.info("Closing staging repository with id '{}' for stagingProfileId '{}'", stagingRepositoryId.get(), stagingProfileId) client.closeStagingRepository(stagingRepositoryId.get()) diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/DefaultNexusRepositoryContainer.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/DefaultNexusRepositoryContainer.kt index 8e6bf8ff..60726af9 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/DefaultNexusRepositoryContainer.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/DefaultNexusRepositoryContainer.kt @@ -23,6 +23,7 @@ import org.gradle.api.internal.NamedDomainObjectContainerConfigureDelegate import org.gradle.util.ConfigureUtil import java.net.URI +@Suppress("UnstableApiUsage") internal class DefaultNexusRepositoryContainer(delegate: NamedDomainObjectContainer) : NexusRepositoryContainer, NamedDomainObjectContainer by delegate { override fun sonatype(): NexusRepository = sonatype {} diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt index e3ef7ace..87f94f30 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt @@ -38,8 +38,8 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository } internal fun createStagingRepo(): URI { - return serverUrlToStagingRepoUrl.computeIfAbsent(serverUrl.get()) { serverUrl -> - val client = NexusClient(serverUrl, username.orNull, password.orNull, clientTimeout.orNull, connectTimeout.orNull) + 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 = determineStagingProfileId(client) // TODO: It would be good to keep/cache value in Extension/Repository logger.info("Creating staging repository for stagingProfileId '{}'", stagingProfileId) val stagingRepositoryIdAsString = client.createStagingRepository(stagingProfileId) @@ -62,7 +62,7 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository private fun replacePublishingRepoUrl(url: URI) { val publishing = project.the() - val repository = publishing.repositories.getByName(repositoryName.get()) as MavenArtifactRepository + val repository = publishing.repositories.getByName(repository.get().name) as MavenArtifactRepository logger.info("Updating URL of publishing repository '{}' to '{}'", repository.name, url) repository.setUrl(url.toString()) } diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt index c54bce55..41fe4e71 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt @@ -18,27 +18,39 @@ 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.Optional import org.gradle.kotlin.dsl.property import java.net.URI import javax.inject.Inject @Suppress("UnstableApiUsage") -open class NexusRepository @Inject constructor(val name: String, project: Project) { +open class NexusRepository @Inject constructor(@get:Input val name: String, project: Project) { + @get:Input val nexusUrl: Property = project.objects.property() + @get:Input val snapshotRepositoryUrl: Property = project.objects.property() + @get:Optional + @get:Input val username: Property = project.objects.property().apply { set(project.provider { project.findProperty("${name}Username") as? String }) } + @get:Optional + @get:Input val password: Property = project.objects.property().apply { set(project.provider { project.findProperty("${name}Password") as? String }) } + @get:Optional + @get:Input val stagingProfileId: Property = project.objects.property() + @get:Optional + @get:Input val stagingRepositoryId: Property = project.objects.property() internal fun capitalizedName(): String { diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt index a7dd1a0e..5b3306ed 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt @@ -41,7 +41,7 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository @TaskAction fun releaseStagingRepo() { - val client = NexusClient(serverUrl.get(), username.orNull, password.orNull, clientTimeout.orNull, connectTimeout.orNull) + val client = NexusClient(repository.get().nexusUrl.get(), repository.get().username.orNull, repository.get().password.orNull, clientTimeout.orNull, connectTimeout.orNull) val stagingProfileId = determineStagingProfileId(client) // TODO: Will it update value in extension? logger.info("Releasing staging repository with id '{}' for stagingProfileId '{}'", stagingRepositoryId.get(), stagingProfileId) client.releaseStagingRepository(stagingRepositoryId.get()) From 716a6b1fb6f7b38262bc98d2a48dbb06c22830ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Zaj=C4=85czkowski?= Date: Fri, 3 Jan 2020 15:19:29 +0100 Subject: [PATCH 14/18] [#4] Workaround problem with finalized properties in task --- .../publishplugin/NexusPublishPluginTests.kt | 6 ++++ .../AbstractNexusStagingRepositoryTask.kt | 5 +-- .../CloseNexusStagingRepository.kt | 14 ++++---- .../publishplugin/NexusRepository.kt | 6 ++-- .../publishplugin/NexusStagingRepository.kt | 34 +++++++++++++++++++ .../ReleaseNexusStagingRepository.kt | 15 ++++---- 6 files changed, 63 insertions(+), 17 deletions(-) create mode 100644 src/main/kotlin/io/github/gradlenexus/publishplugin/NexusStagingRepository.kt diff --git a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt index f0cf9b22..880d6045 100644 --- a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt +++ b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt @@ -144,11 +144,13 @@ class NexusPublishPluginTests { repositories { myNexus { nexusUrl = uri('${server.baseUrl()}') + snapshotRepositoryUrl = uri('${server.baseUrl()}/snapshots/') username = 'username' password = 'password' } someOtherNexus { nexusUrl = uri('http://example.org') + snapshotRepositoryUrl = uri('http://example.org/snapshots/') } } } @@ -301,6 +303,7 @@ class NexusPublishPluginTests { repositories { myNexus { nexusUrl = uri('${server.baseUrl()}/a/') + snapshotRepositoryUrl = uri('${server.baseUrl()}/a/snapshots/') stagingProfileId = 'profile-a' username = 'username' password = 'password' @@ -313,6 +316,7 @@ class NexusPublishPluginTests { repositories { named('myNexus').configure { nexusUrl = uri('${server.baseUrl()}/b/') + snapshotRepositoryUrl = uri('${server.baseUrl()}/b/snapshots/') stagingProfileId = 'profile-b' } } @@ -426,6 +430,7 @@ class NexusPublishPluginTests { repositories { myNexus { nexusUrl = uri('${server.baseUrl()}') + snapshotRepositoryUrl = uri('${server.baseUrl()}/snapshots/') } } } @@ -467,6 +472,7 @@ class NexusPublishPluginTests { repositories { myNexus { nexusUrl = uri('${server.baseUrl()}') + snapshotRepositoryUrl = uri('${server.baseUrl()}/snapshots/') username = 'username' password = 'password' } diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt index 3959b1b3..a15247da 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt @@ -23,6 +23,7 @@ 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 @@ -43,7 +44,7 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository protected val connectTimeout: Property = objects.property() //TODO: Expose externally as interface with getters only - //@get:Nested //FIXME: @Nested switch values in NexusRepository to state = Final which prevent settings stagingRepositoryId in init task + @get:Nested protected val repository: Property = objects.property() init { @@ -66,6 +67,6 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository } protected fun keepStagingRepositoryIdInExtension(stagingRepositoryIdAsString: String) { - repository.get().stagingRepositoryId.set(stagingRepositoryIdAsString) + repository.get().stagingRepository.set(NexusStagingRepository(stagingRepositoryIdAsString, project)) } } diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt index eca2c27d..a0114e39 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt @@ -20,8 +20,8 @@ import io.github.gradlenexus.publishplugin.internal.NexusClient import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Property import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Nested import org.gradle.api.tasks.TaskAction -import org.gradle.api.tasks.options.Option import org.gradle.kotlin.dsl.property import javax.inject.Inject @@ -31,20 +31,22 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository AbstractNexusStagingRepositoryTask(objects, extension, repository) { @get:Input - @get:Option(option = "stagingRepositoryId", description = "stagingRepositoryId to close") - val stagingRepositoryId: Property = objects.property() + @get:Nested + val stagingRepository: Property = objects.property() + + //TODO: Bring back an ability to define stagingRepositoryId from a command line (and propagate that value back to NexusStagingRepository for Release*) init { // TODO: Replace with convention() once only Gradle 5.1+ is supported - stagingRepositoryId.set(repository.stagingRepositoryId) + stagingRepository.set(repository.stagingRepository) } @TaskAction fun closeStagingRepo() { val client = NexusClient(repository.get().nexusUrl.get(), repository.get().username.orNull, repository.get().password.orNull, clientTimeout.orNull, connectTimeout.orNull) val stagingProfileId = determineStagingProfileId(client) - logger.info("Closing staging repository with id '{}' for stagingProfileId '{}'", stagingRepositoryId.get(), stagingProfileId) - client.closeStagingRepository(stagingRepositoryId.get()) + logger.info("Closing staging repository with id '{}' for stagingProfileId '{}'", stagingRepository.get().stagingRepositoryId.get(), stagingProfileId) + client.closeStagingRepository(stagingRepository.get().stagingRepositoryId.get()) // 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/NexusRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt index 41fe4e71..a9b91dc9 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt @@ -19,6 +19,7 @@ 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 @@ -49,9 +50,8 @@ open class NexusRepository @Inject constructor(@get:Input val name: String, proj @get:Input val stagingProfileId: Property = project.objects.property() - @get:Optional - @get:Input - val stagingRepositoryId: Property = project.objects.property() + @get:Internal + val stagingRepository: Property = project.objects.property() internal fun capitalizedName(): String { return name.capitalize() diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusStagingRepository.kt new file mode 100644 index 00000000..88ff1dd8 --- /dev/null +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusStagingRepository.kt @@ -0,0 +1,34 @@ +/* + * 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.Project +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Internal +import org.gradle.kotlin.dsl.property +import javax.inject.Inject + +@Suppress("UnstableApiUsage") +open class NexusStagingRepository @Inject constructor(stagingRepositoryIdAsString: String, project: Project) { + + @Internal + val stagingRepositoryId: Property = project.objects.property() + + init { + stagingRepositoryId.set(stagingRepositoryIdAsString) + } +} diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt index 5b3306ed..7536f578 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt @@ -20,31 +20,34 @@ import io.github.gradlenexus.publishplugin.internal.NexusClient import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Property import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Nested import org.gradle.api.tasks.TaskAction -import org.gradle.api.tasks.options.Option import org.gradle.kotlin.dsl.property import javax.inject.Inject +//TODO: Extract the same logic from CloseNexusStagingRepository and ReleaseNexusStagingRepository @Suppress("UnstableApiUsage") open class ReleaseNexusStagingRepository @Inject constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository: NexusRepository) : AbstractNexusStagingRepositoryTask(objects, extension, repository) { @get:Input - @get:Option(option = "stagingRepositoryId", description = "stagingRepositoryId to release") - val stagingRepositoryId: Property = objects.property() + @get:Nested + val stagingRepository: Property = objects.property() + + //TODO: Bring back an ability to define stagingRepositoryId from a command line init { // TODO: Replace with convention() once only Gradle 5.1+ is supported - stagingRepositoryId.set(repository.stagingRepositoryId) + stagingRepository.set(repository.stagingRepository) } @TaskAction fun releaseStagingRepo() { val client = NexusClient(repository.get().nexusUrl.get(), repository.get().username.orNull, repository.get().password.orNull, clientTimeout.orNull, connectTimeout.orNull) val stagingProfileId = determineStagingProfileId(client) // TODO: Will it update value in extension? - logger.info("Releasing staging repository with id '{}' for stagingProfileId '{}'", stagingRepositoryId.get(), stagingProfileId) - client.releaseStagingRepository(stagingRepositoryId.get()) + logger.info("Releasing staging repository with id '{}' for stagingProfileId '{}'", stagingRepository.get().stagingRepositoryId.get(), stagingProfileId) + client.releaseStagingRepository(stagingRepository.get().stagingRepositoryId.get()) // TODO: Broken with real Nexus - waiting for effective execution is also required https://github.com/gradle-nexus/publish-plugin/issues/7 } } From edb31ee925d670c361c7f7073d23798a98dd1f1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Zaj=C4=85czkowski?= Date: Fri, 3 Jan 2020 15:49:40 +0100 Subject: [PATCH 15/18] [#4] Simplify NexusStagingRepository class --- .../publishplugin/NexusPublishPluginTests.kt | 1 + .../AbstractNexusStagingRepositoryTask.kt | 2 +- .../CloseNexusStagingRepository.kt | 6 ++---- .../publishplugin/NexusStagingRepository.kt | 17 ++--------------- .../ReleaseNexusStagingRepository.kt | 6 ++---- 5 files changed, 8 insertions(+), 24 deletions(-) diff --git a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt index 880d6045..b835e8ea 100644 --- a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt +++ b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt @@ -520,6 +520,7 @@ class NexusPublishPluginTests { repositories { myNexus { nexusUrl = uri('http://$nonRoutableAddress/') + snapshotRepositoryUrl = uri('$nonRoutableAddress/snapshots/') username = 'username' password = 'password' } diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt index a15247da..8465974c 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt @@ -67,6 +67,6 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository } protected fun keepStagingRepositoryIdInExtension(stagingRepositoryIdAsString: String) { - repository.get().stagingRepository.set(NexusStagingRepository(stagingRepositoryIdAsString, project)) + repository.get().stagingRepository.set(NexusStagingRepository(stagingRepositoryIdAsString)) } } diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt index a0114e39..1e62f28d 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt @@ -19,7 +19,6 @@ 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.Input import org.gradle.api.tasks.Nested import org.gradle.api.tasks.TaskAction import org.gradle.kotlin.dsl.property @@ -30,7 +29,6 @@ open class CloseNexusStagingRepository @Inject constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository: NexusRepository) : AbstractNexusStagingRepositoryTask(objects, extension, repository) { - @get:Input @get:Nested val stagingRepository: Property = objects.property() @@ -45,8 +43,8 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository fun closeStagingRepo() { val client = NexusClient(repository.get().nexusUrl.get(), repository.get().username.orNull, repository.get().password.orNull, clientTimeout.orNull, connectTimeout.orNull) val stagingProfileId = determineStagingProfileId(client) - logger.info("Closing staging repository with id '{}' for stagingProfileId '{}'", stagingRepository.get().stagingRepositoryId.get(), stagingProfileId) - client.closeStagingRepository(stagingRepository.get().stagingRepositoryId.get()) + logger.info("Closing staging repository with id '{}' for stagingProfileId '{}'", stagingRepository.get().id, stagingProfileId) + client.closeStagingRepository(stagingRepository.get().id) // 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/NexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusStagingRepository.kt index 88ff1dd8..2d0108d5 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusStagingRepository.kt @@ -16,19 +16,6 @@ package io.github.gradlenexus.publishplugin -import org.gradle.api.Project -import org.gradle.api.provider.Property -import org.gradle.api.tasks.Internal -import org.gradle.kotlin.dsl.property -import javax.inject.Inject +import org.gradle.api.tasks.Input -@Suppress("UnstableApiUsage") -open class NexusStagingRepository @Inject constructor(stagingRepositoryIdAsString: String, project: Project) { - - @Internal - val stagingRepositoryId: Property = project.objects.property() - - init { - stagingRepositoryId.set(stagingRepositoryIdAsString) - } -} +open class NexusStagingRepository constructor(@get:Input val id: String) diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt index 7536f578..e454bb53 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt @@ -19,7 +19,6 @@ 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.Input import org.gradle.api.tasks.Nested import org.gradle.api.tasks.TaskAction import org.gradle.kotlin.dsl.property @@ -31,7 +30,6 @@ open class ReleaseNexusStagingRepository @Inject constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository: NexusRepository) : AbstractNexusStagingRepositoryTask(objects, extension, repository) { - @get:Input @get:Nested val stagingRepository: Property = objects.property() @@ -46,8 +44,8 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository fun releaseStagingRepo() { val client = NexusClient(repository.get().nexusUrl.get(), repository.get().username.orNull, repository.get().password.orNull, clientTimeout.orNull, connectTimeout.orNull) val stagingProfileId = determineStagingProfileId(client) // TODO: Will it update value in extension? - logger.info("Releasing staging repository with id '{}' for stagingProfileId '{}'", stagingRepository.get().stagingRepositoryId.get(), stagingProfileId) - client.releaseStagingRepository(stagingRepository.get().stagingRepositoryId.get()) + logger.info("Releasing staging repository with id '{}' for stagingProfileId '{}'", stagingRepository.get().id, stagingProfileId) + client.releaseStagingRepository(stagingRepository.get().id) // TODO: Broken with real Nexus - waiting for effective execution is also required https://github.com/gradle-nexus/publish-plugin/issues/7 } } From 7388b137faafccb189956bdb7832166742f67dbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Zaj=C4=85czkowski?= Date: Sat, 4 Jan 2020 13:55:24 +0100 Subject: [PATCH 16/18] [#4] Override staging repo id to close/release Using a command line switch. --- .../publishplugin/NexusPublishPluginTests.kt | 131 ++++++++++++------ .../CloseNexusStagingRepository.kt | 6 +- .../ReleaseNexusStagingRepository.kt | 6 +- 3 files changed, 99 insertions(+), 44 deletions(-) diff --git a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt index b835e8ea..cb06cfdf 100644 --- a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt +++ b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt @@ -55,6 +55,11 @@ class NexusPublishPluginTests { companion object { private const val STAGING_PROFILE_ID = "someProfileId" private const val STAGED_REPOSITORY_ID = "orgexample-42" + private const val OVERRIDDEN_STAGED_REPOSITORY_ID = "orgexample-42o" + } + + private enum class StagingRepoTransitionOperation(val urlSufix: String, val type: String) { + CLOSE("close", "CLOSED"), RELEASE("promote", "RELEASED") } private val gson = Gson() @@ -636,24 +641,10 @@ class NexusPublishPluginTests { @Test fun `should close staging repository`(@Wiremock server: WireMockServer) { writeDefaultSingleProjectConfiguration() - buildGradle.append(""" - nexusPublishing { - repositories { - sonatype { - nexusUrl = uri('${server.baseUrl()}') - stagingProfileId = '$STAGING_PROFILE_ID' - } - } - } - """) + writeMockedSonatypeNexusPublishingConfiguration(server) stubCreateStagingRepoRequest(server, "/staging/profiles/$STAGING_PROFILE_ID/start", STAGED_REPOSITORY_ID) - server.stubFor(post(urlEqualTo("/staging/bulk/close")) - .withRequestBody(matchingJsonPath("\$.data[?(@.stagedRepositoryIds[0] == '$STAGED_REPOSITORY_ID')]")) - .withRequestBody(matchingJsonPath("\$.data[?(@.autoDropAfterRelease == true)]")) - .willReturn(aResponse().withHeader("Content-Type", "application/json").withBody("{}"))) - server.stubFor(get(urlEqualTo("/staging/repository/$STAGED_REPOSITORY_ID")) - .willReturn(aResponse().withHeader("Content-Type", "application/json").withBody("{\"transitioning\":false,\"type\":\"CLOSED\"}"))) + stubCloseStagingRepoRequestWithSubsequentQueryAboutItsState(server, STAGED_REPOSITORY_ID) val result = run("initializeSonatypeStagingRepository", "closeSonatypeStagingRepository") @@ -662,27 +653,40 @@ class NexusPublishPluginTests { assertCloseOfStagingRepo(server) } + private fun stubCloseStagingRepoRequestWithSubsequentQueryAboutItsState( + server: WireMockServer, + stagingRepositoryId: String = STAGED_REPOSITORY_ID + ) { + stubTransitToDesiredStateStagingRepoRequestWithSubsequentQueryAboutItsState(server, stagingRepositoryId, StagingRepoTransitionOperation.CLOSE) + } + + private fun stubReleaseStagingRepoRequestWithSubsequentQueryAboutItsState( + server: WireMockServer, + stagingRepositoryId: String = STAGED_REPOSITORY_ID + ) { + stubTransitToDesiredStateStagingRepoRequestWithSubsequentQueryAboutItsState(server, stagingRepositoryId, StagingRepoTransitionOperation.RELEASE) + } + + private fun stubTransitToDesiredStateStagingRepoRequestWithSubsequentQueryAboutItsState( + server: WireMockServer, + stagingRepositoryId: String, + operation: StagingRepoTransitionOperation + ) { + server.stubFor(post(urlEqualTo("/staging/bulk/${operation.urlSufix}")) + .withRequestBody(matchingJsonPath("\$.data[?(@.stagedRepositoryIds[0] == '$stagingRepositoryId')]")) + .withRequestBody(matchingJsonPath("\$.data[?(@.autoDropAfterRelease == true)]")) + .willReturn(aResponse().withHeader("Content-Type", "application/json").withBody("{}"))) + server.stubFor(get(urlEqualTo("/staging/repository/$stagingRepositoryId")) + .willReturn(aResponse().withHeader("Content-Type", "application/json").withBody("{\"transitioning\":false,\"type\":\"${operation.type}\"}"))) + } + @Test fun `should close and release staging repository`(@Wiremock server: WireMockServer) { writeDefaultSingleProjectConfiguration() - buildGradle.append(""" - nexusPublishing { - repositories { - sonatype { - nexusUrl = uri('${server.baseUrl()}') - stagingProfileId = '$STAGING_PROFILE_ID' - } - } - } - """) + writeMockedSonatypeNexusPublishingConfiguration(server) stubCreateStagingRepoRequest(server, "/staging/profiles/$STAGING_PROFILE_ID/start", STAGED_REPOSITORY_ID) - server.stubFor(post(urlEqualTo("/staging/bulk/promote")) - .withRequestBody(matchingJsonPath("\$.data[?(@.stagedRepositoryIds[0] == '$STAGED_REPOSITORY_ID')]")) - .withRequestBody(matchingJsonPath("\$.data[?(@.autoDropAfterRelease == true)]")) - .willReturn(aResponse().withHeader("Content-Type", "application/json").withBody("{}"))) - server.stubFor(get(urlEqualTo("/staging/repository/$STAGED_REPOSITORY_ID")) - .willReturn(aResponse().withHeader("Content-Type", "application/json").withBody("{\"transitioning\":false,\"type\":\"RELEASED\"}"))) + stubReleaseStagingRepoRequestWithSubsequentQueryAboutItsState(server, STAGED_REPOSITORY_ID) val result = run("tasks", "initializeSonatypeStagingRepository", "releaseSonatypeStagingRepository") @@ -691,13 +695,43 @@ class NexusPublishPluginTests { assertReleaseOfStagingRepo(server) } + //TODO: Move to separate subclass with command line tests for @Option + //TODO: Consider switching to parameterized tests for close and release + @Test + fun `should allow to take staging repo id to close from command line without its initialization`(@Wiremock server: WireMockServer) { + writeDefaultSingleProjectConfiguration() + writeMockedSonatypeNexusPublishingConfiguration(server) + //and + stubCloseStagingRepoRequestWithSubsequentQueryAboutItsState(server, OVERRIDDEN_STAGED_REPOSITORY_ID) + + val result = run("closeSonatypeStagingRepository", "--stagingRepositoryId=$OVERRIDDEN_STAGED_REPOSITORY_ID") + + assertSuccess(result, ":closeSonatypeStagingRepository") + assertCloseOfStagingRepo(server, OVERRIDDEN_STAGED_REPOSITORY_ID) + } + + @Test + fun `should allow to take staging repo id to release from command line without its initialization`(@Wiremock server: WireMockServer) { + writeDefaultSingleProjectConfiguration() + writeMockedSonatypeNexusPublishingConfiguration(server) + //and + stubReleaseStagingRepoRequestWithSubsequentQueryAboutItsState(server, OVERRIDDEN_STAGED_REPOSITORY_ID) + + val result = run("releaseSonatypeStagingRepository", "--stagingRepositoryId=$OVERRIDDEN_STAGED_REPOSITORY_ID") + + assertSuccess(result, ":releaseSonatypeStagingRepository") + assertReleaseOfStagingRepo(server, OVERRIDDEN_STAGED_REPOSITORY_ID) + } + @Test - @Disabled("TODO") - fun `should allow to override stagingRepositoryId to close from command line`() {} + @Disabled("Should override or fail with meaningful error?") + fun `command line option should override initialized staging repository to close`() { + } @Test - @Disabled("TODO") - fun `should allow to override stagingRepositoryId to release from command line`() {} + @Disabled("Should override or fail with meaningful error?") + fun `command line option should override initialized staging repository to release`() { + } // TODO: To be used also in other tests private fun writeDefaultSingleProjectConfiguration() { @@ -729,6 +763,19 @@ class NexusPublishPluginTests { """) } + private fun writeMockedSonatypeNexusPublishingConfiguration(server: WireMockServer) { + buildGradle.append(""" + nexusPublishing { + repositories { + sonatype { + nexusUrl = uri('${server.baseUrl()}') + stagingProfileId = '$STAGING_PROFILE_ID' + } + } + } + """) + } + private fun run(vararg arguments: String): BuildResult { return gradleRunner(*arguments).build() } @@ -786,16 +833,16 @@ class NexusPublishPluginTests { server.verify(putRequestedFor(urlMatching(testUrl))) } - private fun assertCloseOfStagingRepo(server: WireMockServer) { - assertGivenTransitionOperationOfStagingRepo(server, "close") + private fun assertCloseOfStagingRepo(server: WireMockServer, stagingRepositoryId: String = STAGED_REPOSITORY_ID) { + assertGivenTransitionOperationOfStagingRepo(server, "close", stagingRepositoryId) } - private fun assertReleaseOfStagingRepo(server: WireMockServer) { - assertGivenTransitionOperationOfStagingRepo(server, "promote") + private fun assertReleaseOfStagingRepo(server: WireMockServer, stagingRepositoryId: String = STAGED_REPOSITORY_ID) { + assertGivenTransitionOperationOfStagingRepo(server, "promote", stagingRepositoryId) } - private fun assertGivenTransitionOperationOfStagingRepo(server: WireMockServer, transitionOperation: String) { + private fun assertGivenTransitionOperationOfStagingRepo(server: WireMockServer, transitionOperation: String, stagingRepositoryId: String) { server.verify(postRequestedFor(urlMatching("/staging/bulk/$transitionOperation")) - .withRequestBody(matchingJsonPath("\$.data[?(@.stagedRepositoryIds[0] == '$STAGED_REPOSITORY_ID')]"))) + .withRequestBody(matchingJsonPath("\$.data[?(@.stagedRepositoryIds[0] == '$stagingRepositoryId')]"))) } } diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt index 1e62f28d..68890422 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt @@ -21,6 +21,7 @@ import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Property import org.gradle.api.tasks.Nested import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.options.Option import org.gradle.kotlin.dsl.property import javax.inject.Inject @@ -32,7 +33,10 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository @get:Nested val stagingRepository: Property = objects.property() - //TODO: Bring back an ability to define stagingRepositoryId from a command line (and propagate that value back to NexusStagingRepository for Release*) + @Option(option = "stagingRepositoryId", description = "stagingRepositoryId to close") + fun setStagingRepositoryId(stagingRepositoryId: String) { + stagingRepository.set(NexusStagingRepository(stagingRepositoryId)) + } init { // TODO: Replace with convention() once only Gradle 5.1+ is supported diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt index e454bb53..b41619c1 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt @@ -21,6 +21,7 @@ import org.gradle.api.model.ObjectFactory import org.gradle.api.provider.Property import org.gradle.api.tasks.Nested import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.options.Option import org.gradle.kotlin.dsl.property import javax.inject.Inject @@ -33,7 +34,10 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository @get:Nested val stagingRepository: Property = objects.property() - //TODO: Bring back an ability to define stagingRepositoryId from a command line + @Option(option = "stagingRepositoryId", description = "stagingRepositoryId to release") + fun setStagingRepositoryId(stagingRepositoryId: String) { + stagingRepository.set(NexusStagingRepository(stagingRepositoryId)) + } init { // TODO: Replace with convention() once only Gradle 5.1+ is supported From 084a51aea85f8fef1f411e1f5ae1908f28d54cf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Zaj=C4=85czkowski?= Date: Tue, 7 Jan 2020 18:45:52 +0100 Subject: [PATCH 17/18] [#4] Determine and cache staging profile id between tasks --- .../publishplugin/NexusPublishPluginTests.kt | 93 +++++++++++++++++++ .../AbstractNexusStagingRepositoryTask.kt | 15 ++- .../CloseNexusStagingRepository.kt | 12 +-- .../InitializeNexusStagingRepository.kt | 5 +- .../publishplugin/NexusRepository.kt | 7 +- ...exusStagingRepositoryMutableTaskConfig.kt} | 13 ++- .../ReleaseNexusStagingRepository.kt | 12 +-- 7 files changed, 137 insertions(+), 20 deletions(-) rename src/main/kotlin/io/github/gradlenexus/publishplugin/{NexusStagingRepository.kt => NexusStagingRepositoryMutableTaskConfig.kt} (65%) diff --git a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt index cb06cfdf..96cf71e9 100644 --- a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt +++ b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt @@ -19,7 +19,9 @@ package io.github.gradlenexus.publishplugin import com.github.tomakehurst.wiremock.WireMockServer import com.github.tomakehurst.wiremock.client.WireMock.aResponse import com.github.tomakehurst.wiremock.client.WireMock.anyUrl +import com.github.tomakehurst.wiremock.client.WireMock.containing import com.github.tomakehurst.wiremock.client.WireMock.get +import com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor import com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath import com.github.tomakehurst.wiremock.client.WireMock.post import com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor @@ -733,6 +735,63 @@ class NexusPublishPluginTests { fun `command line option should override initialized staging repository to release`() { } + @Test + internal fun `initialize task should resolve stagingProfileId if not provided and keep it for close task`(@Wiremock server: WireMockServer) { + 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) + + val result = run("initializeSonatypeStagingRepository", "closeSonatypeStagingRepository") + + assertSuccess(result, ":initializeSonatypeStagingRepository") + assertSuccess(result, ":closeSonatypeStagingRepository") + //and + 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(""" @@ -799,6 +858,15 @@ class NexusPublishPluginTests { .willReturn(aResponse().withBody(gson.toJson(mapOf("data" to mapOf("stagedRepositoryId" to stagedRepositoryId)))))) } + private fun stubGetStagingProfilesForOneProfileIdGivenId(server: WireMockServer, stagingProfileId: String = STAGING_PROFILE_ID) { + server.stubFor(get(urlEqualTo("/staging/profiles")) + .withHeader("Accept", containing("application/json")) + .willReturn(aResponse() + .withStatus(200) + .withHeader("Content-Type", "application/json") + .withBody(getOneStagingProfileWithGivenIdShrunkJsonResponseAsString(stagingProfileId)))) + } + private fun expectArtifactUploads(server: WireMockServer, prefix: String) { server.stubFor(put(urlMatching("$prefix/.+")) .willReturn(aResponse().withStatus(201))) @@ -825,6 +893,10 @@ class NexusPublishPluginTests { assertThat(result.task(taskPath)).describedAs("Task $taskPath").isNull() } + private fun assertGetStagingProfile(server: WireMockServer, count: Int = 1) { + server.verify(count, getRequestedFor(urlMatching("/staging/profiles"))) + } + private fun assertUploadedToStagingRepo(server: WireMockServer, path: String) { assertUploaded(server, "/staging/deployByRepositoryId/$STAGED_REPOSITORY_ID$path") } @@ -845,4 +917,25 @@ class NexusPublishPluginTests { server.verify(postRequestedFor(urlMatching("/staging/bulk/$transitionOperation")) .withRequestBody(matchingJsonPath("\$.data[?(@.stagedRepositoryIds[0] == '$stagingRepositoryId')]"))) } + + private fun getOneStagingProfileWithGivenIdShrunkJsonResponseAsString(stagingProfileId: String): String { + return """ + { + "data": [ + { + "deployURI": "https://oss.sonatype.org/service/local/staging/deploy/maven2", + "id": "$stagingProfileId", + "inProgress": false, + "mode": "BOTH", + "name": "org.example", + "order": 6445, + "promotionTargetRepository": "releases", + "repositoryType": "maven2", + "resourceURI": "https://oss.sonatype.org/service/local/staging/profiles/$stagingProfileId", + "targetGroups": ["staging"] + } + ] + } + """.trimIndent() + } } diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt index 8465974c..286979c0 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt @@ -55,18 +55,25 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository this.onlyIf { extension.useStaging.getOrElse(false) } } - protected fun determineStagingProfileId(client: NexusClient): String { - var stagingProfileId = repository.get().stagingProfileId.orNull + 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 } - protected fun keepStagingRepositoryIdInExtension(stagingRepositoryIdAsString: String) { - repository.get().stagingRepository.set(NexusStagingRepository(stagingRepositoryIdAsString)) + private fun cacheStagingProfileIdForOtherTasks(stagingProfileId: String) { + repository.get().stagingRepositoryMutableTaskConfig.get().profileId = stagingProfileId + } + + protected fun cacheStagingRepositoryForOtherTasks(stagingRepositoryId: String) { + repository.get().stagingRepositoryMutableTaskConfig.get().repositoryId = stagingRepositoryId } } diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt index 68890422..e90e8069 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt @@ -31,24 +31,24 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository AbstractNexusStagingRepositoryTask(objects, extension, repository) { @get:Nested - val stagingRepository: Property = objects.property() + val stagingRepositoryConfig: Property = objects.property() @Option(option = "stagingRepositoryId", description = "stagingRepositoryId to close") fun setStagingRepositoryId(stagingRepositoryId: String) { - stagingRepository.set(NexusStagingRepository(stagingRepositoryId)) + stagingRepositoryConfig.get().repositoryId = stagingRepositoryId } init { // TODO: Replace with convention() once only Gradle 5.1+ is supported - stagingRepository.set(repository.stagingRepository) + stagingRepositoryConfig.set(repository.stagingRepositoryMutableTaskConfig) } @TaskAction fun closeStagingRepo() { val client = NexusClient(repository.get().nexusUrl.get(), repository.get().username.orNull, repository.get().password.orNull, clientTimeout.orNull, connectTimeout.orNull) - val stagingProfileId = determineStagingProfileId(client) - logger.info("Closing staging repository with id '{}' for stagingProfileId '{}'", stagingRepository.get().id, stagingProfileId) - client.closeStagingRepository(stagingRepository.get().id) + 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 // 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 87f94f30..e2883a3f 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt @@ -40,11 +40,12 @@ 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 = determineStagingProfileId(client) // TODO: It would be good to keep/cache value in Extension/Repository + val stagingProfileId = determineAndCacheStagingProfileId(client) logger.info("Creating staging repository for stagingProfileId '{}'", stagingProfileId) val stagingRepositoryIdAsString = client.createStagingRepository(stagingProfileId) - keepStagingRepositoryIdInExtension(stagingRepositoryIdAsString) + cacheStagingRepositoryForOtherTasks(stagingRepositoryIdAsString) + //TODO: To be removed in next iteration project.rootProject.plugins.withId("io.codearte.nexus-staging") { val nexusStagingExtension = project.rootProject.the() try { diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt index a9b91dc9..11df2aaf 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusRepository.kt @@ -51,7 +51,12 @@ open class NexusRepository @Inject constructor(@get:Input val name: String, proj val stagingProfileId: Property = project.objects.property() @get:Internal - val stagingRepository: Property = project.objects.property() + val stagingRepositoryMutableTaskConfig: Property = project.objects.property() + + init { + // TODO: Replace with convention() once only Gradle 5.1+ is supported + stagingRepositoryMutableTaskConfig.set(NexusStagingRepositoryMutableTaskConfig.empty()) + } internal fun capitalizedName(): String { return name.capitalize() diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusStagingRepositoryMutableTaskConfig.kt similarity index 65% rename from src/main/kotlin/io/github/gradlenexus/publishplugin/NexusStagingRepository.kt rename to src/main/kotlin/io/github/gradlenexus/publishplugin/NexusStagingRepositoryMutableTaskConfig.kt index 2d0108d5..bb0e290f 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusStagingRepositoryMutableTaskConfig.kt @@ -17,5 +17,16 @@ package io.github.gradlenexus.publishplugin import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional -open class NexusStagingRepository constructor(@get:Input val id: String) +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 b41619c1..d1e3a9c3 100644 --- a/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt +++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt @@ -32,24 +32,24 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository AbstractNexusStagingRepositoryTask(objects, extension, repository) { @get:Nested - val stagingRepository: Property = objects.property() + val stagingRepositoryConfig: Property = objects.property() @Option(option = "stagingRepositoryId", description = "stagingRepositoryId to release") fun setStagingRepositoryId(stagingRepositoryId: String) { - stagingRepository.set(NexusStagingRepository(stagingRepositoryId)) + stagingRepositoryConfig.get().repositoryId = stagingRepositoryId } init { // TODO: Replace with convention() once only Gradle 5.1+ is supported - stagingRepository.set(repository.stagingRepository) + stagingRepositoryConfig.set(repository.stagingRepositoryMutableTaskConfig) } @TaskAction fun releaseStagingRepo() { val client = NexusClient(repository.get().nexusUrl.get(), repository.get().username.orNull, repository.get().password.orNull, clientTimeout.orNull, connectTimeout.orNull) - val stagingProfileId = determineStagingProfileId(client) // TODO: Will it update value in extension? - logger.info("Releasing staging repository with id '{}' for stagingProfileId '{}'", stagingRepository.get().id, stagingProfileId) - client.releaseStagingRepository(stagingRepository.get().id) + 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!!) // TODO: Broken with real Nexus - waiting for effective execution is also required https://github.com/gradle-nexus/publish-plugin/issues/7 } } From 6ce5c2b3ec501cb01471ea722a1b313f5fa44612 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 11 Jan 2020 14:52:45 +0100 Subject: [PATCH 18/18] 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 } }