Gradle 8.4+ build cache returns stale outputs when configuration cache is enabled
0 reputation · 01 Apr 2023, 06:12 UTC
0 reputation · 01 Apr 2023, 06:12 UTC
On Gradle 8.4 and later, enabling the configuration cache alongside the build cache appears to change which task input properties participate in the cache key. The documented behavior is that the configuration cache serializes the task graph once and reuses it, while the build cache keys task outputs on declared inputs. The uncertainty is what happens at the boundary: when a plugin upgrade or a task class hierarchy change alters the set of input properties, can a previously stored cache entry still be considered a hit because the serialized graph captured only a subset of inputs?
The scenario is a multi-module build where some tasks produce side-effect-free transformations and their only detectable input changes come from the plugin classpath, not from file inputs. The --configure-on-demand-cache-key diagnostic flag mentioned around 8.4.2 is sparsely documented, and it is unclear whether it covers plugin-driven input changes or only configure-on-demand key computation. Verification would involve comparing checksums between a clean build and a cache-reused build and inspecting UP-TO-DATE and FROM-CACHE outcomes with --info.
--configure-on-demand-cache-key intended to diagnose this class of stale hit, and what output does it actually produce?32775 reputation · 01 Apr 2023, 18:03 UTC
When the configuration cache is enabled, Gradle still computes the build‑cache key from three independent sources:
@Input, @InputFile, @InputDirectory, etc.).These components are combined into a hash that is stored alongside the cached output. The configuration cache only serializes the task graph for reuse; it does **not** alter how the build‑cache key is formed.
If a plugin upgrade changes the implementation classpath of a task (e.g., a new version of the plugin JAR is added or removed), the classpath component of the key changes. Consequently the build‑cache key changes and the previously cached output is treated as a miss, even though the configuration cache may have reused the same task graph.
--configure-on-demand-cache-keyThis flag prints the **configuration cache key** for each project. It does **not** display the build‑cache key, so it cannot directly reveal a stale‑output hit caused by missing input properties. However, you can run a build with the flag before and after a plugin version change; the printed keys will stay the same while the build‑cache key (and thus the task execution) changes.
Gradle already includes the task implementation classpath in the build‑cache key by default. To make the dependency explicit in your task definition you can:
@Classpath (or @Input combined with @Classpath) so that its value participates in the key.@PathSensitivity(PathSensitivity.RELATIVE) on a @InputDirectory that points to the plugin’s classpath directory.These annotations are optional; omitting them does not exclude the classpath from the key.
./gradlew clean build --configuration-cache --info
FROM-CACHE versus UP-TO-DATE.classpath configuration) and repeat the same command.FROM-CACHE), confirming that the build‑cache key changed.--configure-on-demand-cache-key to see that the configuration cache keys remain unchanged across the plugin version change.Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.