From adf32d005c52d69a86ce3728a8f1eb53a9936fad Mon Sep 17 00:00:00 2001 From: Martin Bonnin Date: Sun, 21 Jun 2026 15:21:31 +0200 Subject: [PATCH 1/6] Add publishAllChecksums --- docs/src/content/docs/index.mdx | 3 +++ librarian.root.properties | 2 +- nmcp/api/nmcp.api | 2 ++ .../kotlin/nmcp/NmcpAggregationExtension.kt | 10 +++++++++ nmcp/src/main/kotlin/nmcp/NmcpExtension.kt | 11 ++++++++++ .../DefaultNmcpAggregationExtension.kt | 5 ++++- .../nmcp/internal/DefaultNmcpExtension.kt | 3 ++- nmcp/src/main/kotlin/nmcp/internal/utils.kt | 22 ++++++++++++++----- tests/jvm/build.gradle.kts | 12 +++------- tests/jvm/settings.gradle.kts | 5 +++++ 10 files changed, 58 insertions(+), 17 deletions(-) diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx index 629b4a3..c907c1c 100644 --- a/docs/src/content/docs/index.mdx +++ b/docs/src/content/docs/index.mdx @@ -54,6 +54,9 @@ nmcpSettings { // optional: send publications serially instead of in parallel (might be slower) uploadSnapshotsParallelism.set(1) + + // optional: publish all checksums (md5, sha1, sha256, sha512, including for signature files) + publishAllChecksums.set(true) } } ``` diff --git a/librarian.root.properties b/librarian.root.properties index aca5be6..f0d2417 100644 --- a/librarian.root.properties +++ b/librarian.root.properties @@ -6,7 +6,7 @@ kdoc.olderVersions= kdoc.artifactId=kdoc pom.groupId=com.gradleup.nmcp -pom.version=1.5.1-SNAPSHOT +pom.version=1.6.0-SNAPSHOT pom.description=New Maven Central Publishing pom.vcsUrl=https://github.com/gradleup/nmcp pom.developer=nmcp authors diff --git a/nmcp/api/nmcp.api b/nmcp/api/nmcp.api index c9c7012..a519be8 100644 --- a/nmcp/api/nmcp.api +++ b/nmcp/api/nmcp.api @@ -21,12 +21,14 @@ public abstract interface class nmcp/NmcpAggregationExtension { public abstract fun getAllFiles ()Lorg/gradle/api/file/FileCollection; public abstract fun getAllowDuplicateProjectNames ()Lorg/gradle/api/provider/Property; public abstract fun getAllowEmptyAggregation ()Lorg/gradle/api/provider/Property; + public abstract fun getPublishAllChecksums ()Lorg/gradle/api/provider/Property; public abstract fun localRepository (Lorg/gradle/api/Action;)V public abstract fun publishAllProjectsProbablyBreakingProjectIsolation ()V } public abstract interface class nmcp/NmcpExtension { public abstract fun extraFiles (Ljava/lang/Object;)V + public abstract fun getPublishAllChecksums ()Lorg/gradle/api/provider/Property; public abstract fun publishAllPublicationsToCentralPortal (Lorg/gradle/api/Action;)V } diff --git a/nmcp/src/main/kotlin/nmcp/NmcpAggregationExtension.kt b/nmcp/src/main/kotlin/nmcp/NmcpAggregationExtension.kt index df372da..653cf27 100644 --- a/nmcp/src/main/kotlin/nmcp/NmcpAggregationExtension.kt +++ b/nmcp/src/main/kotlin/nmcp/NmcpAggregationExtension.kt @@ -58,4 +58,14 @@ interface NmcpAggregationExtension { * See https://github.com/gradle/gradle/issues/36167 for more details. */ val allowDuplicateProjectNames: Property + + /** + * By default, Nmcp tries to avoid publishing the checksums. + * Especially, it filters out the `.sha256` and `.sha512` files, as well as all the signature checksums + * (`.asc.md5`, `.asc.sha1`, `.asc.sha256`, `.asc.sha512`). + * This is to play nicer with [Maven Central publishing limits](https://central.sonatype.org/publish/maven-central-publishing-limits/). + * + * Default: false + */ + val publishAllChecksums: Property } diff --git a/nmcp/src/main/kotlin/nmcp/NmcpExtension.kt b/nmcp/src/main/kotlin/nmcp/NmcpExtension.kt index d7eee30..0c25310 100644 --- a/nmcp/src/main/kotlin/nmcp/NmcpExtension.kt +++ b/nmcp/src/main/kotlin/nmcp/NmcpExtension.kt @@ -2,6 +2,7 @@ package nmcp import org.gradle.api.Action import org.gradle.api.file.FileCollection +import org.gradle.api.provider.Property interface NmcpExtension { /** @@ -25,4 +26,14 @@ interface NmcpExtension { * a [org.gradle.api.file.DirectoryProperty] so that the files also contain their relative path. */ fun extraFiles(files: Any) + + /** + * By default, Nmcp tries to avoid publishing the checksums. + * Especially, it filters out the `.sha256` and `.sha512` files, as well as all the signature checksums + * (`.asc.md5`, `.asc.sha1`, `.asc.sha256`, `.asc.sha512`). + * This is to play nicer with [Maven Central publishing limits](https://central.sonatype.org/publish/maven-central-publishing-limits/). + * + * Default: false + */ + val publishAllChecksums: Property } diff --git a/nmcp/src/main/kotlin/nmcp/internal/DefaultNmcpAggregationExtension.kt b/nmcp/src/main/kotlin/nmcp/internal/DefaultNmcpAggregationExtension.kt index b2130c1..c3caca5 100644 --- a/nmcp/src/main/kotlin/nmcp/internal/DefaultNmcpAggregationExtension.kt +++ b/nmcp/src/main/kotlin/nmcp/internal/DefaultNmcpAggregationExtension.kt @@ -47,7 +47,8 @@ internal abstract class DefaultNmcpAggregationExtension(private val project: Pro kind = Kind.aggregation, inputFiles = allFiles, spec = spec, - allowEmptyFiles = allowEmptyAggregation + allowEmptyFiles = allowEmptyAggregation, + publishAllChecksums = publishAllChecksums, ) project.afterEvaluate { @@ -100,6 +101,8 @@ internal abstract class DefaultNmcpAggregationExtension(private val project: Pro abstract override val allowEmptyAggregation: Property + abstract override val publishAllChecksums: Property + abstract override val allowDuplicateProjectNames: Property } diff --git a/nmcp/src/main/kotlin/nmcp/internal/DefaultNmcpExtension.kt b/nmcp/src/main/kotlin/nmcp/internal/DefaultNmcpExtension.kt index c49eb4c..a90a5ea 100644 --- a/nmcp/src/main/kotlin/nmcp/internal/DefaultNmcpExtension.kt +++ b/nmcp/src/main/kotlin/nmcp/internal/DefaultNmcpExtension.kt @@ -77,7 +77,8 @@ internal abstract class DefaultNmcpExtension(private val project: Project): Nmcp kind = Kind.allPublications, inputFiles = m2Files, spec = spec, - allowEmptyFiles = project.provider { false } + allowEmptyFiles = project.provider { false }, + publishAllChecksums = publishAllChecksums, ) } } diff --git a/nmcp/src/main/kotlin/nmcp/internal/utils.kt b/nmcp/src/main/kotlin/nmcp/internal/utils.kt index 93225dc..19def48 100644 --- a/nmcp/src/main/kotlin/nmcp/internal/utils.kt +++ b/nmcp/src/main/kotlin/nmcp/internal/utils.kt @@ -53,7 +53,8 @@ internal fun Project.registerPublishToCentralPortalTasks( kind: Kind, inputFiles: FileCollection, spec: CentralPortalOptions, - allowEmptyFiles: Provider + allowEmptyFiles: Provider, + publishAllChecksums: Provider ) { val name = kind.name @@ -78,16 +79,27 @@ internal fun Project.registerPublishToCentralPortalTasks( inputFiles = inputFiles, ) + val publishAllChecksums = publishAllChecksums.getOrElse(false) val zipName = "${name}.zip" val zipTaskProvider = tasks.register(zipTaskName, Zip::class.java) { it.from(inputFiles) it.destinationDirectory.set(project.layout.buildDirectory.dir("nmcp/zip")) it.archiveFileName.set(zipName) it.eachFile { - // Exclude maven-metadata files, or the bundle is not recognized - // See https://slack-chats.kotlinlang.org/t/16407246/anyone-tried-the-https-central-sonatype-org-publish-publish-#c8738fe5-8051-4f64-809f-ca67a645216e - if (it.name.startsWith("maven-metadata")) { - it.exclude() + when { + it.name.startsWith("maven-metadata") -> { + // Exclude maven-metadata files, or the bundle is not recognized + // See https://slack-chats.kotlinlang.org/t/16407246/anyone-tried-the-https-central-sonatype-org-publish-publish-#c8738fe5-8051-4f64-809f-ca67a645216e + it.exclude() + } + !publishAllChecksums && (it.name.endsWith(".sha256") || it.name.endsWith(".sha512")) -> { + // It's not clear if those are used, and it reduces the number of files in the deployment + it.exclude() + } + !publishAllChecksums && (it.name.endsWith(".asc.md5") || it.name.endsWith(".asc.sha1")) -> { + // It's not clear if those are used, and it reduces the number of files in the deployment + it.exclude() + } } } it.dependsOn(checkFilesTaskProvider) diff --git a/tests/jvm/build.gradle.kts b/tests/jvm/build.gradle.kts index 3f20d02..7696f47 100644 --- a/tests/jvm/build.gradle.kts +++ b/tests/jvm/build.gradle.kts @@ -3,16 +3,9 @@ import nmcp.NmcpAggregationExtension plugins { id("base") alias(libs.plugins.kgp).apply(false) + id("com.gradleup.nmcp.aggregation") } -buildscript { - dependencies { - classpath("com.gradleup.nmcp:nmcp") - } -} - -apply(plugin = "com.gradleup.nmcp.aggregation") - group = "net.mbonnin.tnmcp" version = "0.0.3" @@ -85,7 +78,8 @@ subprojects { } } -extensions.getByType().apply { +nmcpAggregation { + @Suppress("DEPRECATION") publishAllProjectsProbablyBreakingProjectIsolation() centralPortal { diff --git a/tests/jvm/settings.gradle.kts b/tests/jvm/settings.gradle.kts index 616ae40..bc1e13b 100644 --- a/tests/jvm/settings.gradle.kts +++ b/tests/jvm/settings.gradle.kts @@ -4,8 +4,13 @@ pluginManagement { mavenCentral() } } + includeBuild("../../") } includeBuild("../../") +plugins { + id("com.gradleup.nmcp.settings").apply(false) +} + include(":module1", ":module2") From 8b2be655bd6cb0226dd5a0e08283cb120bc07712 Mon Sep 17 00:00:00 2001 From: Martin Bonnin Date: Sun, 21 Jun 2026 15:54:49 +0200 Subject: [PATCH 2/6] Update tests --- tests/kmp/build.gradle.kts | 68 -------------------------------------- 1 file changed, 68 deletions(-) diff --git a/tests/kmp/build.gradle.kts b/tests/kmp/build.gradle.kts index 106857b..ef0461d 100644 --- a/tests/kmp/build.gradle.kts +++ b/tests/kmp/build.gradle.kts @@ -80,187 +80,119 @@ tasks.register("checkZip") { "sample/kmp/module1-js/0.0.1/module1-js-0.0.1-sources.jar", "sample/kmp/module1-js/0.0.1/module1-js-0.0.1-sources.jar.md5", "sample/kmp/module1-js/0.0.1/module1-js-0.0.1-sources.jar.sha1", - "sample/kmp/module1-js/0.0.1/module1-js-0.0.1-sources.jar.sha256", - "sample/kmp/module1-js/0.0.1/module1-js-0.0.1-sources.jar.sha512", "sample/kmp/module1-js/0.0.1/module1-js-0.0.1.klib", "sample/kmp/module1-js/0.0.1/module1-js-0.0.1.klib.md5", "sample/kmp/module1-js/0.0.1/module1-js-0.0.1.klib.sha1", - "sample/kmp/module1-js/0.0.1/module1-js-0.0.1.klib.sha256", - "sample/kmp/module1-js/0.0.1/module1-js-0.0.1.klib.sha512", "sample/kmp/module1-js/0.0.1/module1-js-0.0.1.module", "sample/kmp/module1-js/0.0.1/module1-js-0.0.1.module.md5", "sample/kmp/module1-js/0.0.1/module1-js-0.0.1.module.sha1", - "sample/kmp/module1-js/0.0.1/module1-js-0.0.1.module.sha256", - "sample/kmp/module1-js/0.0.1/module1-js-0.0.1.module.sha512", "sample/kmp/module1-js/0.0.1/module1-js-0.0.1.pom", "sample/kmp/module1-js/0.0.1/module1-js-0.0.1.pom.md5", "sample/kmp/module1-js/0.0.1/module1-js-0.0.1.pom.sha1", - "sample/kmp/module1-js/0.0.1/module1-js-0.0.1.pom.sha256", - "sample/kmp/module1-js/0.0.1/module1-js-0.0.1.pom.sha512", "sample/kmp/module1-jvm/", "sample/kmp/module1-jvm/0.0.1/", "sample/kmp/module1-jvm/0.0.1/module1-jvm-0.0.1-sources.jar", "sample/kmp/module1-jvm/0.0.1/module1-jvm-0.0.1-sources.jar.md5", "sample/kmp/module1-jvm/0.0.1/module1-jvm-0.0.1-sources.jar.sha1", - "sample/kmp/module1-jvm/0.0.1/module1-jvm-0.0.1-sources.jar.sha256", - "sample/kmp/module1-jvm/0.0.1/module1-jvm-0.0.1-sources.jar.sha512", "sample/kmp/module1-jvm/0.0.1/module1-jvm-0.0.1.jar", "sample/kmp/module1-jvm/0.0.1/module1-jvm-0.0.1.jar.md5", "sample/kmp/module1-jvm/0.0.1/module1-jvm-0.0.1.jar.sha1", - "sample/kmp/module1-jvm/0.0.1/module1-jvm-0.0.1.jar.sha256", - "sample/kmp/module1-jvm/0.0.1/module1-jvm-0.0.1.jar.sha512", "sample/kmp/module1-jvm/0.0.1/module1-jvm-0.0.1.module", "sample/kmp/module1-jvm/0.0.1/module1-jvm-0.0.1.module.md5", "sample/kmp/module1-jvm/0.0.1/module1-jvm-0.0.1.module.sha1", - "sample/kmp/module1-jvm/0.0.1/module1-jvm-0.0.1.module.sha256", - "sample/kmp/module1-jvm/0.0.1/module1-jvm-0.0.1.module.sha512", "sample/kmp/module1-jvm/0.0.1/module1-jvm-0.0.1.pom", "sample/kmp/module1-jvm/0.0.1/module1-jvm-0.0.1.pom.md5", "sample/kmp/module1-jvm/0.0.1/module1-jvm-0.0.1.pom.sha1", - "sample/kmp/module1-jvm/0.0.1/module1-jvm-0.0.1.pom.sha256", - "sample/kmp/module1-jvm/0.0.1/module1-jvm-0.0.1.pom.sha512", "sample/kmp/module1-linuxarm64/", "sample/kmp/module1-linuxarm64/0.0.1/", "sample/kmp/module1-linuxarm64/0.0.1/module1-linuxarm64-0.0.1-sources.jar", "sample/kmp/module1-linuxarm64/0.0.1/module1-linuxarm64-0.0.1-sources.jar.md5", "sample/kmp/module1-linuxarm64/0.0.1/module1-linuxarm64-0.0.1-sources.jar.sha1", - "sample/kmp/module1-linuxarm64/0.0.1/module1-linuxarm64-0.0.1-sources.jar.sha256", - "sample/kmp/module1-linuxarm64/0.0.1/module1-linuxarm64-0.0.1-sources.jar.sha512", "sample/kmp/module1-linuxarm64/0.0.1/module1-linuxarm64-0.0.1.klib", "sample/kmp/module1-linuxarm64/0.0.1/module1-linuxarm64-0.0.1.klib.md5", "sample/kmp/module1-linuxarm64/0.0.1/module1-linuxarm64-0.0.1.klib.sha1", - "sample/kmp/module1-linuxarm64/0.0.1/module1-linuxarm64-0.0.1.klib.sha256", - "sample/kmp/module1-linuxarm64/0.0.1/module1-linuxarm64-0.0.1.klib.sha512", "sample/kmp/module1-linuxarm64/0.0.1/module1-linuxarm64-0.0.1.module", "sample/kmp/module1-linuxarm64/0.0.1/module1-linuxarm64-0.0.1.module.md5", "sample/kmp/module1-linuxarm64/0.0.1/module1-linuxarm64-0.0.1.module.sha1", - "sample/kmp/module1-linuxarm64/0.0.1/module1-linuxarm64-0.0.1.module.sha256", - "sample/kmp/module1-linuxarm64/0.0.1/module1-linuxarm64-0.0.1.module.sha512", "sample/kmp/module1-linuxarm64/0.0.1/module1-linuxarm64-0.0.1.pom", "sample/kmp/module1-linuxarm64/0.0.1/module1-linuxarm64-0.0.1.pom.md5", "sample/kmp/module1-linuxarm64/0.0.1/module1-linuxarm64-0.0.1.pom.sha1", - "sample/kmp/module1-linuxarm64/0.0.1/module1-linuxarm64-0.0.1.pom.sha256", - "sample/kmp/module1-linuxarm64/0.0.1/module1-linuxarm64-0.0.1.pom.sha512", "sample/kmp/module1/", "sample/kmp/module1/0.0.1/", "sample/kmp/module1/0.0.1/module1-0.0.1-kotlin-tooling-metadata.json", "sample/kmp/module1/0.0.1/module1-0.0.1-kotlin-tooling-metadata.json.md5", "sample/kmp/module1/0.0.1/module1-0.0.1-kotlin-tooling-metadata.json.sha1", - "sample/kmp/module1/0.0.1/module1-0.0.1-kotlin-tooling-metadata.json.sha256", - "sample/kmp/module1/0.0.1/module1-0.0.1-kotlin-tooling-metadata.json.sha512", "sample/kmp/module1/0.0.1/module1-0.0.1-sources.jar", "sample/kmp/module1/0.0.1/module1-0.0.1-sources.jar.md5", "sample/kmp/module1/0.0.1/module1-0.0.1-sources.jar.sha1", - "sample/kmp/module1/0.0.1/module1-0.0.1-sources.jar.sha256", - "sample/kmp/module1/0.0.1/module1-0.0.1-sources.jar.sha512", "sample/kmp/module1/0.0.1/module1-0.0.1.jar", "sample/kmp/module1/0.0.1/module1-0.0.1.jar.md5", "sample/kmp/module1/0.0.1/module1-0.0.1.jar.sha1", - "sample/kmp/module1/0.0.1/module1-0.0.1.jar.sha256", - "sample/kmp/module1/0.0.1/module1-0.0.1.jar.sha512", "sample/kmp/module1/0.0.1/module1-0.0.1.module", "sample/kmp/module1/0.0.1/module1-0.0.1.module.md5", "sample/kmp/module1/0.0.1/module1-0.0.1.module.sha1", - "sample/kmp/module1/0.0.1/module1-0.0.1.module.sha256", - "sample/kmp/module1/0.0.1/module1-0.0.1.module.sha512", "sample/kmp/module1/0.0.1/module1-0.0.1.pom", "sample/kmp/module1/0.0.1/module1-0.0.1.pom.md5", "sample/kmp/module1/0.0.1/module1-0.0.1.pom.sha1", - "sample/kmp/module1/0.0.1/module1-0.0.1.pom.sha256", - "sample/kmp/module1/0.0.1/module1-0.0.1.pom.sha512", "sample/kmp/module2-js/", "sample/kmp/module2-js/0.0.1/", "sample/kmp/module2-js/0.0.1/module2-js-0.0.1-sources.jar", "sample/kmp/module2-js/0.0.1/module2-js-0.0.1-sources.jar.md5", "sample/kmp/module2-js/0.0.1/module2-js-0.0.1-sources.jar.sha1", - "sample/kmp/module2-js/0.0.1/module2-js-0.0.1-sources.jar.sha256", - "sample/kmp/module2-js/0.0.1/module2-js-0.0.1-sources.jar.sha512", "sample/kmp/module2-js/0.0.1/module2-js-0.0.1.klib", "sample/kmp/module2-js/0.0.1/module2-js-0.0.1.klib.md5", "sample/kmp/module2-js/0.0.1/module2-js-0.0.1.klib.sha1", - "sample/kmp/module2-js/0.0.1/module2-js-0.0.1.klib.sha256", - "sample/kmp/module2-js/0.0.1/module2-js-0.0.1.klib.sha512", "sample/kmp/module2-js/0.0.1/module2-js-0.0.1.module", "sample/kmp/module2-js/0.0.1/module2-js-0.0.1.module.md5", "sample/kmp/module2-js/0.0.1/module2-js-0.0.1.module.sha1", - "sample/kmp/module2-js/0.0.1/module2-js-0.0.1.module.sha256", - "sample/kmp/module2-js/0.0.1/module2-js-0.0.1.module.sha512", "sample/kmp/module2-js/0.0.1/module2-js-0.0.1.pom", "sample/kmp/module2-js/0.0.1/module2-js-0.0.1.pom.md5", "sample/kmp/module2-js/0.0.1/module2-js-0.0.1.pom.sha1", - "sample/kmp/module2-js/0.0.1/module2-js-0.0.1.pom.sha256", - "sample/kmp/module2-js/0.0.1/module2-js-0.0.1.pom.sha512", "sample/kmp/module2-jvm/", "sample/kmp/module2-jvm/0.0.1/", "sample/kmp/module2-jvm/0.0.1/module2-jvm-0.0.1-sources.jar", "sample/kmp/module2-jvm/0.0.1/module2-jvm-0.0.1-sources.jar.md5", "sample/kmp/module2-jvm/0.0.1/module2-jvm-0.0.1-sources.jar.sha1", - "sample/kmp/module2-jvm/0.0.1/module2-jvm-0.0.1-sources.jar.sha256", - "sample/kmp/module2-jvm/0.0.1/module2-jvm-0.0.1-sources.jar.sha512", "sample/kmp/module2-jvm/0.0.1/module2-jvm-0.0.1.jar", "sample/kmp/module2-jvm/0.0.1/module2-jvm-0.0.1.jar.md5", "sample/kmp/module2-jvm/0.0.1/module2-jvm-0.0.1.jar.sha1", - "sample/kmp/module2-jvm/0.0.1/module2-jvm-0.0.1.jar.sha256", - "sample/kmp/module2-jvm/0.0.1/module2-jvm-0.0.1.jar.sha512", "sample/kmp/module2-jvm/0.0.1/module2-jvm-0.0.1.module", "sample/kmp/module2-jvm/0.0.1/module2-jvm-0.0.1.module.md5", "sample/kmp/module2-jvm/0.0.1/module2-jvm-0.0.1.module.sha1", - "sample/kmp/module2-jvm/0.0.1/module2-jvm-0.0.1.module.sha256", - "sample/kmp/module2-jvm/0.0.1/module2-jvm-0.0.1.module.sha512", "sample/kmp/module2-jvm/0.0.1/module2-jvm-0.0.1.pom", "sample/kmp/module2-jvm/0.0.1/module2-jvm-0.0.1.pom.md5", "sample/kmp/module2-jvm/0.0.1/module2-jvm-0.0.1.pom.sha1", - "sample/kmp/module2-jvm/0.0.1/module2-jvm-0.0.1.pom.sha256", - "sample/kmp/module2-jvm/0.0.1/module2-jvm-0.0.1.pom.sha512", "sample/kmp/module2-linuxarm64/", "sample/kmp/module2-linuxarm64/0.0.1/", "sample/kmp/module2-linuxarm64/0.0.1/module2-linuxarm64-0.0.1-sources.jar", "sample/kmp/module2-linuxarm64/0.0.1/module2-linuxarm64-0.0.1-sources.jar.md5", "sample/kmp/module2-linuxarm64/0.0.1/module2-linuxarm64-0.0.1-sources.jar.sha1", - "sample/kmp/module2-linuxarm64/0.0.1/module2-linuxarm64-0.0.1-sources.jar.sha256", - "sample/kmp/module2-linuxarm64/0.0.1/module2-linuxarm64-0.0.1-sources.jar.sha512", "sample/kmp/module2-linuxarm64/0.0.1/module2-linuxarm64-0.0.1.klib", "sample/kmp/module2-linuxarm64/0.0.1/module2-linuxarm64-0.0.1.klib.md5", "sample/kmp/module2-linuxarm64/0.0.1/module2-linuxarm64-0.0.1.klib.sha1", - "sample/kmp/module2-linuxarm64/0.0.1/module2-linuxarm64-0.0.1.klib.sha256", - "sample/kmp/module2-linuxarm64/0.0.1/module2-linuxarm64-0.0.1.klib.sha512", "sample/kmp/module2-linuxarm64/0.0.1/module2-linuxarm64-0.0.1.module", "sample/kmp/module2-linuxarm64/0.0.1/module2-linuxarm64-0.0.1.module.md5", "sample/kmp/module2-linuxarm64/0.0.1/module2-linuxarm64-0.0.1.module.sha1", - "sample/kmp/module2-linuxarm64/0.0.1/module2-linuxarm64-0.0.1.module.sha256", - "sample/kmp/module2-linuxarm64/0.0.1/module2-linuxarm64-0.0.1.module.sha512", "sample/kmp/module2-linuxarm64/0.0.1/module2-linuxarm64-0.0.1.pom", "sample/kmp/module2-linuxarm64/0.0.1/module2-linuxarm64-0.0.1.pom.md5", "sample/kmp/module2-linuxarm64/0.0.1/module2-linuxarm64-0.0.1.pom.sha1", - "sample/kmp/module2-linuxarm64/0.0.1/module2-linuxarm64-0.0.1.pom.sha256", - "sample/kmp/module2-linuxarm64/0.0.1/module2-linuxarm64-0.0.1.pom.sha512", "sample/kmp/module2/", "sample/kmp/module2/0.0.1/", "sample/kmp/module2/0.0.1/module2-0.0.1-kotlin-tooling-metadata.json", "sample/kmp/module2/0.0.1/module2-0.0.1-kotlin-tooling-metadata.json.md5", "sample/kmp/module2/0.0.1/module2-0.0.1-kotlin-tooling-metadata.json.sha1", - "sample/kmp/module2/0.0.1/module2-0.0.1-kotlin-tooling-metadata.json.sha256", - "sample/kmp/module2/0.0.1/module2-0.0.1-kotlin-tooling-metadata.json.sha512", "sample/kmp/module2/0.0.1/module2-0.0.1-sources.jar", "sample/kmp/module2/0.0.1/module2-0.0.1-sources.jar.md5", "sample/kmp/module2/0.0.1/module2-0.0.1-sources.jar.sha1", - "sample/kmp/module2/0.0.1/module2-0.0.1-sources.jar.sha256", - "sample/kmp/module2/0.0.1/module2-0.0.1-sources.jar.sha512", "sample/kmp/module2/0.0.1/module2-0.0.1.jar", "sample/kmp/module2/0.0.1/module2-0.0.1.jar.md5", "sample/kmp/module2/0.0.1/module2-0.0.1.jar.sha1", - "sample/kmp/module2/0.0.1/module2-0.0.1.jar.sha256", - "sample/kmp/module2/0.0.1/module2-0.0.1.jar.sha512", "sample/kmp/module2/0.0.1/module2-0.0.1.module", "sample/kmp/module2/0.0.1/module2-0.0.1.module.md5", "sample/kmp/module2/0.0.1/module2-0.0.1.module.sha1", - "sample/kmp/module2/0.0.1/module2-0.0.1.module.sha256", - "sample/kmp/module2/0.0.1/module2-0.0.1.module.sha512", "sample/kmp/module2/0.0.1/module2-0.0.1.pom", "sample/kmp/module2/0.0.1/module2-0.0.1.pom.md5", "sample/kmp/module2/0.0.1/module2-0.0.1.pom.sha1", - "sample/kmp/module2/0.0.1/module2-0.0.1.pom.sha256", - "sample/kmp/module2/0.0.1/module2-0.0.1.pom.sha512", ) ) ) From cf164d1d8684428992bb745f640bf58270c0df38 Mon Sep 17 00:00:00 2001 From: Martin Bonnin Date: Sun, 21 Jun 2026 16:14:24 +0200 Subject: [PATCH 3/6] Add integration test --- scripts/integration-tests.sh | 1 + tests/publish-all-checksums/build.gradle.kts | 71 +++++++++++++++++++ tests/publish-all-checksums/gradle | 1 + tests/publish-all-checksums/gradlew | 1 + .../publish-all-checksums/settings.gradle.kts | 14 ++++ .../src/main/java/com/example/HelloWorld.java | 7 ++ 6 files changed, 95 insertions(+) create mode 100644 tests/publish-all-checksums/build.gradle.kts create mode 120000 tests/publish-all-checksums/gradle create mode 120000 tests/publish-all-checksums/gradlew create mode 100644 tests/publish-all-checksums/settings.gradle.kts create mode 100644 tests/publish-all-checksums/src/main/java/com/example/HelloWorld.java diff --git a/scripts/integration-tests.sh b/scripts/integration-tests.sh index eb2cbe7..ea978c9 100755 --- a/scripts/integration-tests.sh +++ b/scripts/integration-tests.sh @@ -5,3 +5,4 @@ set -x ./gradlew -p tests/kmp publishAggregationToCentralPortal --configuration-cache ./gradlew -p tests/kmp nmcpPublishDeployment -PnmcpDeploymentId=599ab6f5-dd08-4e7b-ae5a-85b45031715a --configuration-cache ./gradlew -p tests/kmp build +./gradlew -p tests/publish-all-checksums build diff --git a/tests/publish-all-checksums/build.gradle.kts b/tests/publish-all-checksums/build.gradle.kts new file mode 100644 index 0000000..bdba6d2 --- /dev/null +++ b/tests/publish-all-checksums/build.gradle.kts @@ -0,0 +1,71 @@ +import nmcp.NmcpAggregationExtension + +plugins { + id("java") + id("com.gradleup.nmcp") + id("maven-publish") + id("signing") + id("com.gradleup.nmcp.aggregation") +} + +group = "net.mbonnin.tnmcp.checksums" +version = "0.0.0-SNAPSHOT" + +publishing { + publications { + create("default", MavenPublication::class.java) { + from(components.getByName("java")) + } + } +} + +signing { + sign(publishing.publications) + // This is a test-only key, it's OK to have it in source control + useInMemoryPgpKeys( + """ + -----BEGIN PGP PRIVATE KEY BLOCK----- + + lFgEajfv+hYJKwYBBAHaRw8BAQdAAtZjfx7pt7TkHKxX6UC9ORR73co/I6+S6t7u + /rXV9wgAAQD634Lubr21SycUMR9XlMopjyAiraFsJhmnlJSEjzUCgA5BtBRUZXN0 + IDx0ZXN0QHRlc3QuY29tPoi1BBMWCgBdFiEEr/qnDkskFs9qzOQsipLIGWOW/iQF + Amo37/obFIAAAAAABAAObWFudTIsMi41KzEuMTIsMCwzAhsDBQkFo5qABQsJCAcC + AiICBhUKCQgLAgQWAgMBAh4HAheAAAoJEIqSyBljlv4kg20A/iDNNgJl3m4cCQoO + mTvvX8QEMnWZLHLpxI69cKZVh36HAQD6eBcof42zc0+6h/xJgkOwFg6F70KIVZv+ + TaqMV1TYBJxdBGo37/oSCisGAQQBl1UBBQEBB0BJYHa33fClfG+p8vhZ4LuBj5Cq + XArQPF/W1ZfAbmTCMQMBCAcAAP9Wk1ssXCVSyeLflcKW+aS8RXgFYTrm8KKwK+A7 + 2GeuwBKKiJoEGBYKAEIWIQSv+qcOSyQWz2rM5CyKksgZY5b+JAUCajfv+hsUgAAA + AAAEAA5tYW51MiwyLjUrMS4xMiwwLDMCGwwFCQWjmoAACgkQipLIGWOW/iRhAQEA + up+FQ86sGGp8oKYCCOS0l5NkgszgJJZYVKCghlSG2G4BAK4hqML04TGh53iXYjFt + KP12LB2cwKyM3On8/1LmBEQC + =PPy4 + -----END PGP PRIVATE KEY BLOCK----- + """.trimIndent(), + "" + ) +} + +val testDirectory = "build/m2" + +nmcpAggregation { + localRepository { + name = "test" + path = testDirectory + } +} + +dependencies { + nmcpAggregation(project) +} + +tasks.named("check") { + dependsOn("nmcpPublishAggregationToTestRepository") + doLast { + check(project.file(testDirectory).walk().any { + it.name.endsWith(".asc.sha512") + }) + check(project.file(testDirectory).walk().any { + it.name.endsWith(".asc.sha256") + }) + } +} \ No newline at end of file diff --git a/tests/publish-all-checksums/gradle b/tests/publish-all-checksums/gradle new file mode 120000 index 0000000..1ce6c4c --- /dev/null +++ b/tests/publish-all-checksums/gradle @@ -0,0 +1 @@ +../../gradle \ No newline at end of file diff --git a/tests/publish-all-checksums/gradlew b/tests/publish-all-checksums/gradlew new file mode 120000 index 0000000..343e0d2 --- /dev/null +++ b/tests/publish-all-checksums/gradlew @@ -0,0 +1 @@ +../../gradlew \ No newline at end of file diff --git a/tests/publish-all-checksums/settings.gradle.kts b/tests/publish-all-checksums/settings.gradle.kts new file mode 100644 index 0000000..78a7346 --- /dev/null +++ b/tests/publish-all-checksums/settings.gradle.kts @@ -0,0 +1,14 @@ +pluginManagement { + listOf(repositories, dependencyResolutionManagement.repositories).forEach { + it.apply { + mavenCentral() + } + } + includeBuild("../../") +} + +includeBuild("../../") + +plugins { + id("com.gradleup.nmcp.settings").apply(false) +} diff --git a/tests/publish-all-checksums/src/main/java/com/example/HelloWorld.java b/tests/publish-all-checksums/src/main/java/com/example/HelloWorld.java new file mode 100644 index 0000000..a7499cf --- /dev/null +++ b/tests/publish-all-checksums/src/main/java/com/example/HelloWorld.java @@ -0,0 +1,7 @@ +package com.example; + +public class HelloWorld { + public static void main(String[] args) { + System.out.println("Hello, World!"); + } +} From 49e3b12daee5dd2e7f22126876ef378d2a350965 Mon Sep 17 00:00:00 2001 From: Martin Bonnin Date: Sun, 21 Jun 2026 17:41:16 +0200 Subject: [PATCH 4/6] Fix integration test --- nmcp/src/main/kotlin/nmcp/NmcpExtension.kt | 10 --- .../DefaultNmcpAggregationExtension.kt | 11 ++- .../nmcp/internal/DefaultNmcpExtension.kt | 2 +- nmcp/src/main/kotlin/nmcp/internal/utils.kt | 12 ++-- scripts/integration-tests.sh | 4 +- tests/jvm/gradle.properties | 1 + tests/kmp/build.gradle.kts | 2 +- tests/kmp/gradle.properties | 2 +- tests/publish-all-checksums/build.gradle.kts | 67 +++++++++++-------- tests/publish-all-checksums/gradle.properties | 1 + 10 files changed, 61 insertions(+), 51 deletions(-) create mode 100644 tests/publish-all-checksums/gradle.properties diff --git a/nmcp/src/main/kotlin/nmcp/NmcpExtension.kt b/nmcp/src/main/kotlin/nmcp/NmcpExtension.kt index 0c25310..e0f0875 100644 --- a/nmcp/src/main/kotlin/nmcp/NmcpExtension.kt +++ b/nmcp/src/main/kotlin/nmcp/NmcpExtension.kt @@ -26,14 +26,4 @@ interface NmcpExtension { * a [org.gradle.api.file.DirectoryProperty] so that the files also contain their relative path. */ fun extraFiles(files: Any) - - /** - * By default, Nmcp tries to avoid publishing the checksums. - * Especially, it filters out the `.sha256` and `.sha512` files, as well as all the signature checksums - * (`.asc.md5`, `.asc.sha1`, `.asc.sha256`, `.asc.sha512`). - * This is to play nicer with [Maven Central publishing limits](https://central.sonatype.org/publish/maven-central-publishing-limits/). - * - * Default: false - */ - val publishAllChecksums: Property } diff --git a/nmcp/src/main/kotlin/nmcp/internal/DefaultNmcpAggregationExtension.kt b/nmcp/src/main/kotlin/nmcp/internal/DefaultNmcpAggregationExtension.kt index c3caca5..bf0d9d1 100644 --- a/nmcp/src/main/kotlin/nmcp/internal/DefaultNmcpAggregationExtension.kt +++ b/nmcp/src/main/kotlin/nmcp/internal/DefaultNmcpAggregationExtension.kt @@ -13,7 +13,10 @@ import org.gradle.api.artifacts.result.ArtifactResult import org.gradle.api.artifacts.result.ResolvedArtifactResult import org.gradle.api.attributes.Usage import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.FileCollection +import org.gradle.api.file.RegularFile import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider @GExtension( pluginId = "com.gradleup.nmcp.aggregation", @@ -32,6 +35,8 @@ internal abstract class DefaultNmcpAggregationExtension(private val project: Pro override val allFiles: ConfigurableFileCollection = project.files() + private val zipProvider: Provider + init { allFiles.from( consumerConfiguration @@ -43,12 +48,12 @@ internal abstract class DefaultNmcpAggregationExtension(private val project: Pro it.filter(::isCompatible).map { it.file } }, ) - project.registerPublishToCentralPortalTasks( + zipProvider = project.registerPublishToCentralPortalTasks( kind = Kind.aggregation, inputFiles = allFiles, spec = spec, allowEmptyFiles = allowEmptyAggregation, - publishAllChecksums = publishAllChecksums, + publishAllChecksums = publishAllChecksums ) project.afterEvaluate { @@ -78,7 +83,7 @@ internal abstract class DefaultNmcpAggregationExtension(private val project: Pro action.execute(options) project.registerNmcpPublishFileByFileToFileSystemTask( taskName = "nmcpPublishAggregationTo${options.name.get().capitalizeFirstLetter()}Repository", - inputFiles = allFiles, + inputFiles = project.zipTree(zipProvider), m2AbsolutePath = project.provider { project.file(options.path.get()).absolutePath }, parallelism = project.provider { 1 }, ) diff --git a/nmcp/src/main/kotlin/nmcp/internal/DefaultNmcpExtension.kt b/nmcp/src/main/kotlin/nmcp/internal/DefaultNmcpExtension.kt index a90a5ea..cbfb85b 100644 --- a/nmcp/src/main/kotlin/nmcp/internal/DefaultNmcpExtension.kt +++ b/nmcp/src/main/kotlin/nmcp/internal/DefaultNmcpExtension.kt @@ -78,7 +78,7 @@ internal abstract class DefaultNmcpExtension(private val project: Project): Nmcp inputFiles = m2Files, spec = spec, allowEmptyFiles = project.provider { false }, - publishAllChecksums = publishAllChecksums, + publishAllChecksums = project.provider { false } ) } } diff --git a/nmcp/src/main/kotlin/nmcp/internal/utils.kt b/nmcp/src/main/kotlin/nmcp/internal/utils.kt index 19def48..9052228 100644 --- a/nmcp/src/main/kotlin/nmcp/internal/utils.kt +++ b/nmcp/src/main/kotlin/nmcp/internal/utils.kt @@ -13,6 +13,7 @@ import org.gradle.api.attributes.HasConfigurableAttributes import org.gradle.api.attributes.Usage import org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE import org.gradle.api.file.FileCollection +import org.gradle.api.file.RegularFile import org.gradle.api.provider.Provider import org.gradle.api.publish.plugins.PublishingPlugin.PUBLISH_TASK_GROUP import org.gradle.api.tasks.bundling.Zip @@ -55,7 +56,7 @@ internal fun Project.registerPublishToCentralPortalTasks( spec: CentralPortalOptions, allowEmptyFiles: Provider, publishAllChecksums: Provider -) { +): Provider { val name = kind.name val releaseTaskName = "nmcpPublish${name.capitalizeFirstLetter()}ToCentralPortal" @@ -79,13 +80,13 @@ internal fun Project.registerPublishToCentralPortalTasks( inputFiles = inputFiles, ) - val publishAllChecksums = publishAllChecksums.getOrElse(false) val zipName = "${name}.zip" val zipTaskProvider = tasks.register(zipTaskName, Zip::class.java) { it.from(inputFiles) it.destinationDirectory.set(project.layout.buildDirectory.dir("nmcp/zip")) it.archiveFileName.set(zipName) it.eachFile { + val publishAllChecksums = publishAllChecksums.getOrElse(false) when { it.name.startsWith("maven-metadata") -> { // Exclude maven-metadata files, or the bundle is not recognized @@ -105,10 +106,11 @@ internal fun Project.registerPublishToCentralPortalTasks( it.dependsOn(checkFilesTaskProvider) } + val zipProvider = zipTaskProvider.flatMap { it.archiveFile } val releaseTask = registerNmcpPublishWithPublisherApiTask( taskName = releaseTaskName, - inputFile = zipTaskProvider.flatMap { it.archiveFile }, + inputFile = zipProvider, username = spec.username, password = spec.password, publicationName = spec.publicationName.orElse(checkFilesTaskProvider.flatMap { it.outputFile }.map { it.asFile.readText() }), @@ -160,7 +162,7 @@ internal fun Project.registerPublishToCentralPortalTasks( registerNmcpPublishFileByFileToFileSystemTask( taskName = localTaskName, m2AbsolutePath = project.provider { m2File.absolutePath }, - inputFiles = inputFiles, + inputFiles = zipTree(zipProvider), parallelism = spec.uploadSnapshotsParallelism.orElse(defaultParallelism), ) @@ -183,6 +185,8 @@ internal fun Project.registerPublishToCentralPortalTasks( } } } + + return zipProvider } private fun taskPath(project: Project, taskName: String): String { diff --git a/scripts/integration-tests.sh b/scripts/integration-tests.sh index ea978c9..67c4f06 100755 --- a/scripts/integration-tests.sh +++ b/scripts/integration-tests.sh @@ -2,7 +2,7 @@ set -e set -x ./gradlew -p tests/jvm build -./gradlew -p tests/kmp publishAggregationToCentralPortal --configuration-cache -./gradlew -p tests/kmp nmcpPublishDeployment -PnmcpDeploymentId=599ab6f5-dd08-4e7b-ae5a-85b45031715a --configuration-cache +./gradlew -p tests/kmp publishAggregationToCentralPortal +./gradlew -p tests/kmp nmcpPublishDeployment -PnmcpDeploymentId=599ab6f5-dd08-4e7b-ae5a-85b45031715a ./gradlew -p tests/kmp build ./gradlew -p tests/publish-all-checksums build diff --git a/tests/jvm/gradle.properties b/tests/jvm/gradle.properties index e69de29..ac1a35f 100644 --- a/tests/jvm/gradle.properties +++ b/tests/jvm/gradle.properties @@ -0,0 +1 @@ +org.gradle.configuration-cache=true \ No newline at end of file diff --git a/tests/kmp/build.gradle.kts b/tests/kmp/build.gradle.kts index ef0461d..c66a111 100644 --- a/tests/kmp/build.gradle.kts +++ b/tests/kmp/build.gradle.kts @@ -69,7 +69,7 @@ tasks.register("checkZip") { } } - //println(paths.sorted().joinToString(",\n")) +// println(paths.sorted().joinToString(",\n")) check( paths.sorted().equals( listOf( diff --git a/tests/kmp/gradle.properties b/tests/kmp/gradle.properties index 8b13789..f6847c1 100644 --- a/tests/kmp/gradle.properties +++ b/tests/kmp/gradle.properties @@ -1 +1 @@ - +# no configuration cache here because we run the test server in the build script diff --git a/tests/publish-all-checksums/build.gradle.kts b/tests/publish-all-checksums/build.gradle.kts index bdba6d2..11fee15 100644 --- a/tests/publish-all-checksums/build.gradle.kts +++ b/tests/publish-all-checksums/build.gradle.kts @@ -1,29 +1,29 @@ import nmcp.NmcpAggregationExtension plugins { - id("java") - id("com.gradleup.nmcp") - id("maven-publish") - id("signing") - id("com.gradleup.nmcp.aggregation") + id("java") + id("com.gradleup.nmcp") + id("maven-publish") + id("signing") + id("com.gradleup.nmcp.aggregation") } group = "net.mbonnin.tnmcp.checksums" version = "0.0.0-SNAPSHOT" publishing { - publications { - create("default", MavenPublication::class.java) { - from(components.getByName("java")) - } + publications { + create("default", MavenPublication::class.java) { + from(components.getByName("java")) } + } } signing { - sign(publishing.publications) - // This is a test-only key, it's OK to have it in source control - useInMemoryPgpKeys( - """ + sign(publishing.publications) + // This is a test-only key, it's OK to have it in source control + useInMemoryPgpKeys( + """ -----BEGIN PGP PRIVATE KEY BLOCK----- lFgEajfv+hYJKwYBBAHaRw8BAQdAAtZjfx7pt7TkHKxX6UC9ORR73co/I6+S6t7u @@ -41,31 +41,40 @@ signing { =PPy4 -----END PGP PRIVATE KEY BLOCK----- """.trimIndent(), - "" - ) + "" + ) } val testDirectory = "build/m2" nmcpAggregation { - localRepository { - name = "test" - path = testDirectory - } + localRepository { + name = "test" + path = testDirectory + } + publishAllChecksums.set(true) } dependencies { - nmcpAggregation(project) + nmcpAggregation(project) +} + +tasks.named("nmcpPublishAggregationToTestRepository") { + val dir = project.file(testDirectory) + doFirst { + dir.deleteRecursively() + } } tasks.named("check") { - dependsOn("nmcpPublishAggregationToTestRepository") - doLast { - check(project.file(testDirectory).walk().any { - it.name.endsWith(".asc.sha512") - }) - check(project.file(testDirectory).walk().any { - it.name.endsWith(".asc.sha256") - }) - } + dependsOn("nmcpPublishAggregationToTestRepository") + val dir = project.file(testDirectory) + doLast { + check(dir.walk().any { + it.name.endsWith(".asc.sha512") + }) + check(dir.walk().any { + it.name.endsWith(".asc.sha256") + }) + } } \ No newline at end of file diff --git a/tests/publish-all-checksums/gradle.properties b/tests/publish-all-checksums/gradle.properties new file mode 100644 index 0000000..ac1a35f --- /dev/null +++ b/tests/publish-all-checksums/gradle.properties @@ -0,0 +1 @@ +org.gradle.configuration-cache=true \ No newline at end of file From 11bcecce8383839d30fcceac60f9a68df2a3f566 Mon Sep 17 00:00:00 2001 From: Martin Bonnin Date: Sun, 21 Jun 2026 17:43:18 +0200 Subject: [PATCH 5/6] update apiDump --- nmcp/api/nmcp.api | 1 - 1 file changed, 1 deletion(-) diff --git a/nmcp/api/nmcp.api b/nmcp/api/nmcp.api index a519be8..efd4e01 100644 --- a/nmcp/api/nmcp.api +++ b/nmcp/api/nmcp.api @@ -28,7 +28,6 @@ public abstract interface class nmcp/NmcpAggregationExtension { public abstract interface class nmcp/NmcpExtension { public abstract fun extraFiles (Ljava/lang/Object;)V - public abstract fun getPublishAllChecksums ()Lorg/gradle/api/provider/Property; public abstract fun publishAllPublicationsToCentralPortal (Lorg/gradle/api/Action;)V } From bda7f475ac2283f943a393f712cc5e06769a1fc3 Mon Sep 17 00:00:00 2001 From: Martin Bonnin Date: Sun, 21 Jun 2026 17:56:20 +0200 Subject: [PATCH 6/6] fix tests --- nmcp/testProjects/duplicate-name/build.gradle.kts | 2 +- nmcp/testProjects/empty-aggregation/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nmcp/testProjects/duplicate-name/build.gradle.kts b/nmcp/testProjects/duplicate-name/build.gradle.kts index 4d6f15f..b665724 100644 --- a/nmcp/testProjects/duplicate-name/build.gradle.kts +++ b/nmcp/testProjects/duplicate-name/build.gradle.kts @@ -1,6 +1,6 @@ plugins { id("org.jetbrains.kotlin.jvm").version("2.3.0").apply(false) - id("com.gradleup.nmcp.aggregation").version("1.5.1-SNAPSHOT") + id("com.gradleup.nmcp.aggregation").version("1.6.0-SNAPSHOT") } group = "com.example" diff --git a/nmcp/testProjects/empty-aggregation/build.gradle.kts b/nmcp/testProjects/empty-aggregation/build.gradle.kts index a118126..5386c6c 100644 --- a/nmcp/testProjects/empty-aggregation/build.gradle.kts +++ b/nmcp/testProjects/empty-aggregation/build.gradle.kts @@ -1,3 +1,3 @@ plugins { - id("com.gradleup.nmcp.aggregation").version("1.5.1-SNAPSHOT") + id("com.gradleup.nmcp.aggregation").version("1.6.0-SNAPSHOT") }