Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make staging repo description configurable #36

Merged
merged 3 commits into from
Jun 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ tasks {
dependsOn(relocateShadowJar)
configurations = listOf(shadowed)
exclude("META-INF/maven/**", "META-INF/proguard/**", "META-INF/*.kotlin_module")
manifest {
attributes["Implementation-Version"] = project.version
}
}
jar {
enabled = false
Expand Down Expand Up @@ -186,6 +189,9 @@ tasks {
useJUnitPlatform()
maxParallelForks = 8
}
withType<Test>().matching { it.name.startsWith("compatTest") }.configureEach {
systemProperty("plugin.version", project.version)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can probably set for all the tests, not just compatTest (to reuse the previous section in build.gradle).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't want to add an unnecessary input to the other test tasks.

}
dokka {
configuration {
outputFormat = "javadoc"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ 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.matching
import com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath
import com.github.tomakehurst.wiremock.client.WireMock.post
import com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor
Expand All @@ -32,8 +33,6 @@ import com.github.tomakehurst.wiremock.client.WireMock.urlMatching
import com.github.tomakehurst.wiremock.stubbing.Scenario
import com.google.gson.Gson
import io.github.gradlenexus.publishplugin.internal.StagingRepository
import java.nio.file.Files
import java.nio.file.Path
import org.assertj.core.api.Assertions.assertThat
import org.gradle.testkit.runner.BuildResult
import org.gradle.testkit.runner.GradleRunner
Expand All @@ -51,6 +50,8 @@ import org.junit.jupiter.api.extension.ExtendWith
import org.junit.jupiter.api.io.TempDir
import ru.lanwen.wiremock.ext.WiremockResolver
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)
Expand Down Expand Up @@ -199,7 +200,7 @@ class NexusPublishPluginTests {
assertThat(result.output).containsOnlyOnce("Created staging repository '$STAGED_REPOSITORY_ID' at ${server.baseUrl()}/repositories/$STAGED_REPOSITORY_ID/content/")
assertNotConsidered(result, ":initializeSomeOtherNexusStagingRepository")
server.verify(postRequestedFor(urlEqualTo("/staging/profiles/$STAGING_PROFILE_ID/start"))
.withRequestBody(matchingJsonPath("\$.data[?(@.description == 'Created by io.github.gradle-nexus.publish-plugin Gradle plugin')]")))
.withRequestBody(matchingJsonPath("\$.data[?(@.description == 'org.example:sample:0.0.1')]")))
assertUploadedToStagingRepo("/org/example/sample/0.0.1/sample-0.0.1.pom")
assertUploadedToStagingRepo("/org/example/sample/0.0.1/sample-0.0.1.jar")
}
Expand Down Expand Up @@ -696,6 +697,7 @@ class NexusPublishPluginTests {
@SafeVarargs
private fun stubStagingProfileRequest(url: String, vararg stagingProfiles: Map<String, String>) {
server.stubFor(get(urlEqualTo(url))
.withHeader("User-Agent", matching("gradle-nexus-publish-plugin/.*"))
.willReturn(aResponse().withBody(gson.toJson(mapOf("data" to listOf(*stagingProfiles))))))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package io.github.gradlenexus.publishplugin

import org.gradle.api.DefaultTask
import org.gradle.api.model.ObjectFactory
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Nested
import org.gradle.kotlin.dsl.property
Expand All @@ -44,6 +45,11 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository
set(repository)
}

@Input
val description = objects.property<String>().apply {
set(extension.description)
}

init {
this.onlyIf { extension.useStaging.getOrElse(false) }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository
val client = NexusClient(repository.get().nexusUrl.get(), repository.get().username.orNull, repository.get().password.orNull, clientTimeout.orNull, connectTimeout.orNull)
val repositoryTransitioner = StagingRepositoryTransitioner(client, BasicActionRetrier.retryUntilRepoTransitionIsCompletedRetrier(repository.get().retrying.get()))
logger.info("Closing staging repository with id '{}'", stagingRepositoryId.get())
repositoryTransitioner.effectivelyClose(stagingRepositoryId.get())
repositoryTransitioner.effectivelyClose(stagingRepositoryId.get(), description.get())
logger.info("Repository with id '{}' effectively closed", stagingRepositoryId.get())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ open class InitializeNexusStagingRepository @Inject constructor(
val client = NexusClient(serverUrl, repository.username.orNull, repository.password.orNull, clientTimeout.orNull, connectTimeout.orNull)
val stagingProfileId = determineStagingProfileId(repository, client)
logger.info("Creating staging repository for {} at {}, stagingProfileId '{}'", repository.name, serverUrl, stagingProfileId)
val descriptor = client.createStagingRepository(stagingProfileId)
val descriptor = client.createStagingRepository(stagingProfileId, description.get())
val consumerUrl = HttpUrl.get(serverUrl)!!.newBuilder().addEncodedPathSegments("repositories/${descriptor.stagingRepositoryId}/content/").build()
logger.lifecycle("Created staging repository '{}' at {}", descriptor.stagingRepositoryId, consumerUrl)
registry.get()[repository.name] = descriptor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ open class NexusPublishExtension(project: Project) {
set(project.provider { project.group.toString() })
}

val description = project.objects.property<String>().apply {
set(project.provider { project.run { "$group:$name:$version" } })
}

val clientTimeout = project.objects.property<Duration>().apply {
set(Duration.ofMinutes(1))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository
val client = NexusClient(repository.get().nexusUrl.get(), repository.get().username.orNull, repository.get().password.orNull, clientTimeout.orNull, connectTimeout.orNull)
val repositoryTransitioner = StagingRepositoryTransitioner(client, BasicActionRetrier.retryUntilRepoTransitionIsCompletedRetrier(repository.get().retrying.get()))
logger.info("Releasing staging repository with id '{}'", stagingRepositoryId.get())
repositoryTransitioner.effectivelyRelease(stagingRepositoryId.get())
repositoryTransitioner.effectivelyRelease(stagingRepositoryId.get(), description.get())
logger.info("Repository with id '{}' effectively released", stagingRepositoryId.get())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ open class NexusClient(private val baseUrl: URI, username: String?, password: St
.build())
}
}
httpClientBuilder.addInterceptor { chain ->
val version = javaClass.`package`.implementationVersion ?: "dev"
chain.proceed(chain.request().newBuilder()
.header("User-Agent", "gradle-nexus-publish-plugin/$version")
.build())
}
val retrofit = Retrofit.Builder()
.baseUrl(baseUrl.toString())
.client(httpClientBuilder.build())
Expand All @@ -80,24 +86,24 @@ open class NexusClient(private val baseUrl: URI, username: String?, password: St
?.id
}

fun createStagingRepository(stagingProfileId: String): StagingRepositoryDescriptor {
val response = api.startStagingRepo(stagingProfileId, Dto(Description("Created by io.github.gradle-nexus.publish-plugin Gradle plugin"))).execute()
fun createStagingRepository(stagingProfileId: String, description: String): StagingRepositoryDescriptor {
val response = api.startStagingRepo(stagingProfileId, Dto(Description(description))).execute()
if (!response.isSuccessful) {
throw failure("create staging repository", response)
}
val stagingRepositoryId = response.body()?.data?.stagedRepositoryId ?: throw RuntimeException("No response body")
return StagingRepositoryDescriptor(baseUrl, stagingRepositoryId)
}

open fun closeStagingRepository(stagingRepositoryId: String) {
val response = api.closeStagingRepo(Dto(StagingRepositoryToTransit(listOf(stagingRepositoryId), "Closed by io.github.gradle-nexus.publish-plugin Gradle plugin"))).execute()
open fun closeStagingRepository(stagingRepositoryId: String, description: String) {
val response = api.closeStagingRepo(Dto(StagingRepositoryToTransit(listOf(stagingRepositoryId), description))).execute()
if (!response.isSuccessful) {
throw failure("close staging repository", response)
}
}

open fun releaseStagingRepository(stagingRepositoryId: String) {
val response = api.releaseStagingRepo(Dto(StagingRepositoryToTransit(listOf(stagingRepositoryId), "Release by io.github.gradle-nexus.publish-plugin Gradle plugin"))).execute()
open fun releaseStagingRepository(stagingRepositoryId: String, description: String) {
val response = api.releaseStagingRepo(Dto(StagingRepositoryToTransit(listOf(stagingRepositoryId), description))).execute()
if (!response.isSuccessful) {
throw failure("release staging repository", response)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ class StagingRepositoryTransitioner(val nexusClient: NexusClient, val retrier: A
private val log: Logger = LoggerFactory.getLogger(StagingRepositoryTransitioner::class.java.simpleName)
}

fun effectivelyClose(repoId: String) {
effectivelyChangeState(repoId, StagingRepository.State.CLOSED, nexusClient::closeStagingRepository)
fun effectivelyClose(repoId: String, description: String) {
effectivelyChangeState(repoId, StagingRepository.State.CLOSED) { nexusClient.closeStagingRepository(it, description) }
}

//TODO: Add support for autoDrop=false
fun effectivelyRelease(repoId: String) {
effectivelyChangeState(repoId, StagingRepository.State.NOT_FOUND, nexusClient::releaseStagingRepository)
fun effectivelyRelease(repoId: String, description: String) {
effectivelyChangeState(repoId, StagingRepository.State.NOT_FOUND) { nexusClient.releaseStagingRepository(it, description) }
}

private fun effectivelyChangeState(repoId: String, desiredState: StagingRepository.State, transitionClientRequest: (String) -> Unit) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ internal class StagingRepositoryTransitionerTest {

companion object {
private const val TEST_STAGING_REPO_ID = "orgexample-42"
private const val DESCRIPTION = "some description"
}

@Mock
Expand All @@ -53,10 +54,10 @@ internal class StagingRepositoryTransitionerTest {
.willReturn(StagingRepository(TEST_STAGING_REPO_ID, StagingRepository.State.CLOSED, false))
given(retrier.execute(anyOrNull())).willAnswer(executeFunctionPassedAsFirstArgument())

transitioner.effectivelyClose(TEST_STAGING_REPO_ID)
transitioner.effectivelyClose(TEST_STAGING_REPO_ID, DESCRIPTION)

val inOrder = inOrder(nexusClient, retrier)
inOrder.verify(nexusClient).closeStagingRepository(TEST_STAGING_REPO_ID)
inOrder.verify(nexusClient).closeStagingRepository(TEST_STAGING_REPO_ID, DESCRIPTION)
inOrder.verify(nexusClient).getStagingRepositoryStateById(TEST_STAGING_REPO_ID)
}

Expand All @@ -66,10 +67,10 @@ internal class StagingRepositoryTransitionerTest {
.willReturn(StagingRepository(TEST_STAGING_REPO_ID, StagingRepository.State.NOT_FOUND, false))
given(retrier.execute(anyOrNull())).willAnswer(executeFunctionPassedAsFirstArgument())

transitioner.effectivelyRelease(TEST_STAGING_REPO_ID)
transitioner.effectivelyRelease(TEST_STAGING_REPO_ID, DESCRIPTION)

val inOrder = inOrder(nexusClient, retrier)
inOrder.verify(nexusClient).releaseStagingRepository(TEST_STAGING_REPO_ID)
inOrder.verify(nexusClient).releaseStagingRepository(TEST_STAGING_REPO_ID, DESCRIPTION)
inOrder.verify(nexusClient).getStagingRepositoryStateById(TEST_STAGING_REPO_ID)
}

Expand All @@ -80,7 +81,7 @@ internal class StagingRepositoryTransitionerTest {
given(retrier.execute(anyOrNull())).willAnswer(executeFunctionPassedAsFirstArgument())

assertThatExceptionOfType(RepositoryTransitionException::class.java)
.isThrownBy { transitioner.effectivelyClose(TEST_STAGING_REPO_ID) }
.isThrownBy { transitioner.effectivelyClose(TEST_STAGING_REPO_ID, DESCRIPTION) }
.withMessageContainingAll(TEST_STAGING_REPO_ID, "transitioning=true")
}

Expand All @@ -91,7 +92,7 @@ internal class StagingRepositoryTransitionerTest {
given(retrier.execute(anyOrNull())).willAnswer(executeFunctionPassedAsFirstArgument())

assertThatExceptionOfType(RepositoryTransitionException::class.java)
.isThrownBy { transitioner.effectivelyClose(TEST_STAGING_REPO_ID) }
.isThrownBy { transitioner.effectivelyClose(TEST_STAGING_REPO_ID, DESCRIPTION) }
.withMessageContainingAll(TEST_STAGING_REPO_ID, StagingRepository.State.OPEN.toString(), StagingRepository.State.CLOSED.toString())
}

Expand Down