ci(pull-request-kotlin): persist Gradle build-cache across runs (split restore/save) [NO-JIRA]#298
Merged
Conversation
e6d9c35 to
89e89b9
Compare
…plit restore/save [NO-JIRA] The test job recompiled (~150s of KSP + Kotlin, main+test) on every run. Dependencies were cached, but setup-java's built-in 'gradle' cache keys on the gradle files and only saves on a cache MISS — so Gradle's build-cache (compiled task output) froze at first save and never accumulated, leaving every run to recompile from scratch. Switch to the split restore/save pattern and save on every run under a per-commit key, so the build-cache persists and unchanged KSP/Kotlin output returns FROM-CACHE instead of recompiling. The Sonar cache had the same freeze-on-fixed-key problem and gets the same treatment. Cache key is branch-scoped with a shared fallback: a PR restores its own branch's latest cache first (closest source -> best build-cache hit rate), else the most recent run. Caches are isolated per repository automatically (GitHub + runs-on), so no repo name is needed in the key. Saves run on always() so compiled output is cached even when tests fail. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
89e89b9 to
d430113
Compare
sudheer-monta
approved these changes
Jun 5, 2026
joscdk
approved these changes
Jun 5, 2026
This was referenced Jun 5, 2026
JesperTerkelsen
added a commit
that referenced
this pull request
Jun 5, 2026
…anch builds [NO-JIRA] (#303) GitHub/runs-on caches are branch-scoped: a run can only restore caches from its own ref + the default branch (main). The Kotlin PR test workflow (#298) never runs on main, so no Linux-gradle-* cache exists there, and its Linux-gradle- fallback can't reach sibling PR caches -> every fresh branch's first build is cold (~3-4m recompile). sonar-cloud.yml already compiles + tests on main (code-analysis on push:main). Have it save ~/.gradle under Linux-gradle-main-<sha> (split restore/save, replacing setup-java's frozen cache:'gradle'). That sits on refs/heads/main = default branch, so the PR test workflow's existing Linux-gradle- fallback matches it -> fresh PR branches start warm. No change to pull-request-kotlin.yml needed. Save is guarded to refs/heads/main so a PR-context run can't poison the baseline. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Problem
The Kotlin PR test job recompiles ~2m 30s of KSP + Kotlin every run, even for unchanged modules. Dependencies are cached, but
setup-java's built-incache: 'gradle'keys on the gradle files and only saves on a cache miss — so Gradle's build-cache (~/.gradle/caches/build-cache-1, the compiled task output) is written once and frozen, and every run recompiles from scratch. The Sonar cache (fixed key${{ runner.os }}-sonar) has the same freeze.Fix
Switch both caches to the split
restore/savepattern and save on every run under a per-commit, branch-scoped key, so the build-cache persists and unchangedkspKotlin/compileKotlincome back FROM-CACHE.saveruns onalways()(compiled output is cached even when tests fail) and is skipped on an exact re-run hit.${{ github.repository }}is needed in the key.Validated on a canary (
service-feature#737)Two runs through this branch ref — cold, then warm (identical source):
Log confirms:
Cache hit for restore-key: …-gradle-…→compileKotlin FROM-CACHE,kspKotlin FROM-CACHE,ktlint… FROM-CACHE.Caveat on the 1m 56s: run 2 had byte-identical source (empty commit), so even the
testtask cache-hit. A real PR that changes code still recompiles changed files and re-runs affected tests (~2m 17s of realinternal-apitest execution). So the dependable win is eliminating the ~2m 30s–3m 40s cold recompile; expect a typical code PR around ~4–5 min (from ~9 min), and a docs/no-op PR the full ~1m 56s.Notes
org.gradle.caching=true(harmless no-op otherwise); dependency caching helps every repo.-gradle-fallback can pull another PR's cache on a cold first build of a new branch — low risk for this PR-only, ships-nothing workflow, and moot if runs-on enforces branch-scoping on the magic cache.pull-request-kotlin.yml@mainis consumed by 35 repos — merging flips all of them on their next PR run. Two repos pin a SHA (service-charges,service-internal-ocpi-tooling-service) and are unaffected. Consider migrating a couple via the branch ref first as a wider canary before merging tomain.🤖 Generated with Claude Code