From 62675013acd3f9eb2608a810d43f96f635af7f9a Mon Sep 17 00:00:00 2001 From: Matas Lauzadis Date: Wed, 6 Aug 2025 14:14:40 -0400 Subject: [PATCH 1/4] Add back configureNexus function --- .../aws/sdk/kotlin/gradle/dsl/Publish.kt | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/build-plugins/build-support/src/main/kotlin/aws/sdk/kotlin/gradle/dsl/Publish.kt b/build-plugins/build-support/src/main/kotlin/aws/sdk/kotlin/gradle/dsl/Publish.kt index eb2efa1..3a8e7b3 100644 --- a/build-plugins/build-support/src/main/kotlin/aws/sdk/kotlin/gradle/dsl/Publish.kt +++ b/build-plugins/build-support/src/main/kotlin/aws/sdk/kotlin/gradle/dsl/Publish.kt @@ -143,6 +143,43 @@ fun Project.configurePublishing(repoName: String, githubOrganization: String = " } } +/** + * Configure nexus publishing plugin. This (conditionally) enables the `gradle-nexus.publish-plugin` and configures it. + */ +fun Project.configureNexus( + nexusUrl: String = "https://ossrh-staging-api.central.sonatype.com/service/local/", + snapshotRepositoryUrl: String = "https://central.sonatype.com/repository/maven-snapshots/", +) { + verifyRootProject { "Kotlin SDK nexus configuration must be applied to the root project only" } + + val requiredProps = listOf(SONATYPE_USERNAME_PROP, SONATYPE_PASSWORD_PROP, PUBLISH_GROUP_NAME_PROP) + val doConfigure = requiredProps.all { project.hasProperty(it) } + if (!doConfigure) { + logger.info("skipping nexus configuration, missing one or more required properties: $requiredProps") + return + } + + apply(plugin = "io.github.gradle-nexus.publish-plugin") + extensions.configure { + val publishGroupName = project.property(PUBLISH_GROUP_NAME_PROP) as String + group = publishGroupName + packageGroup.set(publishGroupName) + repositories { + create("awsNexus") { + this.nexusUrl.set(uri(nexusUrl)) + this.snapshotRepositoryUrl.set(uri(snapshotRepositoryUrl)) + username.set(project.property(SONATYPE_USERNAME_PROP) as String) + password.set(project.property(SONATYPE_PASSWORD_PROP) as String) + } + } + + transitionCheckOptions { + maxRetries.set(180) + delayBetween.set(Duration.ofSeconds(10)) + } + } +} + /** * Configure JReleaser publishing plugin. This (conditionally) enables the `org.jreleaser` plugin and configures it. */ From f96b2ce9b8ce056c66b727636e3c79b3ee11d020 Mon Sep 17 00:00:00 2001 From: Matas Lauzadis Date: Wed, 6 Aug 2025 14:14:46 -0400 Subject: [PATCH 2/4] Add allDeps task --- build.gradle.kts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index a75dc57..c281005 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,6 +13,11 @@ if (releaseVersion == null) logger.warn("no release version set") val s3Url = propertyOrEnv("release.s3.url", "RELEASE_S3_URL") if (s3Url == null) logger.warn("S3 repository not configured, missing S3 url") +allprojects { + // Enables running `./gradlew allDeps` to get a comprehensive list of dependencies for every subproject + tasks.register("allDeps") { } +} + subprojects { group = "aws.sdk.kotlin.gradle" version = releaseVersion ?: "0.0.1" From 67d36e1f3d98b4311df1a31b826a3cbeeb84ace1 Mon Sep 17 00:00:00 2001 From: Matas Lauzadis Date: Wed, 6 Aug 2025 14:27:06 -0400 Subject: [PATCH 3/4] Add back `configureNexus` and the Nexus flavor of `configurePublishing` for aws-sdk-kotlin --- .../aws/sdk/kotlin/gradle/dsl/Publish.kt | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/build-plugins/build-support/src/main/kotlin/aws/sdk/kotlin/gradle/dsl/Publish.kt b/build-plugins/build-support/src/main/kotlin/aws/sdk/kotlin/gradle/dsl/Publish.kt index 3a8e7b3..b3d617a 100644 --- a/build-plugins/build-support/src/main/kotlin/aws/sdk/kotlin/gradle/dsl/Publish.kt +++ b/build-plugins/build-support/src/main/kotlin/aws/sdk/kotlin/gradle/dsl/Publish.kt @@ -5,6 +5,7 @@ package aws.sdk.kotlin.gradle.dsl import aws.sdk.kotlin.gradle.util.verifyRootProject +import io.github.gradlenexus.publishplugin.NexusPublishExtension import org.gradle.api.Project import org.gradle.api.publish.PublishingExtension import org.gradle.api.publish.maven.MavenPublication @@ -15,11 +16,19 @@ import org.gradle.plugins.signing.Sign import org.gradle.plugins.signing.SigningExtension import org.jreleaser.gradle.plugin.JReleaserExtension import org.jreleaser.model.Active +import java.time.Duration private object Properties { const val SKIP_PUBLISHING = "skipPublish" } +// TODO Remove once aws-sdk-kotlin migrates to Central Portal +private const val PUBLISH_GROUP_NAME_PROP = "publishGroupName" +private const val SIGNING_KEY_PROP = "signingKey" +private const val SIGNING_PASSWORD_PROP = "signingPassword" +private const val SONATYPE_USERNAME_PROP = "sonatypeUsername" +private const val SONATYPE_PASSWORD_PROP = "sonatypePassword" + private object EnvironmentVariables { const val GROUP_ID = "JRELEASER_PROJECT_JAVA_GROUP_ID" const val MAVEN_CENTRAL_USERNAME = "JRELEASER_MAVENCENTRAL_USERNAME" @@ -55,6 +64,102 @@ fun Project.skipPublishing() { extra.set(Properties.SKIP_PUBLISHING, true) } +// TODO Remove this once aws-sdk-kotlin migrates to Central Portal +fun Project.configureNexusPublishing(repoName: String, githubOrganization: String = "awslabs") { + val project = this + apply(plugin = "maven-publish") + + // FIXME: create a real "javadoc" JAR from Dokka output + val javadocJar = tasks.register("emptyJar") { + archiveClassifier.set("javadoc") + destinationDirectory.set(layout.buildDirectory.dir("libs")) + from() + } + + extensions.configure { + repositories { + maven { + name = "testLocal" + url = rootProject.layout.buildDirectory.dir("m2").get().asFile.toURI() + } + } + + publications.all { + if (this !is MavenPublication) return@all + + project.afterEvaluate { + pom { + name.set(project.name) + description.set(project.description) + url.set("https://github.com/$githubOrganization/$repoName") + licenses { + license { + name.set("Apache-2.0") + url.set("https://www.apache.org/licenses/LICENSE-2.0.txt") + } + } + developers { + developer { + id.set(repoName) + name.set("AWS SDK Kotlin Team") + } + } + scm { + connection.set("scm:git:git://github.com/$githubOrganization/$repoName.git") + developerConnection.set("scm:git:ssh://github.com/$githubOrganization/$repoName.git") + url.set("https://github.com/$githubOrganization/$repoName") + } + + artifact(javadocJar) + } + } + } + + if (project.hasProperty(SIGNING_KEY_PROP) && project.hasProperty(SIGNING_PASSWORD_PROP)) { + apply(plugin = "signing") + extensions.configure { + useInMemoryPgpKeys( + project.property(SIGNING_KEY_PROP) as String, + project.property(SIGNING_PASSWORD_PROP) as String, + ) + sign(publications) + } + + // FIXME - workaround for https://github.com/gradle/gradle/issues/26091 + val signingTasks = tasks.withType() + tasks.withType().configureEach { + mustRunAfter(signingTasks) + } + } + } + + fun isAvailableForNexusPublication(project: Project, publication: MavenPublication): Boolean { + var shouldPublish = true + + // Check SKIP_PUBLISH_PROP + if (project.extra.has(Properties.SKIP_PUBLISHING)) shouldPublish = false + + // Only publish publications with the configured group from JReleaser or everything if JReleaser group is not configured + val publishGroupName = project.findProperty(PUBLISH_GROUP_NAME_PROP) as? String + shouldPublish = shouldPublish && (publishGroupName == null || publication.groupId.startsWith(publishGroupName)) + + // Validate publication name is allowed to be published + shouldPublish = shouldPublish && ALLOWED_PUBLICATION_NAMES.any { publication.name.equals(it, ignoreCase = true) } + + return shouldPublish + } + + tasks.withType().configureEach { + onlyIf { + isAvailableForNexusPublication(project, publication).also { + if (!it) { + logger.warn("Skipping publication, project=${project.name}; publication=${publication.name}; group=${publication.groupId}") + } + } + } + } +} + /** * Configure publishing for this project. This applies the `maven-publish` and `signing` plugins and configures * the publications. From f2e707f26419391bddd37830af8df9abe0b56315 Mon Sep 17 00:00:00 2001 From: Matas Lauzadis Date: Wed, 6 Aug 2025 14:27:19 -0400 Subject: [PATCH 4/4] Add back `configureNexus` and the Nexus flavor of `configurePublishing` for aws-sdk-kotlin --- build-plugins/build-support/build.gradle.kts | 3 ++- gradle/libs.versions.toml | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/build-plugins/build-support/build.gradle.kts b/build-plugins/build-support/build.gradle.kts index f1ee43a..1c9e3dd 100644 --- a/build-plugins/build-support/build.gradle.kts +++ b/build-plugins/build-support/build.gradle.kts @@ -24,7 +24,8 @@ dependencies { exclude(group = "org.jetbrains.kotlin", module = "kotlin-compiler-embeddable") } - implementation(libs.jReleaserPlugin) + implementation(libs.nexus.publish.plugin) + implementation(libs.jreleaser.plugin) compileOnly(gradleApi()) implementation(libs.aws.sdk.s3) implementation(libs.aws.sdk.cloudwatch) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index da7c486..6fdad8d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,6 +2,7 @@ aws-sdk-version = "1.4.116" kotlin-version = "2.2.0" ktlint = "1.3.0" +nexus-plugin-version = "2.0.0" jreleaser-plugin-version = "1.18.0" publish-plugin-version = "1.3.1" smithy-version = "1.60.2" @@ -14,7 +15,8 @@ aws-sdk-s3 = { module = "aws.sdk.kotlin:s3", version.ref = "aws-sdk-version" } ktlint-cli = { module = "com.pinterest.ktlint:ktlint-cli", version.ref = "ktlint" } ktlint-cli-ruleset-core = { module = "com.pinterest.ktlint:ktlint-cli-ruleset-core", version.ref = "ktlint" } ktlint-test = {module = "com.pinterest.ktlint:ktlint-test", version.ref = "ktlint" } -jReleaserPlugin = { module = "org.jreleaser:jreleaser-gradle-plugin", version.ref = "jreleaser-plugin-version" } +nexus-publish-plugin = { module = "io.github.gradle-nexus:publish-plugin", version.ref = "nexus-plugin-version" } +jreleaser-plugin = { module = "org.jreleaser:jreleaser-gradle-plugin", version.ref = "jreleaser-plugin-version" } smithy-model = { module = "software.amazon.smithy:smithy-model", version.ref = "smithy-version" } smithy-gradle-base-plugin = { module = "software.amazon.smithy.gradle:smithy-base", version.ref = "smithy-gradle-plugin-version" }