Skip to content

Commit

Permalink
[#4] Close and release tasks
Browse files Browse the repository at this point in the history
Initial version.
  • Loading branch information
szpak committed Oct 18, 2019
1 parent b92668a commit 27dc786
Show file tree
Hide file tree
Showing 14 changed files with 434 additions and 36 deletions.
4 changes: 4 additions & 0 deletions .stutter/java11.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# DO NOT MODIFY: Generated by Stutter plugin.
4.10.3
5.0
5.6.3
7 changes: 1 addition & 6 deletions .stutter/java8.lock
Original file line number Diff line number Diff line change
@@ -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
6 changes: 5 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down Expand Up @@ -98,9 +98,13 @@ dependencies {
}

stutter {
isSparse = (findProperty("stutter.sparce")?.toString()?.toBoolean()) ?: true
java(8) {
compatibleRange("4.10")
}
java(11) {
compatibleRange("4.10")
}
}

configurations {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@ 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.Disabled
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.junit.jupiter.api.io.TempDir
Expand All @@ -45,6 +48,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 {

Expand All @@ -55,7 +59,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()
Expand All @@ -67,6 +71,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("""
Expand Down Expand Up @@ -615,6 +626,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()
}
Expand Down Expand Up @@ -673,7 +772,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')]")))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
}
Original file line number Diff line number Diff line change
@@ -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<String> = 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
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -32,6 +32,8 @@ open class InitializeNexusStagingRepository @Inject
constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository: NexusRepository, private val serverUrlToStagingRepoUrl: MutableMap<URI, URI>) :
BaseOperationOnNexusStagingRepository(objects, extension, repository) {

private val stagingRepositoryId: Property<String> = repository.stagingRepositoryId

@TaskAction
fun createStagingRepoAndReplacePublishingRepoUrl() {
val url = createStagingRepo()
Expand All @@ -41,39 +43,34 @@ 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<NexusStagingExtension>()
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" +
"If this also does not make this warning go away, please report an issue for io.github.gradle-nexus.publish-plugin.")
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<PublishingExtension>()
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)
}
}
Loading

0 comments on commit 27dc786

Please sign in to comment.