Add CodeGeneratorRequestWriter from Base; fix plugins to work with Gradle cache; fix ArtifactMetaPlugin working directory#181
Merged
Conversation
The class is protoc-plugin tooling: its only consumers are the protoc-plugin entry points of the Compiler and ProtoTap, both of which already depend on ToolBase. It is repackaged from `io.spine.code.proto` to `io.spine.tools.code.proto` to avoid a split package across the `spine-base` and `spine-tool-base` artifacts. See SpineEventEngine/base-libraries#938
The object is `internal` to `base`, so the moved class can no longer import it for the documentation link. The `parse` extension applies the registry internally; the KDoc now says so in prose.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #181 +/- ##
============================================
+ Coverage 90.40% 90.45% +0.04%
Complexity 554 554
============================================
Files 122 122
Lines 2230 2241 +11
Branches 311 311
============================================
+ Hits 2016 2027 +11
Misses 93 93
Partials 121 121 🚀 New features to boost your workflow:
|
Also: * Bump the Compiler
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1b5b01c61b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
`GeneratedSourcePlugin` and `DescriptorSetFilePlugin` do their work in `doLast` actions of the cacheable `generateProto` task. Declare the copied `generated/<sourceSet>` directory and the `desc.ref` file as task outputs so that the build cache stores and restores them after `clean`. Also add the generated source directories to source sets via `builtBy(task)` so that the consuming tasks (e.g., `compileJava` in pure-Java projects) depend on the generating task. The new `BuildCacheSpec` verifies both plugins with the build cache turned on and off. `org.gradle.caching` stays off in this repository until the dogfooded `protobuf-setup-plugins` contains this fix. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A bare file name passed as the request file path has no parent directory, making `File.parentFile` return `null`. Guard the parent directory creation so that `writeBinary()` and `writeJson()` work for files resolved against the current working directory. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
CodeGeneratorRequestWriter moved from Spine BaseCodeGeneratorRequestWriter from Base; fix plugins to work with Gradle cache
`ArtifactMetaPlugin` claimed the whole `build/spine` directory — the root working directory shared by all Spine plugins — as the output of its `writeArtifactMeta` task and as a `main` resources source directory. Declared inputs of other plugins' tasks under `build/spine`, such as `build/spine/compiler/settings` of `launchSpineCompiler`, were thus contained in the declared output of `writeArtifactMeta`, making Gradle demand explicit ordering between tasks of unrelated plugins: Task ':launchSpineCompiler' uses this output of task ':writeArtifactMeta' without declaring an explicit or implicit dependency. The plugin now claims the dedicated `build/spine/artifact-meta` subdirectory, following the `rootWorkingDir` convention. The path of the metadata file relative to the output directory is unchanged, so the in-JAR resource path (`META-INF/io.spine/<artifact-id>.meta`) read by `ArtifactMeta.loadFromResource` stays the same, and the reading side needs no changes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
CodeGeneratorRequestWriter from Base; fix plugins to work with Gradle cacheCodeGeneratorRequestWriter from Base; fix plugins to work with Gradle cache; fix ArtifactMetaPlugin working directory
CodeGeneratorRequestWriter from Base; fix plugins to work with Gradle cache; fix ArtifactMetaPlugin working directoryCodeGeneratorRequestWriter from Base; fix plugins to work with Gradle cache; fix ArtifactMetaPlugin working directory
armiol
approved these changes
Jun 11, 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.
This is the receiving half of SpineEventEngine/base-libraries#938:
CodeGeneratorRequestWriteris protoc-plugin tooling, not runtime API, so it moves frombaseinto thetool-basemodule.Changes
CodeGeneratorRequestWriterunder the new packageio.spine.tools.code.proto(repackaged fromio.spine.code.prototo avoid a split package across thespine-baseandspine-tool-baseartifacts, as discussed in the issue).CodeGeneratorRequestWriterSpecwith a localconstructRequesthelper (inbasethe helper is shared with the parsing specs, which stay there).ArtifactMetaPluginwrite its files underbuild/spine/artifact-metainstead of claiming the wholebuild/spinedirectory (see below).2.0.0-SNAPSHOT.400.Gradle build cache fix
With
org.gradle.caching=true,clean buildfailed in modules using theio.spine.generated-sourcesandio.spine.descriptor-set-fileplugins (e.g.,classic-codegenin this repository): compilation reported unresolved references because no generated code was present.Root cause
The same pattern as SpineEventEngine/compiler#67. Both plugins do their work in
doLastactions of the cacheablegeneratePrototask without declaring the results as task outputs:GeneratedSourcePlugincopies theprotocoutput into$projectDir/generated/<sourceSet>/;DescriptorSetFilePlugincreates thedesc.reffile next to the descriptor set file.cleandeletesgenerated/andbuild/; the build cache then restoresgenerateProtowithout executing it — only declared outputs are restored — so the copied sources anddesc.refare missing, and compilation fails. With the cache off, everything works only because the task always re-executes afterclean.Fix
GeneratedSourcePlugin— declares$projectDir/generated/<sourceSet>as an output ofgenerateProto, so the build cache stores and restores the copied code.DescriptorSetFilePlugin— declaresdesc.refas an output (the.descfile itself is already a declared output of the Protobuf Gradle plugin).project.files(dir).builtBy(task). This fixes a latent gap exposed by the new test: in pure-Java projectscompileJavadid not depend ongenerateProtoat all, because the plugin severs the dependency carried by theprotocoutput directories when replacing them withgenerated/.... In Spine repositories this was masked by the Kotlin compilation dependency arranged bysetupKotlinCompile().Testing
The new
BuildCacheSpecrunsbuild→clean→buildvia TestKit against a project applying both plugins, with a project-local build cache directory for hermeticity. The test project'scleandeletesgenerated/(mimicking the Spine convention), and a handwritten Java class refers to the generated code, so missing codegen fails the compilation.generateProtoisFROM_CACHE, the generated code,desc.ref, and the descriptor set file are restored and re-packed into resources.clean.Verified both ways: with the output declarations temporarily removed, the cache-on test fails while the cache-off test passes; with the fix, both pass.
ArtifactMetaPluginworking directoryThe plugin declared the whole
build/spinedirectory as the output of itswriteArtifactMetatask and as amainresources source directory.build/spineis the root working directory shared by all Spine plugins (seerootWorkingDir), where each plugin is expected to claim its own subdirectory. Claiming the root put the declared inputs of other Spine plugins' tasks — e.g.,build/spine/compiler/{requests,settings}oflaunchSpineCompiler— inside the declared output tree ofwriteArtifactMeta. Gradle's missing-dependency validation then failed consumer builds:The actual files never intersected; only the declared trees overlapped.
The plugin now claims
build/spine/artifact-meta. The metadata file keeps its path relative to the output directory, so the in-JAR resource path —META-INF/io.spine/<artifact-id>.meta, the contract ofArtifactMeta.loadFromResource— is unchanged, and the reading side needs no changes. A side benefit: working files of other plugins underbuild/spinecan no longer be swept into packaged resources byprocessResources. Consumer repositories can dropmustRunAfter("writeArtifactMeta")workarounds once they depend on atool-baseversion with this change.Notes
org.gradle.cachingremains off ingradle.properties: this repository's own build applies the publishedprotobuf-setup-pluginsvia the root buildscript classpath, which does not yet contain the fix. Re-enable onceToolBase.versioninbuildSrcpoints to a release with this change.generated/<sourceSet>(e.g.,validation), Gradle's overlapping-outputs detection makes it re-execute the affected tasks instead of restoring them — correct results, fewer cache hits. Separating output directories per producer is a follow-up beyond this PR.https://claude.ai/code/session_01QkiJSc86Y7ocs1PeZMxJhX
🤖 Generated with Claude Code