From 1cfeaddc6aff22f837bd252e97b00f48c9ae65f3 Mon Sep 17 00:00:00 2001 From: Yuki Fujisaki Date: Tue, 16 Jun 2026 11:08:02 +0900 Subject: [PATCH 1/2] fix: consolidate publishing onto the pluginMaven publication to fix signing The 2.10.0 release failed at `signPluginMavenPublication` with an implicit task-dependency error: the hand-rolled `release` publication and the plugin-publish-managed `pluginMaven` publication both reference the same physical jars, so `signReleasePublication` and `signPluginMavenPublication` each wrote the same `*.asc` files. `publishReleasePublicationToMavenRepository` then consumed an `.asc` produced by `signPluginMavenPublication` without a declared dependency, which Gradle rejects. Drop the separate `release` publication and reuse plugin-publish's `pluginMaven` for both Maven Central and the Plugin Portal: a single publication means a single set of artifacts and a single signing task per artifact, so there is no `.asc` collision. The Maven Central coordinate stays `com.deploygate:gradle` (artifactId override), and the plugin marker keeps depending on `com.deploygate:gradle`. - build.gradle: configure `pluginMaven` (artifactId + pom) instead of a separate `release` publication; drop the explicit `sign` call (plugin-publish already signs pluginMaven + marker); gate signing on the new `publishPluginMavenPublicationToMavenRepository` task. - release.sh: publish via `publishPluginMavenPublicationToMavenRepository`. Verified locally with a throwaway GPG key: a signing-required publish of both `pluginMaven` and the marker to a file repository succeeds with no implicit- dependency error and emits signed jar/sources/javadoc/module/pom (+ marker). Co-Authored-By: Claude Opus 4.8 (1M context) --- build.gradle | 20 +++++++++++--------- release.sh | 6 +++--- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index cdf1199..b7c58d0 100644 --- a/build.gradle +++ b/build.gradle @@ -347,14 +347,14 @@ afterEvaluate { } publications { - release(MavenPublication) { - // The plugin-publish plugin enables withSourcesJar()/withJavadocJar() on the java - // component, so components.java already carries the sources and javadoc jars; adding - // them again here would fail with "multiple artifacts with the identical ... classifier". - from components.java - groupId = project.group + // java-gradle-plugin (via plugin-publish) already creates the `pluginMaven` publication + // from components.java, with the sources and javadoc jars attached. Reuse it for BOTH + // Maven Central and the Plugin Portal rather than maintaining a second hand-rolled + // publication: a single publication means a single set of artifacts and a single signing + // task, which avoids two Sign tasks writing the same `*.asc` files. Keep the Maven Central + // coordinate as `com.deploygate:gradle` (not the project name) for back-compat. + pluginMaven { artifactId = archivesBaseName - version = project.version pom { name = "Gradle DeployGate Plugin" description = "This is the DeployGate plugin for the Gradle. You can build and deploy your apps to DeployGate by running a single task." @@ -378,12 +378,14 @@ afterEvaluate { } signing { - required { (isRelease() || System.getenv("RELEASE_SCRIPT_TEST") == "true") && gradle.taskGraph.hasTask("publishReleasePublicationToMavenRepository") } + required { (isRelease() || System.getenv("RELEASE_SCRIPT_TEST") == "true") && gradle.taskGraph.hasTask("publishPluginMavenPublicationToMavenRepository") } def signingKey = findProperty("signingKey") def signingPassword = findProperty("signingPassword") useInMemoryPgpKeys(signingKey, signingPassword) - publishing.publications.configureEach { publication -> sign publication } + // No explicit `sign` call: the plugin-publish plugin already signs the `pluginMaven` and + // marker publications once the signing plugin is applied. Adding our own `sign` here would + // double-sign the shared jars and produce conflicting `*.asc` outputs. } } } diff --git a/release.sh b/release.sh index 8ef56db..e6b797e 100755 --- a/release.sh +++ b/release.sh @@ -3,10 +3,10 @@ set -euo pipefail # Publish in a single build to: -# * Maven Central -> publishReleasePublicationToMavenRepository (com.deploygate:gradle) -# * Plugin Portal -> publishPlugins (id com.deploygate) +# * Maven Central -> publishPluginMavenPublicationToMavenRepository (com.deploygate:gradle) +# * Plugin Portal -> publishPlugins (id com.deploygate) ./gradlew clean build \ - publishReleasePublicationToMavenRepository \ + publishPluginMavenPublicationToMavenRepository \ publishPlugins \ --stacktrace From c2b94dafc5bb0f748a4cc94ff8a4ea3fd7f4fe30 Mon Sep 17 00:00:00 2001 From: Yuki Fujisaki Date: Tue, 16 Jun 2026 11:23:25 +0900 Subject: [PATCH 2/2] fix: make the signing-required gate match the publish task by name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `gradle.taskGraph.hasTask("publishPluginMavenPublicationToMavenRepository")` compares against the task *path* (":publishPluginMavenPublicationToMavenRepository"), so the bare-name argument never matched and `signing.required` was effectively always false — signing only happened when a key was present, and a release run with a missing key would silently publish unsigned artifacts (which Maven Central then rejects). Match by task name via `gradle.taskGraph.allTasks.any { it.name == ... }` so the gate fails fast when a release runs without a signing key. Verified locally: with a key the publish signs and succeeds; without a key the build now fails at `signPluginMavenPublication` ("no configured signatory") instead of skipping. Addresses review feedback from gemini-code-assist on PR #296. Co-Authored-By: Claude Opus 4.8 (1M context) --- build.gradle | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b7c58d0..2359245 100644 --- a/build.gradle +++ b/build.gradle @@ -378,7 +378,15 @@ afterEvaluate { } signing { - required { (isRelease() || System.getenv("RELEASE_SCRIPT_TEST") == "true") && gradle.taskGraph.hasTask("publishPluginMavenPublicationToMavenRepository") } + // Match by task name rather than gradle.taskGraph.hasTask(""): hasTask compares the + // full task path (e.g. ":publishPluginMavenPublicationToMavenRepository"), so the bare name + // never matched and signing was effectively never "required". Matching the name makes the + // gate fail fast when a release runs without a signing key. + required { + (isRelease() || System.getenv("RELEASE_SCRIPT_TEST") == "true") && gradle.taskGraph.allTasks.any { + it.name == "publishPluginMavenPublicationToMavenRepository" + } + } def signingKey = findProperty("signingKey") def signingPassword = findProperty("signingPassword")