This is an automated email from the ASF dual-hosted git repository.

snazy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/polaris-tools.git


The following commit(s) were added to refs/heads/main by this push:
     new 321cd17  Apprunner: Ensure Maven publishing works (#69)
321cd17 is described below

commit 321cd1748f121e4618a29a73a913d59236206a7b
Author: Robert Stupp <[email protected]>
AuthorDate: Sat Dec 6 10:19:40 2025 +0100

    Apprunner: Ensure Maven publishing works (#69)
    
    This change ensures that publishing tasks work correctly, the right 
`MavenPublications` are being used and no duplicate `MavenPublications` exist.
    
    * The Gradle plugin-plugin uses the name `pluginMaven` for the "main" 
publication. This name is then used instead of the common name `maven`, 
removing a duplicate (shadowing) publication.
    * The Maven plugin-plugin uses the name `mavenJava` for the "main" 
publication. This name is then used instead of the common name `maven`, 
removing a duplicate (shadowing) publication.
    * The Gradle plugin-plugin adds another publication for the "plugin marker" 
artifact, which only consists of a pom.xml. Adding the license and parent 
information to that pom as well.
---
 .../kotlin/publishing/PublishingHelperPlugin.kt    | 34 ++++++--
 .../src/main/kotlin/publishing/configurePom.kt     | 93 +++++++++++-----------
 .../src/main/kotlin/publishing/maven-utils.kt      | 13 ++-
 apprunner/gradle-plugin/build.gradle.kts           |  8 +-
 apprunner/settings.gradle.kts                      |  4 +-
 5 files changed, 92 insertions(+), 60 deletions(-)

diff --git 
a/apprunner/apprunner-build-logic/src/main/kotlin/publishing/PublishingHelperPlugin.kt
 
b/apprunner/apprunner-build-logic/src/main/kotlin/publishing/PublishingHelperPlugin.kt
index bc7ef4a..7ad73ac 100644
--- 
a/apprunner/apprunner-build-logic/src/main/kotlin/publishing/PublishingHelperPlugin.kt
+++ 
b/apprunner/apprunner-build-logic/src/main/kotlin/publishing/PublishingHelperPlugin.kt
@@ -28,6 +28,7 @@ import org.gradle.api.component.SoftwareComponentFactory
 import org.gradle.api.publish.PublishingExtension
 import org.gradle.api.publish.maven.MavenPublication
 import org.gradle.api.publish.maven.plugins.MavenPublishPlugin
+import org.gradle.api.publish.maven.tasks.GenerateMavenPom
 import org.gradle.api.publish.tasks.GenerateModuleMetadata
 import org.gradle.api.tasks.SourceSetContainer
 import org.gradle.api.tasks.javadoc.Javadoc
@@ -94,6 +95,17 @@ constructor(private val softwareComponentFactory: 
SoftwareComponentFactory) : Pl
         configureOnRootProject(project)
       }
 
+      // The Gradle plugin-plugin adds another publication for the Gradle 
plugin marker artifact,
+      // which is needed to resolve Gradle plugins by their ID. It uses the 
name `pluginMaven` for
+      // the "main" `MavenPublication`, but that publication is created 
_after_ this code runs,
+      // if it does not already exist.
+      // The Maven plugin-plugin uses the name `mavenJava` for the "main" 
`MavenPublication`, which
+      // is created _before_ this code runs.
+      val hasGradlePlugin = plugins.hasPlugin("java-gradle-plugin")
+      val hasMavenPlugin = plugins.hasPlugin("io.freefair.maven-plugin")
+      val publicationName =
+        if (hasGradlePlugin) "pluginMaven" else if (hasMavenPlugin) 
"mavenJava" else "maven"
+
       if (isSigningEnabled()) {
         apply(plugin = "signing")
         plugins.withType<SigningPlugin>().configureEach {
@@ -102,7 +114,7 @@ constructor(private val softwareComponentFactory: 
SoftwareComponentFactory) : Pl
             val signingPassword: String? by project
             useInMemoryPgpKeys(signingKey, signingPassword)
             val publishing = 
project.extensions.getByType(PublishingExtension::class.java)
-            afterEvaluate { sign(publishing.publications.getByName("maven")) }
+            afterEvaluate { publishing.publications.forEach { publication -> 
sign(publication) } }
 
             if (project.hasProperty("useGpgAgent")) {
               useGpgCmd()
@@ -121,7 +133,11 @@ constructor(private val softwareComponentFactory: 
SoftwareComponentFactory) : Pl
       plugins.withType<MavenPublishPlugin>().configureEach {
         configure<PublishingExtension> {
           publications {
-            register<MavenPublication>("maven") {
+            // The maven plugin-plugin has already registered the 'mavenJava' 
publication.
+            if (!hasMavenPlugin) {
+              register<MavenPublication>(publicationName)
+            }
+            named<MavenPublication>(publicationName) {
               val mavenPublication = this
               afterEvaluate {
                 // This MUST happen in an 'afterEvaluate' to ensure that the 
Shadow*Plugin has
@@ -139,7 +155,12 @@ constructor(private val softwareComponentFactory: 
SoftwareComponentFactory) : Pl
                       }
                     }
                   }
-                  from(component)
+                  // The Gradle and Maven plugin-plugins unconditionally add 
the 'java' component.
+                  // It's illegal to have more than one `SoftwareComponent` in 
a publication,
+                  // even if it is the same.
+                  if (!hasGradlePlugin && !hasMavenPlugin) {
+                    from(component)
+                  }
                 }
 
                 suppressPomMetadataWarningsFor("testFixturesApiElements")
@@ -167,14 +188,15 @@ constructor(private val softwareComponentFactory: 
SoftwareComponentFactory) : Pl
                 artifact(testFixturesJavadocJar)
               }
 
-              tasks.named("generatePomFileForMavenPublication").configure {
-                configurePom(project, mavenPublication, this)
+              // Have to configure all pom's (needed for the Gradle 
plugin-plugin)
+              tasks.withType(GenerateMavenPom::class.java).configureEach {
+                configurePom(project, this)
               }
             }
           }
         }
       }
 
-      addAdditionalJarContent(this)
+      addAdditionalJarContent(this, publicationName)
     }
 }
