Skip to content

Fix descriptor set generation when the project version changes - #184

Merged
alexander-yevsyukov merged 5 commits into
masterfrom
fix-descriptor-generation-when-version-changes
Jun 25, 2026
Merged

Fix descriptor set generation when the project version changes#184
alexander-yevsyukov merged 5 commits into
masterfrom
fix-descriptor-generation-when-version-changes

Conversation

@alexander-yevsyukov

@alexander-yevsyukov alexander-yevsyukov commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #183.

GenerateProtoTask is a cacheable task whose key is the .proto sources and the
compiler configuration only. The descriptor set file name is derived from the project's
full Maven coordinates (<group>_<artifactId>_<version>_<classifier>.desc), and the
desc.ref file points at that name. After a coordinate-only change (most commonly a
version bump) the .proto sources are unchanged, so with the Gradle build cache on,
generateProto is restored from the cache — bringing back a descriptor set produced under
the previous name while desc.ref references the new name. The mismatch leaves
Protobuf types unresolvable at runtime (UnknownTypeException), which surfaces as
intermittent, hard-to-diagnose CI/test failures after any version bump.

Fix

DescriptorSetFilePlugin now declares the descriptor set file name as an explicit
input of the GenerateProtoTask:

inputs.property("descriptorSetName", descriptorSetFile.name)

The name embeds every output-determining coordinate (group, artifact ID, version,
classifier), so any change to it invalidates the cache key and regenerates the descriptor
set together with its desc.ref — while caching is preserved for every other change. The
input is read from the same descriptorSetFile used for the output path, so the cache key
and the produced name can never disagree. Caching stays on; only the cache key is
corrected.

Initially keyed on the project version alone; broadened to the full descriptor file name
per review feedback, so group / artifact-ID / classifier changes are covered too.

Tests

Added regression tests to BuildCacheSpec that seed the build cache, change one
coordinate (the version in one test, the group in another) leaving the .proto
sources unchanged, run clean with the cache on, then assert that generateProto
re-executes instead of restoring a stale descriptor and that the descriptor set and
desc.ref are consistent at the new coordinates. Each test fails without the fix
(generateProto is FROM_CACHE, stale name) and passes with it.

Verification: ./gradlew build dokkaGenerate passes; all tests in
:protobuf-setup-plugins pass; detekt and Dokka are clean.

Note for reviewers

Beyond the descriptor-set fix, this branch also carries a routine config submodule +
dependency sync and the 2.0.0-SNAPSHOT.401 → .402 version bump (pre-existing branch
preparation). Those config-distributed files are owned by the config repository and are
out of scope for review here.

🤖 Generated with Claude Code

alexander-yevsyukov and others added 4 commits June 24, 2026 19:38
`GenerateProtoTask` is a cacheable task whose key is the `.proto` sources and
the compiler configuration only. The descriptor set file name embeds the
project version, and the `desc.ref` file points at that name. After a
version-only change the Proto sources are unchanged, so the build cache
restored a descriptor set produced for the previous version while `desc.ref`
referenced the new name — leaving Protobuf types unresolvable at runtime
(`UnknownTypeException`).

Declare the project version as an explicit, lazily-read input of the task so a
version change invalidates the cached descriptor set and regenerates it, and
its reference file, with matching names. Caching is preserved for all other
changes. This mirrors the `inputs.property("projectVersion", ...)` approach
already used in `LicenseReporter`.

Add a regression test to `BuildCacheSpec` that bumps the version with the
build cache on and asserts the descriptor set and its reference file are
regenerated consistently.

Fixes #183.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@codecov

codecov Bot commented Jun 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.45%. Comparing base (20237db) to head (502e3df).

Additional details and impacted files
@@            Coverage Diff            @@
##             master     #184   +/-   ##
=========================================
  Coverage     90.45%   90.45%           
  Complexity      554      554           
=========================================
  Files           122      122           
  Lines          2241     2243    +2     
  Branches        311      311           
=========================================
+ Hits           2027     2029    +2     
  Misses           93       93           
  Partials        121      121           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a Gradle build-cache correctness issue in protobuf-setup-plugins where Protobuf descriptor set generation could be restored from cache after a version-only change, causing desc.ref to point at a non-existent (new-version) descriptor file name and leading to UnknownTypeException at runtime.

