diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml index 56951d74..744c4603 100644 --- a/.github/workflows/build-and-deploy.yml +++ b/.github/workflows/build-and-deploy.yml @@ -193,12 +193,63 @@ jobs: maven-central-password: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} signing-key: ${{ secrets.SIGNING_KEY }} signing-password: ${{ secrets.SIGNING_PASSWORD }} + test-drop-repo-task-regression: + runs-on: ubuntu-latest + concurrency: + group: test-drop-task-${{ github.workflow }}-${{ github.event.number || github.ref }} + cancel-in-progress: true + if: >- + !github.event.repository.fork + && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) + steps: + - name: Compute the version of the target test project + id: versiontrick + shell: bash + run: | + # Idea: the regex matcher of Renovate keeps this string up to date automatically + # The version is extracted and used to access the correct version of the scripts + USES=$(cat <> $GITHUB_OUTPUT + - name: Checkout Template-for-Kotlin-Multiplatform-Projects ${{ steps.versiontrick.outputs.version }} + uses: actions/checkout@v3.3.0 + with: + fetch-depth: '0' + path: 'kt-mp-drop-task' + ref: "${{ steps.versiontrick.outputs.version }}" + repository: 'DanySK/Template-for-Kotlin-Multiplatform-Projects' + submodules: 'recursive' + - name: Checkout publish-on-central + uses: actions/checkout@v3.3.0 + with: + path: 'publish-on-central' + - name: Dry-deploy + uses: DanySK/build-check-deploy-gradle-action@2.1.26 + with: + build-command: true + check-command: true + deploy-command: | + ./gradlew --include-build ../publish-on-central createStagingRepositoryOnMavenCentral --parallel + [[ -e "build/staging-repo-ids.properties" ]] || (echo "No staging repo ID found" && exit 1) + REPO_ID="$(cat build/staging-repo-ids.properties)" + ./gradlew --include-build ../publish-on-central -PstagingRepoId="$REPO_ID" dropStagingRepositoryOnMavenCentral --parallel + working-directory: kt-mp-drop-task + should-run-codecov: false + should-deploy: true + maven-central-password: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} + signing-key: ${{ secrets.SIGNING_KEY }} + signing-password: ${{ secrets.SIGNING_PASSWORD }} release: needs: - build - test-alchemist-deployment - test-kt-multiplatform-deployment - test-multi-stage-deployment + - test-drop-repo-task-regression runs-on: ubuntu-latest if: >- !github.event.repository.fork @@ -235,6 +286,7 @@ jobs: - test-alchemist-deployment - test-kt-multiplatform-deployment - test-multi-stage-deployment + - test-drop-repo-task-regression if: >- always() && ( contains(join(needs.*.result, ','), 'failure') diff --git a/src/main/kotlin/org/danilopianini/gradle/mavencentral/Configuration.kt b/src/main/kotlin/org/danilopianini/gradle/mavencentral/Configuration.kt index f0d5a836..f4b683d6 100644 --- a/src/main/kotlin/org/danilopianini/gradle/mavencentral/Configuration.kt +++ b/src/main/kotlin/org/danilopianini/gradle/mavencentral/Configuration.kt @@ -101,6 +101,9 @@ private fun Project.configureNexusRepository(repoToConfigure: Repository, nexusU repoToConfigure, nexusUrl, ) as InitializeNexusClient + /* + * Creates a new staging repository on the Nexus server, or fetches an existing one if the repoId is known. + */ val createStagingRepository = rootProject.registerTaskIfNeeded( "createStagingRepositoryOn${repoToConfigure.name}" ) { @@ -118,11 +121,19 @@ private fun Project.configureNexusRepository(repoToConfigure: Repository, nexusU group = PublishingPlugin.PUBLISH_TASK_GROUP description = "Creates a new Nexus staging repository on ${repoToConfigure.name}." } + /* + * Collector of all upload tasks. Actual uploads are defined at the bottom. + * Requires the creation of the staging repository. + */ val uploadAllPublications = tasks.register("uploadAllPublicationsTo${repoToConfigure.name}Nexus") { it.dependsOn(createStagingRepository) it.group = PublishingPlugin.PUBLISH_TASK_GROUP it.description = "Uploads all publications to a staging repository on ${repoToConfigure.name}." } + /* + * Closes the staging repository. If it's closed already, skips the operation. + * Runs after all uploads. Requires the creation of the staging repository. + */ val closeStagingRepository = rootProject.registerTaskIfNeeded( "closeStagingRepositoryOn${repoToConfigure.name}" ) { @@ -140,19 +151,32 @@ private fun Project.configureNexusRepository(repoToConfigure: Repository, nexusU group = PublishingPlugin.PUBLISH_TASK_GROUP description = "Closes the Nexus repository on ${repoToConfigure.name}." } + /* + * Releases the staging repository. Requires closing. + */ val release = rootProject.registerTaskIfNeeded("releaseStagingRepositoryOn${repoToConfigure.name}") { doLast { nexusClient.nexusClient.release() } dependsOn(closeStagingRepository) group = PublishingPlugin.PUBLISH_TASK_GROUP description = "Releases the Nexus repo on ${repoToConfigure.name}. Incompatible with dropping the same repo." } + /* + * Drops the staging repository. + * Requires the creation of the staging repository. + * It must run after all uploads. + * If closing is requested as well, drop must run after it. + */ val drop = rootProject.registerTaskIfNeeded("dropStagingRepositoryOn${repoToConfigure.name}") { doLast { nexusClient.nexusClient.drop() } + dependsOn(createStagingRepository) mustRunAfter(uploadAllPublications) mustRunAfter(closeStagingRepository) group = PublishingPlugin.PUBLISH_TASK_GROUP description = "Drops the Nexus repo on ${repoToConfigure.name}. Incompatible with releasing the same repo." } + /* + * Checks that only release or drop are selected for execution, as they are mutually exclusive. + */ gradle.taskGraph.whenReady { if (it.hasTask(release) && it.hasTask(drop)) { error( @@ -181,9 +205,16 @@ private fun Project.configureNexusRepository(repoToConfigure: Repository, nexusU tasks.withType().forEach { uploadTask.mustRunAfter(it) } + /* + * We need to make sure that the staging repository is created before we upload anything. + * We also need to make sure that the staging repository is closed *after* we upload + * We also need to make sure that the staging repository is dropped *after* we upload + * Releasing does not need to be explicitly ordered, as it will be performed after closing + */ uploadTask.dependsOn(createStagingRepository) uploadAllPublications.get().dependsOn(uploadTask) closeStagingRepository.mustRunAfter(uploadTask) + drop.mustRunAfter(uploadTask) uploadTask.doFirst { warnIfCredentialsAreMissing(repoToConfigure) uploadTask.repository.url = nexusClient.nexusClient.repoUrl