Skip to content

Commit

Permalink
Add closeStagingRepositories and releaseStagingRepositories summary t…
Browse files Browse the repository at this point in the history
…asks (#236)
  • Loading branch information
Vampire committed Dec 3, 2023
1 parent 1368389 commit eaa08f5
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 31 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,26 @@ So the steps to publish and release in different Gradle invocations are:

(in the above example, steps 1 and 2 could be also combined into `./gradlew publishToSonatype closeSonatypeStagingRepository`, to make only the releasing done in a separate step)

### Summary Tasks

If you declare multiple repositories, you get a separate set of tasks for each of the repositories.
If you for example declared the repositories `sonatype` and `otherNexus`, you get these tasks:
- `closeSonatypeStagingRepository`
- `closeOtherNexusStagingRepository`
- `releaseSonatypeStagingRepository`
- `releaseOtherNexusStagingRepository`
- `closeAndReleaseSonatypeStagingRepository`
- `closeAndReleaseOtherNexusStagingRepository`

For convenience there are also summary tasks generated, that group the tasks for the different repositories, which are
- `closeStagingRepositories`
- `releaseStagingRepositories`
- `closeAndReleaseStagingRepositories`

In the typical use-case, which is only one repository for publishing to Maven Central, these tasks still are useful,
especially if you are using Kotlin DSL build scripts, because those summary tasks are always added, independent of
declared repositories. Due to that there are type-safe accessors generated that can be used conveniently for task dependencies.

### Full example

#### Groovy DSL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ import java.time.Duration
class NexusPublishPlugin : Plugin<Project> {

companion object {
// visibility for testing
const val SIMPLIFIED_CLOSE_AND_RELEASE_TASK_NAME = "closeAndReleaseStagingRepository"
private const val SIMPLIFIED_CLOSE_AND_RELEASE_TASK_NAME = "closeAndReleaseStagingRepositories"
private const val SIMPLIFIED_CLOSE_TASK_NAME = "closeStagingRepositories"
private const val SIMPLIFIED_RELEASE_TASK_NAME = "releaseStagingRepositories"
}

override fun apply(project: Project) {
Expand Down Expand Up @@ -125,10 +126,17 @@ class NexusPublishPlugin : Plugin<Project> {
enabled = false
}
}
rootProject.tasks.register<Task>(SIMPLIFIED_CLOSE_AND_RELEASE_TASK_NAME) {
rootProject.tasks.register(SIMPLIFIED_CLOSE_AND_RELEASE_TASK_NAME) {
group = PublishingPlugin.PUBLISH_TASK_GROUP
description = "Closes and releases open staging repositories in all configured Nexus instances."
enabled = false
}
rootProject.tasks.register(SIMPLIFIED_CLOSE_TASK_NAME) {
group = PublishingPlugin.PUBLISH_TASK_GROUP
description = "Closes open staging repositories in all configured Nexus instances."
}
rootProject.tasks.register(SIMPLIFIED_RELEASE_TASK_NAME) {
group = PublishingPlugin.PUBLISH_TASK_GROUP
description = "Releases open staging repositories in all configured Nexus instances."
}
}

Expand Down Expand Up @@ -235,7 +243,7 @@ class NexusPublishPlugin : Plugin<Project> {
}
}
}
configureSimplifiedCloseAndReleaseTask(rootProject, extension)
configureSimplifiedCloseAndReleaseTasks(rootProject, extension)
}
}

Expand Down Expand Up @@ -346,25 +354,37 @@ class NexusPublishPlugin : Plugin<Project> {
}
}

