Skip to content

make CI dependency caching actually work (branch-keyed jar cache)#15935

Open
jdaugherty wants to merge 4 commits into
7.0.xfrom
ci/branch-keyed-dependency-cache
Open

make CI dependency caching actually work (branch-keyed jar cache)#15935
jdaugherty wants to merge 4 commits into
7.0.xfrom
ci/branch-keyed-dependency-cache

Conversation

@jdaugherty

@jdaugherty jdaugherty commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

fix: make CI dependency caching actually work (branch-keyed jar cache)

Description

CI builds regularly fail when repo.grails.org has an outage, because every job downloads its full dependency set from scratch on every run — e.g. this run, where Build Grails-Core (macos-latest, 21) failed with 502 Bad Gateway downloading groovy-console/groovy-swing jars during compileGroovy.

Investigation showed that although setup-gradle caching is configured, no Gradle caches exist for this repository at all:

  1. setup-gradle only writes caches on the repository's default branch (8.0.x). All 7.x branch and PR builds run cache-read-only: true, and GitHub's cache scoping only lets them restore from their own branch or the default branch — so the 7.x branches never have a warm cache.
  2. The repo's 10 GB cache quota was exhausted by the groovy-joint-workflow, which cached ~/.m2/repository under a per-SHA key (cache-local-maven-${{ github.sha }}). A per-SHA key can never be re-used across runs, so this added a new ~60 MB dead entry on every commit (89 entries at the time of writing), evicting anything useful.

This PR fixes both:

.github/workflows/groovy-joint-workflow.yml — remove caching entirely:

  • The per-SHA Maven-repo cache was really a same-run hand-off of the locally built Groovy from the build_groovy job to the build_grails job. It is now passed via upload-artifact/download-artifact (only ~/.m2/repository/org/apache/groovy, retention-days: 1), which is the correct mechanism for job-to-job transfer and does not consume the cache quota.
  • cache-disabled: true on the setup-gradle steps — this workflow rebuilds Groovy each run, so a Gradle home cache is not useful.

.github/workflows/gradle.yml — explicit, branch-keyed dependency-jar cache:

  • cache-disabled: true on all setup-gradle steps, replacing the action's automatic Gradle-home caching (which was silently doing nothing on 7.x, and would also cache build outputs).
  • Every job now has an explicit actions/cache step covering only downloaded dependency jars and wrapper distributions (~/.gradle/caches/modules-2, ~/.gradle/wrapper) — never Grails build outputs.
  • The key is based on the branch version: gradle-deps-<os>-${{ github.base_ref || github.ref_name }}-<hash of dependencies.gradle + gradle-wrapper.properties>, with a matching restore-keys prefix. Pushes to 7.0.x seed the cache; PRs targeting 7.0.x restore it. PRs that don't change dependency files get an exact cache hit and skip saving, so PR runs don't pollute the quota.

With a warm cache, a transient repo.grails.org outage no longer fails the build, and dependency download time is removed from every job.

Follow-up (separate PRs): delete the stale cache-local-maven-* cache entries so the new caches have room immediately, and add a mavenCentral() fallback in GrailsRepoSettingsPlugin so a repository outage cannot fail even a cold-cache build.

Contributor Checklist

Please review the following checklist before submitting your pull request. Pull requests that do not meet these requirements may be closed without review.

Issue and Scope

  • This PR is linked to an existing issue that has been acknowledged or approved by the project team. If no approved issue exists, please give background on why this change is necessary. Tickets are preferred for release change log history.
    • No existing issue; background is given above — recurring CI failures caused by repo.grails.org outages combined with dependency caching that was configured but never effective.
  • This PR addresses the complete scope of the linked issue. Partial implementations or unfinished work should not be submitted for review.
  • This PR contains a single, focused change. Unrelated changes should be submitted as separate pull requests.
  • This PR targets the correct branch for the type of change:
    • Patch release branches (e.g., 7.0.x): Bug fixes only. No new features or API changes.
    • Minor release branches (e.g., 7.1.x): New features are welcome, but breaking existing APIs must be avoided.
    • Major release branches (e.g., 8.0.x): Reserved for major changes. Breaking API changes are permitted.
    • CI-infrastructure fix only; no framework code or API changes. Targets 7.0.x to be merged forward through 7.1.x/7.2.x/8.0.x.

