org.danilopianini.gradle.mavencentral.NexusStatefulOperation.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of publish-on-central Show documentation
Show all versions of publish-on-central Show documentation
A Plugin for easily publishing artifacts on Maven Central
package org.danilopianini.gradle.mavencentral
import com.github.kittinunf.fuel.Fuel
import com.github.kittinunf.fuel.core.extensions.authentication
import com.github.kittinunf.fuel.core.extensions.jsonBody
import io.github.gradlenexus.publishplugin.internal.BasicActionRetrier
import io.github.gradlenexus.publishplugin.internal.NexusClient
import io.github.gradlenexus.publishplugin.internal.StagingRepositoryDescriptor
import io.github.gradlenexus.publishplugin.internal.StagingRepositoryTransitioner
import kotlinx.coroutines.runBlocking
import org.gradle.api.Project
import org.gradle.api.provider.Provider
import java.net.URI
import java.time.Duration
import org.gradle.internal.impldep.com.google.api.client.http.HttpStatusCodes.STATUS_CODE_CREATED as HTTP_201_CREATED
import org.gradle.internal.impldep.com.google.api.client.http.HttpStatusCodes.STATUS_CODE_OK as HTTP_200_OK
/**
* Lazy class acting as a container for stateful operations on Nexus.
*/
data class NexusStatefulOperation(
private val project: Project,
private val nexusUrl: String,
private val user: Provider,
private val password: Provider,
private val timeOut: Duration,
private val connectionTimeOut: Duration,
private val group: String,
) {
/**
* Repository description.
*/
val description by lazy { project.run { "$group:$name:$version" } }
/**
* The NexusClient.
*/
val client: NexusClient by lazy {
NexusClient(
project.uri(nexusUrl),
user.get(),
password.get(),
timeOut,
connectionTimeOut,
)
}
/**
* Lazily computed staging profile id.
*/
val stagingProfile: String by lazy {
project.logger.lifecycle("Retrieving the profile id for $group on Nexus installed at $nexusUrl")
requireNotNull(client.findStagingProfileId(group)) {
"Invalid group id '$group': could not find an appropriate staging profile"
}
}
/**
* Lazily computed staging repository descriptor.
*/
val stagingRepository: StagingRepositoryDescriptor by lazy {
project.properties["stagingRepositoryId"]?.let {
project.logger.lifecycle("Using existing staging repository {}", it)
val stagingRepo = client.getStagingRepositoryStateById(it as String)
return@lazy StagingRepositoryDescriptor(project.uri(nexusUrl), stagingRepo.id)
} ?: run {
project.logger.lifecycle("Creating repository for profile id {} on Nexus at {}", stagingProfile, nexusUrl)
client.createStagingRepository(stagingProfile, description)
}
}
/**
* Lazily computed staging repository url.
*/
val repoUrl: URI by lazy { stagingRepository.stagingRepositoryUrl }
/**
* Lazily computed staging repository id.
*/
val repoId: String by lazy { stagingRepository.stagingRepositoryId }
private val transitioner by lazy {
StagingRepositoryTransitioner(
client,
BasicActionRetrier(Int.MAX_VALUE, Duration.ofSeconds(retryInterval)) { it.transitioning },
)
}
/**
* Closes the repository.
*/
fun close() {
project.logger.lifecycle("Closing repository {} on Nexus at {}", repoId, repoUrl)
transitioner.effectivelyClose(repoId, description)
project.logger.lifecycle("Repository $repoId closed")
}
/**
* Releases the repository. Must be called after close().
*/
fun release() {
project.logger.lifecycle("Releasing repository {} on Nexus at {}", repoId, repoUrl)
transitioner.effectivelyRelease(repoId, description)
project.logger.lifecycle("Repository {} released", repoId)
}
/**
* Drops the repository. Must be called after close().
*/
fun drop() {
project.logger.lifecycle("Dropping repository {} on Nexus at {}", repoId, repoUrl)
runBlocking {
Fuel.post("${nexusUrl.removeSuffix("/")}/staging/bulk/drop")
.header(
"Accept" to "application/json",
"Content-Type" to "application/json",
)
.authentication().basic(user.get(), password.get())
.jsonBody("""{"data":{"stagedRepositoryIds":["$repoId"],"description":"$description"}}""")
.response { _, response, _ ->
project.logger.lifecycle("Received response {} ", response)
check(response.statusCode in HTTP_200_OK..HTTP_201_CREATED) {
"Could not drop repository $repoId: HTTP ${response.statusCode} ${response.responseMessage}"
}
}
}
project.logger.lifecycle("Requested drop for repository {} ", repoId)
}
companion object {
private const val retryInterval: Long = 10
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy