Skip to content

Cache Maven and Gradle wrapper distributions separately from the dependency cache - #1097

Merged
brunoborges merged 12 commits into
mainfrom
brunoborges-fix-maven-wrapper-caching
Jul 14, 2026
Merged

Cache Maven and Gradle wrapper distributions separately from the dependency cache#1097
brunoborges merged 12 commits into
mainfrom
brunoborges-fix-maven-wrapper-caching

Conversation

@brunoborges

@brunoborgesbrunoborges commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Description:

Each build tool's wrapper distribution was cached in the same cache entry as its dependency cache, keyed on volatile dependency files. Because those files change frequently and no restoreKeys are used (by design, see #269), almost every change rotates the key and produces a full cache miss. On a miss nothing is restored, including the rarely-changing wrapper distribution, so ./mvnw / ./gradlew re-download the build tool, which intermittently fails due to upstream rate limiting.

Maven: The wrapper distribution (~/.m2/wrapper/dists) shared the ~/.m2/repository entry, keyed on **/pom.xml (plus wrapper properties and extensions). I confirmed the impact from the linked JRuby run: the setup-java step logged maven cache is not found, then ./mvnw failed with wget: Failed to fetch https://repo1.maven.org/.../apache-maven-3.9.14-bin.zip. JRuby's maven-wrapper.properties changed only twice in about two years, while the repo has 31 pom.xml files that each rotate the shared key, so the wrapper was evicted far more often than it actually changes.

Gradle: The wrapper distribution (~/.gradle/wrapper) shared the ~/.gradle/caches entry, keyed on volatile files such as **/*.gradle*, with the same net effect — the wrapper was re-downloaded on nearly every dependency change.

Approach:

Give each build-tool wrapper distribution its own cache entry, keyed only on its wrapper properties file, so it survives the frequent dependency changes that invalidate the main dependency cache.

  • Adds a generic additionalCaches concept to PackageManager, restored and saved independently with name-scoped state keys so restore/save state does not collide with the main cache.
  • Moves ~/.m2/wrapper/dists out of the main maven path into a maven-wrapper additional cache keyed on **/.mvn/wrapper/maven-wrapper.properties.
  • Moves ~/.gradle/wrapper out of the main gradle path into a gradle-wrapper additional cache keyed on **/gradle-wrapper.properties.
  • Each additional cache is skipped silently when the project does not use the corresponding wrapper (no wrapper properties file).
  • Keeps the cache-hit and cache-primary-key outputs driven by the main dependency cache, so existing behavior and outputs are unchanged.

Related issue:

Fixes: #1095

Check list:

  • Ran npm run check locally (format, lint, build, test) and all checks pass.
  • Mark if documentation changes are required.
  • Mark if tests were added or updated to cover the changes.