Code Quality

  • I have added or updated tests that cover the changes introduced in this PR. All code contributions are expected to include appropriate test coverage.
    • Not applicable — GitHub Actions workflow change only; no framework code is touched. Both workflow files pass YAML validation, and the change is verified by CI itself.
  • I have verified that all existing tests pass by running ./gradlew build --rerun-tasks.
    • Not applicable — no Gradle-built source is modified; the CI run on this PR exercises the change directly.
  • My code follows the project's code style guidelines. I have run ./gradlew codeStyle and resolved any violations. See Code Style for details.
  • This PR does not include mass reformatting, style-only changes, or large-scale refactoring unless it was explicitly approved in the linked issue. Unsolicited reformatting will not be accepted.
  • If generative AI tooling was used in preparing this contribution, a quality model was used to ensure contributions are consistent with the project's quality standards.

Licensing and Attribution

  • All contributed code is provided under the Apache License 2.0, and new source files include the appropriate Apache license header.
    • No new files; the modified workflow files retain their existing Apache license headers.
  • I have the necessary rights to submit this contribution and confirm it is my own original work (see Legal Notice).
  • If generative AI tooling was used in preparing this contribution, I have followed the Apache Software Foundation's policy on generative tooling and have properly attributed its use.
    • This change was prepared with the assistance of Claude Code (Anthropic), including the root-cause investigation of the failing CI run; the approach and final content were reviewed by the contributor.

Documentation

  • If this PR introduces user-facing changes, I have included or updated the relevant documentation.
    • Not applicable — no user-facing changes.
  • If this PR adds a new feature, I have updated the What's New section of the Grails Guide.
    • Not applicable.
  • If this PR introduces breaking changes or changes that require user action during an upgrade, I have updated the Upgrade Notes for the corresponding version in the Grails Guide.
    • Not applicable.
  • The PR description clearly explains what was changed and why.

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 adjusts the repository’s GitHub Actions workflows to make dependency caching effective across release branches and reduce CI failures during transient repository outages by introducing an explicit, branch-keyed Gradle dependency cache and replacing an ineffective per-SHA Maven cache with artifact hand-off.

Changes:

  • Replace per-SHA ~/.m2/repository caching in the Groovy joint workflow with upload-artifact/download-artifact for the locally built Groovy snapshot.
  • Disable setup-gradle’s built-in caching and add an explicit actions/cache step for downloaded Gradle dependency jars and wrapper distributions keyed by branch and dependency inputs.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
.github/workflows/groovy-joint-workflow.yml Removes per-SHA Maven cache and uses artifacts to share locally built Groovy between jobs; disables Gradle action caching.
.github/workflows/gradle.yml Adds explicit branch-keyed caching for ~/.gradle/caches/modules-2 and ~/.gradle/wrapper and disables setup-gradle caching across jobs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/groovy-joint-workflow.yml
Comment on lines +39 to +43
- name: "🗄️ Restore dependency jar cache"
uses: actions/cache@v4
with:
# Cache only downloaded dependency jars and wrapper distributions, never Grails build outputs.
# Keyed by branch version so each release branch maintains its own warm cache.
@jdaugherty jdaugherty force-pushed the ci/branch-keyed-dependency-cache branch from 1ff64c7 to 9e381f5 Compare July 7, 2026 19:13
@jdaugherty

Copy link
Copy Markdown
Contributor Author

FYI:the alternative to this PR is to adopt the commerical gradle cache, but the licensing terms may prevent this.

actions/download-artifact has no v7.0.1 release (its version line jumped
from v7.0.0 to v8.x). Pin download-artifact to v8.0.1 and upload-artifact
to v7.0.1 by SHA, matching gradle.yml.
@testlens-app

testlens-app Bot commented Jul 8, 2026

Copy link
Copy Markdown

✅ All tests passed ✅

🏷️ Commit: 71208cf
▶️ Tests: 34243 executed
⚪️ Checks: 51/51 completed


Learn more about TestLens at testlens.app.

@codeconsole codeconsole self-requested a review July 8, 2026 21:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

4 participants