Repository navigation
Stop bundling the Protobuf runtime into the plugin uber JARs - #196
Conversation
Skips `.426`, which the in-flight dependency refresh wave claims. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`protobuf-setup-plugins` and `jvm-tool-plugins` (and their `-all` twins) embedded unrelocated `protobuf-java`, `protobuf-java-util`, and `protobuf-kotlin` classes, pinning the runtime of each build. Consumers whose generated code was newer failed with `ProtobufRuntimeVersionException`, and no `force(...)` could reach the copy. The runtime cannot be relocated, as it depends on the names of its classes, and need not be bundled, as it is on Maven Central. Exclude it from `shadowJar` by the dependency filter and declare it as a non-transitive `runtime` dependency: via the `shadow` configuration for the plugin publications, and by hand in the POM of the `fatJar` publications. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Rename the destructured coordinates so they no longer hide the `name` and `version` of the publication, state that the function needs `uber-jar-module`, and polish the KDoc and the task plan. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shadow writes the files of the `shadow` configuration into the `Class-Path` attribute of the JAR manifest, which named the build-time Protobuf JARs. A dedicated `protobufRuntime` configuration, extended by `shadowRuntimeElements`, keeps the published metadata the same without it. 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. |
There was a problem hiding this comment.
🔵 Needs a closer look
The central publication helper remains outside the permitted review scope, and downstream dependency resolution requires human validation.
0 open findings
What changed in this PR
Moves the Protobuf runtime out of plugin uber JARs so consumers can resolve its version through normal dependency management.
Changes:
- Applies runtime unbundling to both plugin modules.
- Adds explicit runtime dependencies to publication metadata.
- Advances the release to
2.0.0-SNAPSHOT.427and refreshes dependency reports.
| File | Description |
|---|---|
version.gradle.kts |
Advances the publication version. |
protobuf-setup-plugins/build.gradle.kts |
Applies runtime unbundling. |
jvm-tool-plugins/build.gradle.kts |
Applies runtime unbundling. |
docs/dependencies/pom.xml |
Updates the reported version. |
docs/dependencies/dependencies.md |
Refreshes report versions and timestamps. |
buildSrc/src/main/kotlin/io/spine/gradle/shade/ProtobufRuntime.kt |
Adds shading exclusions and runtime publication declarations. |
.agents/tasks/unbundle-protobuf-runtime.md |
Records implementation and verification progress. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Resolve the conflicts with the dependency refresh (#195): keep version `2.0.0-SNAPSHOT.427`, above the `.426` of master, and take the regenerated dependency reports of master with this project version in their headers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #196 +/- ##
=========================================
Coverage 91.96% 91.96%
Complexity 840 840
=========================================
Files 163 163
Lines 2999 2999
Branches 373 373
=========================================
Hits 2758 2758
Misses 109 109
Partials 132 132 🚀 New features to boost your workflow:
|
Bring `unbundleProtobufRuntime()` from config (#796). Keep the local dependency pins of this repository, which are newer than those of config. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Remove the repo-owned copy in `buildSrc/…/shade/`, which config#796 moved into config as `io.spine.gradle.publish.unbundleProtobufRuntime`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Problem
The uber JARs of
protobuf-setup-pluginsandjvm-tool-plugins— published asprotobuf-setup-plugins[-all]andjvm-tool-plugins[-all]— embedded about 1,100 unrelocated classes ofprotobuf-java,protobuf-java-util, andprotobuf-kotlin.com/google/protobuf/RuntimeVersionin.426reads4.36.2. So every build pinned the Protobuf runtime it was built with on the build classpath of its consumers.Gradle cannot see that copy, because it is bytecode inside another artifact, not a dependency.
force(...), constraints, and BOMs do not reach it. In the dependency refresh wave (Protobuf4.36.0 → 4.36.2), code generated by4.36.2next to the.422or.425JARs failed withProtobufRuntimeVersionException: … gencode 4.36.2, runtime 4.36.0. That brokecore-jvm-compiler,core-jvm, andjdbc-storage, which now carry temporary resolution rules.Change
The new repo-owned
buildSrc/…/shade/ProtobufRuntime.ktaddsProject.unbundleProtobufRuntime(). Both modules call it. For each ofProtobuf.libs, it:shadowJarthrough the dependency filter, not by path. That way the SBOM does not describe the library as bundled (seeSbomContent.bundled(task));protobufRuntimeconfiguration.shadowRuntimeElementsextends that configuration, soplugin-publishlists the library in the.moduleand the POM of the Gradle plugin publication. Theshadowconfiguration would do the same, but Shadow also writes its files into the manifestClass-Path(Class-Path: protobuf-java-4.36.0.jar …). In a directory that holds several Protobuf JARs, that entry would put the build-time runtime first again;fatJarpublication ofuber-jar-module. That publication publishes withartifact(...)and gets no dependencies from Gradle.The declarations are non-transitive because the libraries' own dependencies are covered elsewhere:
protobuf-javais declared itself.So consumers get the same classes as before. Only the Protobuf runtime now comes from genuine artifacts, at the version the consumer resolves.
Relocation is not an option, because the Protobuf runtime depends on the names of its classes. Bundling is not needed either: Protobuf is on Maven Central. This is the approach of #188 (
IntelliJUberJar.kt), applied to Protobuf.Verification
RuntimeVersionis absent, and the size drops from 6.9 MB to 4.7 MB forjvm-tool-pluginsand from 7.3 MB to 5.1 MB forprotobuf-setup-plugins.pluginMavenandfatJarPOMs and the.modulefiles declareprotobuf-java,protobuf-java-util, andprotobuf-kotlinin theruntimescope with*:*exclusions.Class-Pathattribute../gradlew build dokkaGeneratepasses.Version
2.0.0-SNAPSHOT.427. It skips.426, which the in-flight refresh wave (#195) claims.Follow-ups for consumers
Once a consumer pins ToolBase
.427or later:core-jvmandjdbc-storagecan drop theireachDependencyrules that liftprotobuf-setup-pluginsfrom.422/.425to.426.core-jvm-compilercan go back toToolBase.jvmToolPluginDogfoodingoncedogfoodingVersionis.427or later.Future Protobuf bumps no longer need such rules.
Not in scope
protobuf-setup-pluginsstill bundles theprotobuf-gradle-pluginclasses (com/google/protobuf/gradle/**) and its OS-detector dependencies, unrelocated. They are not the runtime, and nothing failed on them. Declaring them in the same way could be a separate change.🤖 Generated with Claude Code