private fun configureSimplifiedCloseAndReleaseTask(rootProject: Project, extension: NexusPublishExtension) {
private fun configureSimplifiedCloseAndReleaseTasks(rootProject: Project, extension: NexusPublishExtension) {
if (extension.repositories.isNotEmpty()) {
val closeAndReleaseSimplifiedTask = rootProject.tasks.named(SIMPLIFIED_CLOSE_AND_RELEASE_TASK_NAME)
closeAndReleaseSimplifiedTask.configure {
val repositoryNamesAsString = extension.repositories.joinToString(", ") { "'${it.name}'" }
val instanceCardinalityAwareString = if (extension.repositories.size > 1) {
"instances"
} else {
"instance"
}
val repositoryNamesAsString = extension.repositories.joinToString(", ") { "'${it.name}'" }
val instanceCardinalityAwareString = if (extension.repositories.size > 1) {
"instances"
} else {
"instance"
}
val closeAndReleaseSimplifiedTask = rootProject.tasks.named(SIMPLIFIED_CLOSE_AND_RELEASE_TASK_NAME) {
description = "Closes and releases open staging repositories in the following Nexus $instanceCardinalityAwareString: $repositoryNamesAsString"
enabled = true
}
val closeSimplifiedTask = rootProject.tasks.named(SIMPLIFIED_CLOSE_TASK_NAME) {
description = "Closes open staging repositories in the following Nexus $instanceCardinalityAwareString: $repositoryNamesAsString"
}
val releaseSimplifiedTask = rootProject.tasks.named(SIMPLIFIED_RELEASE_TASK_NAME) {
description = "Releases open staging repositories in the following Nexus $instanceCardinalityAwareString: $repositoryNamesAsString"
}
extension.repositories.all {
val repositoryCapitalizedName = this.capitalizedName
val closeAndReleaseTask = rootProject.tasks.named<Task>("closeAndRelease${repositoryCapitalizedName}StagingRepository")
closeAndReleaseSimplifiedTask.configure {
closeAndReleaseSimplifiedTask {
dependsOn(closeAndReleaseTask)
}
val closeTask = rootProject.tasks.named<Task>("close${repositoryCapitalizedName}StagingRepository")
closeSimplifiedTask {
dependsOn(closeTask)
}
val releaseTask = rootProject.tasks.named<Task>("release${repositoryCapitalizedName}StagingRepository")
releaseSimplifiedTask {
dependsOn(releaseTask)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.CsvSource
import org.junit.jupiter.params.provider.MethodSource
import org.junit.jupiter.params.provider.ValueSource
import java.nio.file.Path

@KotlinParameterizeTest
Expand Down Expand Up @@ -93,44 +95,64 @@ class TaskOrchestrationTest {
.contains("closeSonatypeStagingRepository", "releaseSonatypeStagingRepository")
}

@Test
internal fun `simplified close and release task without repository name should be available but trigger nothing if no repositories are configured`() {
@ParameterizedTest(name = "{0}")
@ValueSource(
strings = [
"closeAndReleaseStagingRepositories",
"closeStagingRepositories",
"releaseStagingRepositories"
]
)
internal fun `simplified task without repository name should be available but trigger nothing if no repositories are configured`(simplifiedTaskName: String) {
initSingleProjectWithDefaultConfiguration()
project.extensions.configure<NexusPublishExtension> {
repositories.clear()
}

val simplifiedCloseAndReleaseTasks = project.getTasksByName(NexusPublishPlugin.SIMPLIFIED_CLOSE_AND_RELEASE_TASK_NAME, true)
val simplifiedTasks = project.getTasksByName(simplifiedTaskName, true)

assertThat(simplifiedCloseAndReleaseTasks).hasSize(1)
assertThat(simplifiedCloseAndReleaseTasks.first().dependsOn).isEmpty()
assertThat(simplifiedTasks).hasSize(1)
assertThat(simplifiedTasks.first().dependsOn).isEmpty()
}

@Test
internal fun `simplified closeAndRelease task without repository name should depend on all closeAndRelease (created one per defined repository)`() {
@ParameterizedTest(name = "{0}")
@CsvSource(
textBlock = """
closeAndReleaseStagingRepositories, closeAndReleaseSonatypeStagingRepository, closeAndReleaseOtherNexusStagingRepository
closeStagingRepositories , closeSonatypeStagingRepository , closeOtherNexusStagingRepository
releaseStagingRepositories , releaseSonatypeStagingRepository , releaseOtherNexusStagingRepository"""
)
internal fun `simplified task without repository name should depend on all normal tasks (created one per defined repository)`(simplifiedTaskName: String, sonatypeTaskName: String, otherNexusTaskName: String) {
initSingleProjectWithDefaultConfiguration()
project.extensions.configure<NexusPublishExtension> {
repositories.create("otherNexus")
}

val closeAndReleaseTask = getJustOneTaskByNameOrFail(NexusPublishPlugin.SIMPLIFIED_CLOSE_AND_RELEASE_TASK_NAME)
val simplifiedTasks = getJustOneTaskByNameOrFail(simplifiedTaskName)

assertThat(closeAndReleaseTask.taskDependencies.getDependencies(null).map { it.name })
assertThat(simplifiedTasks.taskDependencies.getDependencies(null).map { it.name })
.hasSize(2)
.contains("closeAndReleaseSonatypeStagingRepository")
.contains("closeAndReleaseOtherNexusStagingRepository")
.contains(sonatypeTaskName)
.contains(otherNexusTaskName)
}

@Test
internal fun `description of simplified closeAndRelease task contains names of all defined Nexus instances`() {
@ParameterizedTest(name = "{0}")
@ValueSource(
strings = [
"closeAndReleaseStagingRepositories",
"closeStagingRepositories",
"releaseStagingRepositories"
]
)
internal fun `description of simplified task contains names of all defined Nexus instances`(simplifiedTaskName: String) {
initSingleProjectWithDefaultConfiguration()
project.extensions.configure<NexusPublishExtension> {
repositories.create("otherNexus")
}

val closeAndReleaseTask = getJustOneTaskByNameOrFail(NexusPublishPlugin.SIMPLIFIED_CLOSE_AND_RELEASE_TASK_NAME)
val simplifiedTasks = getJustOneTaskByNameOrFail(simplifiedTaskName)

assertThat(closeAndReleaseTask.description)
assertThat(simplifiedTasks.description)
.contains("sonatype")
.contains("otherNexus")
}
Expand Down

0 comments on commit eaa08f5

Please sign in to comment.