Fix CI toolchain caching#401
Open
holodorum wants to merge 4 commits into
Open
Conversation
The jdk cache entries pointed at ./gradle/jdk and ./buildSrc/gradle/jdk, which no longer exist (the jvm wrapper installs the GraalVM JDK to ~/.gradle/jdks, already covered by the dependencies cache), so every run saved an empty archive. Remove them and add caches that hit: rattler (pixi's conda package cache, keyed on kson-lib/pixi.lock) and uv (Python packages and CPython downloads, keyed on lib-python/uv.lock), each with Linux/macOS/Windows paths. The Python sdist jobs previously restored no caches at all despite running a full bundled-Gradle + GraalVM native-image build plus uv/cibuildwheel; they now restore/save gradle deps, rattler, and uv via new shared restore-build-caches and save-build-caches commands, with the Linux jobs sharing linux-amd64 keys with the every-commit build job so release runs start warm. No tests: this is CI configuration, verified by regenerating .circleci/config.yml from config.kson via the gradle transpile task.
Enable Gradle's build cache CI-only by setting
GRADLE_OPTS=-Dorg.gradle.caching=true in the environment of every
Gradle-running job, letting CI reuse compile and test task outputs across
runs (build-linux-amd64 spends most of its time in `./gradlew check`).
Keeping this in GRADLE_OPTS rather than gradle.properties leaves local dev
behavior untouched, and the env var still reaches the bundled-Gradle build
that `pip install` of the sdist runs and the separate `cd buildSrc &&
./gradlew check`. Persist the cache in the shared
restore-build-caches/save-build-caches commands: save
`~/.gradle/caches/build-cache-1` under a per-commit key (`{{ .Revision }}`)
and restore by prefix so each build starts from the most recent snapshot. A
per-commit key is required because the dependencies cache keys on the
build.gradle.kts checksum and CircleCI writes any given key only once, so
that cache can never carry an evolving build cache. No tests: this is CI
configuration, verified by regenerating config.yml via the transpile task
and by confirming locally that GRADLE_OPTS makes :kson-lib:compileKotlinJvm
report FROM-CACHE while a plain invocation still rebuilds.
Enabling Gradle's build cache in CI exposed a latent bug in the nl.ochagavia.krossover plugin: its KSP processor writes build/kotlin/krossover/metadata/api.json as a side effect that is not among kspKotlinJvm's declared outputs. Cold builds work because the task executes and the file appears, but on a warm cache kspKotlinJvm is served FROM-CACHE and the side-effect file is never restored, so generateJniConfigJvm then fails with "property 'publicApiMetadataFile' specifies file '...api.json' which doesn't exist". Declaring api.json as an additional output of kspKotlinJvm lets the build cache capture and restore it on a cache hit, keeping the task cacheable. Reproduced locally against an isolated build cache: prime, then wipe kson-lib/build and rerun :kson-lib:generateJniConfigJvm, which fails before this change (kspKotlinJvm FROM-CACHE, api.json missing) and passes after (api.json restored from the cache entry); a broader warm-cache run of :generateJniBindingsJvm confirmed api.json is the only undeclared side-effect in the krossover chain. The real fix belongs upstream in the plugin. No automated test is added: exercising this requires a full cold-then-warm Gradle run, which the manual reproduction covers and which has no cheap unit-test surface.
Contributor
|
Nice! Thanks, @holodorum! |
Gradle caches go stale depending on clarified input and ouptut of task. If we accidentally did not specify an input or not all inputs the task won't be run again or will be run with stale a stale cache. I'm not sure if we can fully safeguard against this. This would limit the consequence by only using the Gradle caching option only for the check job, not for any of the release jobs.
f7b28d5 to
69a2897
Compare
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.
Two of the CI cache entries never stored anything, and the jobs with the biggest downloads had no caching at all. This PR fixes both:
./gradle/jdkand./buildSrc/gradle/jdkno longer exist — the jvm wrapper installs the GraalVM JDK to~/.gradle/jdks/, which the existing~/.gradledependencies cache already covers — so this entry saved an empty archive on every run.kson-lib/pixi.lock, and uv (Python packages + CPython downloads) keyed onlib-python/uv.lock, each with Linux/macOS/Windows cache paths, following the multi-path pattern of the existing vscode cache.pip installof the sdist running a full bundled-Gradle + GraalVM native-image build, plus uv/cibuildwheel for wheels. They now restore/save gradle deps + rattler + uv through new sharedrestore-build-caches/save-build-cachescommands; the existing gradle-caches commands layer vscode/pnpm on top of the same trio. The Linux Python jobs sharelinux-amd64cache keys with the every-commitbuild-linux-amd64job, so release runs start with warm caches..circleci/config.ymlis regenerated fromconfig.ksonvia the gradle transpile task.Supersedes #400.