Give the POMs of plugin publications the license and SCM of the project - #766
Merged
Merged
Conversation
`CustomPublicationHandler` copied the project attributes to the publications present when it was applied, in `afterEvaluate` of the module. For a module listed in `modulesWithCustomPublishing`, that action is added by the root project, so it runs before `java-gradle-plugin` creates `pluginMaven` and the plugin markers in an `afterEvaluate` action of its own. Their POMs went out without `<licenses>`, `<scm>`, and `<inceptionYear>` — SBOMs of the consumers report such a plugin as `NOASSERTION` — while a `fatJar` of the same module, created earlier, got all three. Where the handler ran after `java-gradle-plugin` instead, it replaced the `groupId` of the markers with the project group, which breaks resolving a plugin by its ID. The handler now reaches the publications with `configureEach`, so those added later get the same treatment. A plugin marker gets only the attributes describing the project as a whole, which move from `copyProjectAttributes()` to `copyProjectWideAttributes()`; its coordinates, name, and description stay those of the plugin. `isPluginMarker` moves to `PublishingExts.kt`, to be shared with the SBOM code. `CustomPublicationHandlerIgTest` compares the POMs with those of a standard publication for a module declared by the root project, by the module itself, and by both. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Records the evidence from the published POMs, the root cause, and the follow-ups left out of the fix: the marker workaround in `core-jvm-compiler`, the snapshot check of `PublicationChecksums`, and the destinations that `SpinePublishing.publishTo()` fails to inherit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Publishing code in `buildSrc` runs in `afterEvaluate`, often before `java-gradle-plugin` adds `pluginMaven` and the plugin markers. The memory records why such code must reach publications with `configureEach` and must leave the identity of a marker to the plugin it points to. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The test names its modules and publications through constants, reusing `StandardJavaPublicationHandler.PUBLICATION_NAME` for the standard one. Restrictive clauses use "that", sentences no longer open with a lowercase identifier, and the marker test states that the identity of a marker must not be replaced, which the previous wording left ambiguous. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Applies the rest of the documentation review to the task plan and the team memory: such sentences start with a word instead, and the third declaration of the test is named by its constant, `IN_BOTH`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
alexander-yevsyukov
requested review from
armiol
and
a lite review from Copilot
September 24, 2026 17:35
alexander-yevsyukov
enabled auto-merge
September 24, 2026 17:36
armiol
approved these changes
Sep 24, 2026
Contributor
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
Only minor documentation nits remain; no blocking issues were identified.
Review effort: Lite
Findings: 1
What changed in this PR
Updates Maven publication handling so late-created Gradle plugin publications receive project metadata while preserving marker coordinates.
Changes:
- Uses lazy configuration for late publications.
- Separates shared POM metadata from publication coordinates.
- Adds marker detection reuse and Gradle TestKit coverage.
| File | Summary |
|---|---|
buildSrc/src/test/kotlin/io/spine/gradle/publish/CustomPublicationHandlerIgTest.kt |
Tests plugin and marker POM metadata and identities. |
buildSrc/src/main/kotlin/io/spine/gradle/publish/PublishingExts.kt |
Centralizes plugin-marker detection. |
buildSrc/src/main/kotlin/io/spine/gradle/publish/PublicationSbom.kt |
Reuses shared marker detection. |
buildSrc/src/main/kotlin/io/spine/gradle/publish/PublicationHandler.kt |
Separates project-wide POM metadata handling. |
buildSrc/src/main/kotlin/io/spine/gradle/publish/CustomPublicationHandler.kt |
Configures existing and late publications. |
.agents/tasks/plugin-pom-metadata.md |
Documents the implementation plan and verification. |
.agents/memory/project/plugin-publications-created-late.md |
Records publication lifecycle guidance. |
.agents/memory/MEMORY.md |
Indexes the new project memory. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This was referenced Sep 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

What changed
CustomPublicationHandlernow reaches Maven publications withconfigureEachinstead of an eagerforEach. Publications added after the handler is applied —pluginMavenand the plugin markers ofjava-gradle-plugin— now get the project attributes too.PublicationHandler.copyProjectAttributes()is split: the inception year, license, and SCM move tocopyProjectWideAttributes(). Plugin markers get only these; their coordinates, name, and description stay those of the plugin.isPluginMarkermoves toPublishingExts.ktasinternal, shared with the SBOM code from Publish an SPDX SBOM with each Maven publication #764, which carried its own private copy.CustomPublicationHandlerIgTest.Why
Found while adding SBOM generation (#762, #764): the SPDX Gradle Plugin reads licenses from dependency POMs, and every Spine Gradle plugin artifact showed up as
NOASSERTION. Their POMs have no<licenses>,<scm>, or<inceptionYear>— for examplevalidation-gradle-plugin:2.0.0-SNAPSHOT.464,time-gradle-plugin:2.0.0-SNAPSHOT.251,compiler-gradle-plugin:2.0.0-SNAPSHOT.069, androot-gradle-plugins,protobuf-setup-plugins,jvm-tool-pluginsat2.0.0-SNAPSHOT.423.Root cause.
SpinePublishingapplies the handler inafterEvaluateof the module. For a module listed inmodulesWithCustomPublishing, the root script adds that action before the module appliesjava-gradle-plugin, which createspluginMavenand the markers in anafterEvaluateaction of its own. The eagerforEachsaw neither. The published artifacts show it: inprotobuf-setup-plugins, thefatJarpublication (protobuf-setup-plugins-all), created earlier, has all three sections, whilepluginMavenhas none.A second, latent bug. When a module opens
spinePublishing { customPublishing = true }itself after applyingjava-gradle-plugin, the loop ran after the markers existed and replaced theirgroupIdwith the project group, which breaks resolving the plugin by its ID.Tests
CustomPublicationHandlerIgTestbuilds a fixture with a standard module and ajava-gradle-pluginmodule, and compares thepluginMavenand marker POMs with the standard POM for three declarations: in the root project, in the module, and in both. The last is howtool-basedeclaresprotobuf-setup-pluginsandjvm-tool-pluginsviauber-jar-module.artifactId, and a markergroupIdofio.spine.tools.appliedguard disabled, theIN_BOTHcase fails with two licenses, so applying the attributes twice is caught as well../gradlew :buildSrc:build detekton JDK 17: all 118 tests pass.Notes for reviewers
pluginMavennow also gets its coordinates from the handler, as its KDoc always stated. The values match whatvalidation,time,compiler,tool-base, andProtoTapset by hand, so their workarounds become redundant but stay harmless.gradle-pluginmodule ofcore-jvm-compilerstrips the marker's plugin dependency only when it is namedgradle-plugin. After it pulls this change, its marker would listcore-jvm-gradle-plugintwice (same GAV) until that workaround is updated; this is tracked separately.<name>,<url>, or<developers>either, so none are added here. Adding them would change every published POM..agents/tasks/plugin-pom-metadata.mdand a team memory,plugin-publications-created-late, each in its own commit so the memory can be reviewed on its own.🤖 Generated with Claude Code