The Maven wrapper distribution (~/.m2/wrapper/dists) was cached in the same
entry as the local Maven repository (~/.m2/repository), keyed on a hash of
**/pom.xml (plus wrapper properties and extensions). Because pom.xml changes
frequently and no restoreKeys are used (by design, #269), almost every change
produces a full cache miss and the wrapper distribution is re-downloaded via
mvnw — which intermittently fails due to upstream rate limiting.
The wrapper distribution only depends on maven-wrapper.properties, which
changes very rarely. Give it its own cache entry keyed solely on
**/.mvn/wrapper/maven-wrapper.properties so it survives the frequent pom.xml
changes that rotate the main dependency cache key.
- Add a generic additionalCaches concept to PackageManager, restored and saved
independently with name-scoped state keys.
- Move ~/.m2/wrapper/dists out of the main maven path into a maven-wrapper
additional cache; skip silently when the project does not use mvnw.
- Keep cache-hit / cache-primary-key outputs driven by the main cache.
- Update tests, docs, and rebuild dist bundles.
Fixes#1095
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings July 10, 2026 00:29
@brunoborges
brunoborges requested a review from a team as a code ownerJuly 10, 2026 00:29

CopilotAI 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 improves cache: maven reliability by splitting the Maven Wrapper distribution (~/.m2/wrapper/dists) into its own independently-keyed cache entry, so wrapper downloads are not evicted by frequent pom.xml-driven key rotations in the main Maven dependency cache.

Changes:

  • Introduces a generic additionalCaches mechanism in the caching layer to restore/save auxiliary caches independently from the main dependency cache.
  • Moves Maven Wrapper distributions to a separate cache entry keyed only on **/.mvn/wrapper/maven-wrapper.properties.
  • Updates documentation and unit tests to reflect and validate the new caching behavior.
Show a summary per file
FileDescription
src/cache.tsAdds additionalCaches support and splits Maven wrapper dists into a separately-keyed cache entry.
tests/cache.test.tsUpdates/extends cache tests for Maven and adds coverage for wrapper cache restore/save behavior.
README.mdDocuments that the Maven wrapper distribution cache is stored separately from the main Maven cache.
docs/advanced-usage.mdUpdates advanced caching docs to describe the new separate wrapper cache entry and its rationale.
dist/setup/index.jsUpdates the built distribution output to include the new caching logic.
dist/cleanup/index.jsUpdates the built distribution output to include the new caching logic.

Review details

Tip

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

Comments suppressed due to low confidence (1)

src/cache.ts:145

  • The cache-key format described here doesn’t match the actual key produced by buildCacheKey (it includes the setup-java prefix, RUNNER_OS, and process.arch). This makes the documentation misleading for users/debugging.
/**
* A function that generates a cache key to use.
* Format of the generated key will be "${{ platform }}-${{ id }}-${{ fileHash }}"".
* @see {@link https://docs.github.com/en/actions/guides/caching-dependencies-to-speed-up-workflows#matching-a-cache-key|spec of cache key}
*/
  • Files reviewed: 4/6 changed files
  • Comments generated: 3
  • Review effort level: Low

Comment threadsrc/cache.ts Outdated
Comment threadsrc/cache.ts
Comment thread__tests__/cache.test.ts Outdated
#1098)
The Gradle wrapper distribution (~/.gradle/wrapper) only depends on
gradle-wrapper.properties, which changes rarely, but it was previously
cached in the same entry as ~/.gradle/caches, keyed on volatile
**/*.gradle* files with no restoreKeys (issue #269). Every dependency
change therefore re-downloaded the wrapper.
Move ~/.gradle/wrapper into a dedicated `gradle-wrapper` additional
cache keyed only on **/gradle-wrapper.properties, reusing the
additionalCaches infrastructure introduced for the Maven wrapper fix.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@brunoborgesbrunoborges changed the title Cache Maven wrapper distribution separately from the local repositoryCache Maven and Gradle wrapper distributions separately from the dependency cacheJul 10, 2026
brunoborgesand others added 3 commits July 9, 2026 21:09
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

CopilotAI 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.

Review details

  • Files reviewed: 4/6 changed files
  • Comments generated: 3
  • Review effort level: Low

Comment threadsrc/cache.ts
Comment threadsrc/cache.ts Outdated
Comment threadREADME.md
brunoborgesand others added 3 commits July 9, 2026 21:16
The autofix commits dropped the `} catch (error) {` line in
saveAdditionalCache, leaving a `try` block without a catch and a dangling
`error` reference, which broke compilation and Prettier. Restore the catch
clause, reformat, and regenerate the dist bundles.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- saveAdditionalCache: handle @actions/cache ValidationError (thrown when the
cache paths do not resolve, e.g. the wrapper distribution was never
downloaded) by skipping instead of failing the post step. Add a test.
- Point the Gradle wrapper cache comment at issue #269 (Gradle wrapper cache
churn) instead of the Maven-specific #1095.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add a parallel "Gradle Wrapper" note alongside the Maven Wrapper note, so the
new behavior for cache: 'gradle' (caching ~/.gradle/wrapper in a separate entry
keyed on **/gradle-wrapper.properties) is documented.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

CopilotAI 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.

Review details

  • Files reviewed: 4/6 changed files
  • Comments generated: 0 new
  • Review effort level: Low

@brunoborges

Copy link
Copy Markdown
ContributorAuthor

Backport PR #1122

@brunoborges
brunoborges merged commit 81c13a4 into mainJul 14, 2026
422 checks passed
@brunoborges
brunoborges deleted the brunoborges-fix-maven-wrapper-caching branch July 14, 2026 21:14
brunoborges added a commit that referenced this pull request Jul 14, 2026
…parately (#1122)
Backports the wrapper caching fix to the v5 release line.
The Maven wrapper distribution (~/.m2/wrapper/dists) and Gradle wrapper
distribution (~/.gradle/wrapper) were cached in the same entry as the
dependency cache, keyed on the volatile dependency-file hashes (**/pom.xml,
**/*.gradle*). With no restoreKeys fallback (#269), almost every dependency
change was a full cache miss, forcing ./mvnw and ./gradlew to re-download the
build tool distribution and hitting intermittent rate-limit failures.
Each wrapper distribution now lives in its own additional cache entry keyed
only on the rarely-changing wrapper properties file
(**/.mvn/wrapper/maven-wrapper.properties, **/gradle-wrapper.properties), so
it survives dependency changes. Optional-cache saves swallow ValidationError
and ReserveCacheError so a project without a wrapper never fails the post step.
Fixes: #1095
Copilot-Session: ea015caa-980a-4e0a-af20-3fc9f39c77fd
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Maven wrapper caching does not seem to cache enough

2 participants

@brunoborges