Changes:

  • Declare the project version as an explicit (lazy) input to GenerateProtoTask in DescriptorSetFilePlugin to ensure version bumps invalidate the cache entry.
  • Add a regression test in BuildCacheSpec that seeds the build cache, bumps the project version, runs clean, and asserts the descriptor set is regenerated and consistent with desc.ref.
  • Includes routine version/dependency/config sync updates (notably in config-distributed paths).

Reviewed changes

Copilot reviewed 18 out of 20 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
version.gradle.kts Bumps published version to 2.0.0-SNAPSHOT.402.
protobuf-setup-plugins/src/test/kotlin/io/spine/tools/protobuf/gradle/plugin/BuildCacheSpec.kt Adds regression coverage for cache behavior across version bumps.
protobuf-setup-plugins/src/main/kotlin/io/spine/tools/protobuf/gradle/plugin/DescriptorSetFilePlugin.kt Adds a lazy task input so version changes invalidate the build-cache entry for descriptor generation.
init-submodules Config-sync change (config-managed; out of scope here).
docs/dependencies/pom.xml Updates docs dependency metadata version to .402.
docs/dependencies/dependencies.md Regenerates dependency report for .402 (including new generation timestamp).
buildSrc/src/main/kotlin/io/spine/dependency/test/Testcontainers.kt Adds Testcontainers coordinates (buildSrc/config-managed; out of scope here).
buildSrc/src/main/kotlin/io/spine/dependency/local/ToolBase.kt Updates local ToolBase versions (buildSrc/config-managed; out of scope here).
buildSrc/src/main/kotlin/io/spine/dependency/local/CoreJvmCompiler.kt Updates Core JVM compiler versions (buildSrc/config-managed; out of scope here).
buildSrc/src/main/kotlin/io/spine/dependency/local/CoreJvm.kt Updates Core JVM version (buildSrc/config-managed; out of scope here).
buildSrc/src/main/kotlin/io/spine/dependency/local/Compiler.kt Updates compiler fallback versions (buildSrc/config-managed; out of scope here).
buildSrc/src/main/kotlin/io/spine/dependency/lib/PerfMark.kt Adds PerfMark coordinates (buildSrc/config-managed; out of scope here).
buildSrc/src/main/kotlin/io/spine/dependency/lib/GoogleCloud.kt Updates Google Cloud library versions (buildSrc/config-managed; out of scope here).
buildSrc/src/main/kotlin/io/spine/dependency/lib/GoogleApis.kt Updates Google API library versions (buildSrc/config-managed; out of scope here).
.idea/kotlinc.xml IDE config sync (config-managed; out of scope here).
.gitignore Shared config block updates (config-managed; out of scope here).
.github/workflows/secret-scan.yml New workflow (config-distributed per PR description; out of scope here).
.github/workflows/build-on-ubuntu.yml Workflow updates (config-managed; out of scope here).
.claude/settings.json Claude settings sync (config-managed; out of scope here).
Files not reviewed (1)
  • .idea/kotlinc.xml: Generated file

Address review feedback on PR #184: the descriptor set file name is derived from
the full Maven coordinates (group, artifact ID, version, classifier), so keying
the `GenerateProtoTask` cache on the project version alone left a group- or
artifact-ID change able to restore a descriptor set produced under a different
name — the same `desc.ref`/descriptor mismatch the fix set out to prevent.

Key the task on the computed descriptor set file name instead, which already
embeds every naming component. This still fixes the reported version-bump case
(#183) and additionally covers group, artifact-ID, and classifier changes. The
input is read from the same `descriptorSetFile` used for the output path, so the
cache key and the produced name can never disagree.

Add a regression test that changes only the project group (version unchanged)
and asserts the descriptor set is regenerated rather than restored from the
build cache.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@alexander-yevsyukov
alexander-yevsyukov merged commit bd9ea3a into master Jun 25, 2026
9 checks passed
@alexander-yevsyukov
alexander-yevsyukov deleted the fix-descriptor-generation-when-version-changes branch June 25, 2026 08:02
@github-project-automation github-project-automation Bot moved this from 🏗 In progress to ✅ Done in v2.0 Jun 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

Protobuf descriptor set generation is not safely cacheable, causing UnknownTypeException after version bumps

3 participants