Build: Designate a single Gradle cache writer across CI workflows#16356
Open
kevinjqliu wants to merge 4 commits into
Open
Build: Designate a single Gradle cache writer across CI workflows#16356kevinjqliu wants to merge 4 commits into
kevinjqliu wants to merge 4 commits into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR addresses Gradle cache thrashing in CI by designating a single canonical cache writer (java-ci.yml's build-checks (17) job on refs/heads/main) and making all other gradle/actions/setup-gradle invocations read-only (or cache-disabled for the workflow_dispatch-driven jmh-benchmarks.yml). This prevents parallel jobs from racing to save overlapping cache entries and accelerating LRU eviction against GitHub's 10 GB per-repo cache cap.
Changes:
- Add
cache-read-only: trueto setup-gradle steps in 11 jobs across 10 workflows. - Make
java-ci.ymlbuild-checksjob conditionally read-only — writes only onrefs/heads/mainwithmatrix.jvm == 17. - Set
cache-disabled: trueinjmh-benchmarks.ymlto prevent cache poisoning from arbitrary repo/ref dispatch inputs.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| .github/workflows/java-ci.yml | Marks core-tests, build-javadoc, check-runtime-deps read-only; gates build-checks writes to main + JVM 17 |
| .github/workflows/spark-ci.yml | Adds cache-read-only: true to setup-gradle |
| .github/workflows/flink-ci.yml | Adds cache-read-only: true to setup-gradle |
| .github/workflows/hive-ci.yml | Adds cache-read-only: true to setup-gradle |
| .github/workflows/kafka-connect-ci.yml | Adds cache-read-only: true to setup-gradle |
| .github/workflows/delta-conversion-ci.yml | Adds cache-read-only: true to two scala-variant jobs |
| .github/workflows/cve-scan.yml | Adds cache-read-only: true to setup-gradle |
| .github/workflows/api-binary-compatibility.yml | Adds cache-read-only: true to setup-gradle |
| .github/workflows/publish-snapshot.yml | Adds cache-read-only: true to setup-gradle |
| .github/workflows/publish-iceberg-rest-fixture-docker.yml | Adds cache-read-only: true to setup-gradle |
| .github/workflows/recurring-jmh-benchmarks.yml | Adds cache-read-only: true to setup-gradle |
| .github/workflows/jmh-benchmarks.yml | Sets cache-disabled: true to prevent poisoning from arbitrary dispatch inputs |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
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.
Why
The shared gradle caches managed by
gradle/actions/setup-gradleare written by every job that doesn't explicitly opt out. With ~10 setup-gradle invocations across 12 workflows, parallel jobs race to save overlapping caches on every push tomain, producing duplicated entries and accelerating LRU pressure against GitHub's 10 GB per-repo cap.This causes cache thrashing: each commit produces ~3–4 GB of fresh per-job
gradle-home-...-<sha>entries that immediately evict older entries (including hot dependency caches) under LRU. The next build then misses on entries that should have been warm, re-downloads dependencies, writes new entries, and evicts again — a self-perpetuating churn loop that wastes minutes per build and keeps the cache in a permanently cold state despite being at-capacity.What
Restrict cache writes to a single canonical job and make every other job read-only:
java-ci.yml→build-checks (17)onrefs/heads/mainonly. This job runs./gradlew -DallModules buildand therefore resolves the union dependency closure that all other workflows need.cache-read-only: trueadded to setup-gradle injava-ci.yml(3 other jobs),spark-ci.yml,flink-ci.yml,hive-ci.yml,kafka-connect-ci.yml,delta-conversion-ci.yml(×2),cve-scan.yml,api-binary-compatibility.yml,publish-snapshot.yml,publish-iceberg-rest-fixture-docker.yml,recurring-jmh-benchmarks.yml.jmh-benchmarks.yml(workflow_dispatch on arbitrary repo/ref) →cache-disabled: trueto avoid cache poisoning.Read-only jobs still benefit from cache restores (including setup-gradle's
restore-keysprefix walk that lets matrix variants pull a sibling job'sgradle-homeentry).Validation
Validated on a fork (
kevinjqliu/iceberg) across 4 rounds:build-checks (17)onlyrefs/pull/20/*)build-checks (17)updatedgradle-homeandgradle-dependencies; no other writersgradle-homeentry createdJob logs confirm
Cache is read-only: will not save state for use in subsequent builds.for every non-writer job, andSaved cache entry with key gradle-home-v1\|...build-checks[...]-<sha>only frombuild-checks (17).Impact
Files changed
12 workflows under
.github/workflows/, +58 lines (comments + 1–2 new keys per file). No code changes, no test changes.