diff --git 
a/apprunner/apprunner-build-logic/src/main/kotlin/publishing/configurePom.kt 
b/apprunner/apprunner-build-logic/src/main/kotlin/publishing/configurePom.kt
index e8c2c13..7c9684b 100644
--- a/apprunner/apprunner-build-logic/src/main/kotlin/publishing/configurePom.kt
+++ b/apprunner/apprunner-build-logic/src/main/kotlin/publishing/configurePom.kt
@@ -21,9 +21,8 @@ package publishing
 
 import groovy.util.Node
 import org.gradle.api.Project
-import org.gradle.api.Task
 import org.gradle.api.artifacts.component.ModuleComponentSelector
-import org.gradle.api.publish.maven.MavenPublication
+import org.gradle.api.publish.maven.tasks.GenerateMavenPom
 
 /**
  * Configures the content of the generated `pom.xml` files.
@@ -42,9 +41,9 @@ import org.gradle.api.publish.maven.MavenPublication
  * must be exactly the same when built by a release manager and by someone 
else to verify the built
  * artifact(s).
  */
-internal fun configurePom(project: Project, mavenPublication: 
MavenPublication, task: Task) =
-  mavenPublication.run {
-    pom {
+internal fun configurePom(project: Project, task: GenerateMavenPom) =
+  task.actions.addFirst {
+    with(task.pom) {
       if (project != project.rootProject) {
         // Add the license to every pom to make it easier for downstream 
projects to retrieve the
         // license.
@@ -68,56 +67,54 @@ internal fun configurePom(project: Project, 
mavenPublication: MavenPublication,
       } else {
         val mavenPom = this
 
-        task.doFirst {
-          mavenPom.run {
-            val prj = EffectiveAsfProject.forProject(project)
-            val asfProjectId = prj.asfProject.apacheId
+        mavenPom.run {
+          val prj = EffectiveAsfProject.forProject(project)
+          val asfProjectId = prj.asfProject.apacheId
 
-            organization {
-              name.set("The Apache Software Foundation")
-              url.set("https://www.apache.org/";)
-            }
-            licenses {
-              license {
-                name.set("Apache-2.0") // SPDX identifier
-                url.set(prj.asfProject.licenseUrl)
-              }
+          organization {
+            name.set("The Apache Software Foundation")
+            url.set("https://www.apache.org/";)
+          }
+          licenses {
+            license {
+              name.set("Apache-2.0") // SPDX identifier
+              url.set(prj.asfProject.licenseUrl)
             }
-            mailingLists {
-              prj.publishingHelperExtension.mailingLists
-                .get()
-                .map { id -> prj.mailingList(id) }
-                .forEach { ml ->
-                  mailingList {
-                    name.set(ml.name())
-                    subscribe.set(ml.subscribe())
-                    unsubscribe.set(ml.unsubscribe())
-                    post.set(ml.post())
-                    archive.set(ml.archive())
-                  }
+          }
+          mailingLists {
+            prj.publishingHelperExtension.mailingLists
+              .get()
+              .map { id -> prj.mailingList(id) }
+              .forEach { ml ->
+                mailingList {
+                  name.set(ml.name())
+                  subscribe.set(ml.subscribe())
+                  unsubscribe.set(ml.unsubscribe())
+                  post.set(ml.post())
+                  archive.set(ml.archive())
                 }
-            }
-
-            scm {
-              val codeRepoString: String = prj.codeRepoUrl().get()
-              connection.set("scm:git:$codeRepoString")
-              developerConnection.set("scm:git:$codeRepoString")
-              url.set("$codeRepoString/tree/main")
-              val version = project.version.toString()
-              if (!version.endsWith("-SNAPSHOT")) {
-                val tagPrefix: String = prj.tagPrefix().get()
-                tag.set("$tagPrefix-$version")
               }
+          }
+
+          scm {
+            val codeRepoString: String = prj.codeRepoUrl().get()
+            connection.set("scm:git:$codeRepoString")
+            developerConnection.set("scm:git:$codeRepoString")
+            url.set("$codeRepoString/tree/main")
+            val version = project.version.toString()
+            if (!version.endsWith("-SNAPSHOT")) {
+              val tagPrefix: String = prj.tagPrefix().get()
+              tag.set("$tagPrefix-$version")
             }
-            issueManagement { url.set(prj.issueTracker()) }
+          }
+          issueManagement { url.set(prj.issueTracker()) }
 
-            name.set(prj.fullName())
-            description.set(prj.description())
-            url.set(prj.projectUrl())
-            inceptionYear.set(prj.asfProject.inceptionYear.toString())
+          name.set(prj.fullName())
+          description.set(prj.description())
+          url.set(prj.projectUrl())
+          inceptionYear.set(prj.asfProject.inceptionYear.toString())
 
-            developers { developer { 
url.set("https://$asfProjectId.apache.org/community/";) } }
-          }
+          developers { developer { 
url.set("https://$asfProjectId.apache.org/community/";) } }
         }
       }
     }
diff --git 
a/apprunner/apprunner-build-logic/src/main/kotlin/publishing/maven-utils.kt 
b/apprunner/apprunner-build-logic/src/main/kotlin/publishing/maven-utils.kt
index 4c370f6..88123ed 100644
--- a/apprunner/apprunner-build-logic/src/main/kotlin/publishing/maven-utils.kt
+++ b/apprunner/apprunner-build-logic/src/main/kotlin/publishing/maven-utils.kt
@@ -70,7 +70,7 @@ abstract class GeneratePomProperties : DefaultTask() {
  * `META-INF/maven/group-id/artifact-id/`. Also adds the `NOTICE` and 
`LICENSE` files in `META-INF`,
  * which makes it easier for license scanners.
  */
-fun addAdditionalJarContent(project: Project): Unit =
+fun addAdditionalJarContent(project: Project, mainPublicationName: String): 
Unit =
   project.run {
     project.plugins.withType(JavaLibraryPlugin::class.java) {
       val generatePomProperties =
@@ -83,7 +83,6 @@ fun addAdditionalJarContent(project: Project): Unit =
             rootProject.layout.files("gradle/jar-licenses/LICENSE", 
"gradle/jar-licenses/NOTICE")
           )
           inputs.property("GAV", 
"${project.group}:${project.name}:${project.version}")
-          dependsOn("generatePomFileForMavenPublication")
           if (!project.file("src/main/resources/META-INF/LICENSE").exists()) {
             
from(rootProject.rootDir).include("gradle/jar-licenses/LICENSE").eachFile {
               this.path = "META-INF/$sourceName"
@@ -94,7 +93,12 @@ fun addAdditionalJarContent(project: Project): Unit =
               this.path = "META-INF/$sourceName"
             }
           }
-          from(tasks.named("generatePomFileForMavenPublication")) {
+          // The Gradle plugin-plugin add another publication for the Gradle 
plugin marker artifact,
+          // which is needed to resolve Gradle plugins by their ID.
+          // Here we want to add the Maven pom information for the "main" 
publication to the jar.
+          val generateMavenPomTask = 
tasks.named(generatePomTaskName(mainPublicationName))
+          dependsOn(generateMavenPomTask)
+          from(generateMavenPomTask) {
             include("pom-default.xml")
             eachFile { this.path = 
"META-INF/maven/${project.group}/${project.name}/pom.xml" }
           }
@@ -110,3 +114,6 @@ fun addAdditionalJarContent(project: Project): Unit =
       }
     }
   }
+
+fun generatePomTaskName(publicationName: String) =
+  "generatePomFileFor${publicationName.replaceFirstChar { if 
(it.isLowerCase()) it.titlecase() else it.toString() }}Publication"
diff --git a/apprunner/gradle-plugin/build.gradle.kts 
b/apprunner/gradle-plugin/build.gradle.kts
index 1784707..19cf103 100644
--- a/apprunner/gradle-plugin/build.gradle.kts
+++ b/apprunner/gradle-plugin/build.gradle.kts
@@ -18,8 +18,9 @@
  */
 
 plugins {
-  id("polaris-apprunner-java")
+  // Order of java-gradle-plugin + polaris-apprunner-java matters!
   `java-gradle-plugin`
+  id("polaris-apprunner-java")
 }
 
 dependencies {
@@ -30,7 +31,10 @@ dependencies {
 gradlePlugin {
   plugins {
     register("polaris-apprunner") {
-      id = "org.apache.polaris.apprunner"
+      // This ID becomes the Maven group ID of the Gradle plugin marker 
artifact.
+      // The artifact ID of the Gradle plugin marker artifact is ID + 
".gradle.plugin"
+      // (the defined plugin marker suffix).
+      id = project.group.toString()
       implementationClass = 
"org.apache.polaris.apprunner.plugin.PolarisRunnerPlugin"
       displayName = "Polaris Runner"
       description = "Start and stop a Polaris server for integration testing"
diff --git a/apprunner/settings.gradle.kts b/apprunner/settings.gradle.kts
index e9faef2..1e919b6 100644
--- a/apprunner/settings.gradle.kts
+++ b/apprunner/settings.gradle.kts
@@ -67,7 +67,9 @@ dependencyResolutionManagement {
 
 gradle.beforeProject {
   version = baseVersion
-  group = "org.apache.polaris.tools.apprunner"
+  // Note: the Gradle plugin ID is the group ID here. Both should be "aligned",
+  // so that the plugin ID is within this group.
+  group = "org.apache.polaris.apprunner"
 }
 
 val isCI = System.getenv("CI") != null

Reply via email to