Cache Gradle dependencies in the live E2E workflow (#7234)

# Description of Changes

Fixes the `playwright-e2e-live` failure seen on [run
30694073128](https://github.com/Stirling-Tools/Stirling-PDF/actions/runs/30694073128).
The backend never started:

```
> Could not resolve org.springframework.boot:spring-boot-buildpack-platform:4.0.6.
   > Could not GET 'https://repo.maven.apache.org/maven2/.../spring-boot-buildpack-platform-4.0.6.pom'.
     Received status code 429 from server: Too Many Requests
> There are 14 more failures with identical causes.
BUILD FAILED in 21s
```

Gradle was throttled by Maven Central while resolving the buildscript
classpath, `:stirling-pdf:bootRun` died, and the runner's "backend
exited before becoming ready" guard aborted the suite before a single
test ran.

`e2e-live.yml` was the only Java-running workflow with no Gradle
dependency cache, no `setup-gradle`, and no Maven mirror env - every
sibling (`backend-build.yml`, `db-migration-test.yml`,
`coverage-aggregate.yml`) has all three. So it downloaded the Gradle
distribution and resolved the entire classpath cold from Maven Central
on every single run, and eventually got throttled.

Added:

- the same `Cache Gradle dependency artifacts` + `Setup Gradle` pair
used by `backend-build.yml`
- `MAVEN_USER` / `MAVEN_PASSWORD` / `MAVEN_PUBLIC_URL` on the two
Gradle-invoking steps, so runs that have the secrets use the internal
mirror instead of hitting Central
- a `Prime Gradle dependencies` step that retries 3x with backoff.
Gradle does not retry 429s, and doing the cold resolve up front means a
rate-limit failure retries cheaply instead of killing a backgrounded
`bootRun` twenty minutes in

Side benefit: the job gets faster once the cache is warm.

## Notes for reviewers

- The 429 itself is transient infrastructure behaviour - a re-run would
likely have gone green. The defect being fixed is that this job had no
cache to fall back on, so it was exposed to it on every run.
- `:stirling-pdf:classes` does not trigger a frontend build
(`buildWithFrontend` defaults off, `app/core/build.gradle:147`), so
priming before the Vite build step is safe. It is not wasted work either
- `bootRun` compiles the same classes.
- This PR originally also carried a fix for the `tauri-build`
updater-key failure on that same run. #7181 fixes that more simply and
has been merged, so that half has been dropped here.
- Workflow changes cannot be fully verified locally; a CI run on this
branch is the real check.

---

## Checklist

### General

- [x] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [x] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [x] I have performed a self-review of my own code
- [x] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [x] I have run `task check` to verify linters, typechecks, and tests
pass
- [x] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
This commit is contained in:
Anthony Stirling
2026-08-03 14:58:14 +00:00
committed by GitHub
parent 21dff695fe
commit 28480d137a
+42
View File
@@ -25,6 +25,39 @@ jobs:
with:
java-version: "25"
distribution: "temurin"
# Same cache layer as backend-build.yml. Without it every run resolved the
# whole classpath cold and eventually got HTTP 429 from Maven Central.
- name: Cache Gradle dependency artifacts
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: |
~/.gradle/wrapper
~/.gradle/caches/modules-2/files-2.1
~/.gradle/caches/modules-2/metadata-2.*
key: gradle-deps-${{ runner.os }}-jdk-25-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties', '**/*.gradle', '**/*.gradle.kts', 'settings.gradle', 'settings.gradle.kts', 'gradle/libs.versions.toml') }}
- name: Setup Gradle
uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0
with:
gradle-version: 9.6.1
cache-disabled: true
# Gradle does not retry 429s, and a cold cache resolving the buildscript
# classpath is exactly where Maven Central rate-limits us. Retry it here,
# where a failure is cheap, instead of inside the backgrounded bootRun.
- name: Prime Gradle dependencies
env:
MAVEN_USER: ${{ secrets.MAVEN_USER }}
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
MAVEN_PUBLIC_URL: ${{ secrets.MAVEN_PUBLIC_URL }}
run: |
for attempt in 1 2 3; do
if ./gradlew --quiet -PnoSpotless :stirling-pdf:classes; then
exit 0
fi
echo "::warning::Gradle dependency resolution failed (attempt $attempt of 3)"
sleep $((attempt * 30))
done
echo "::error::Gradle could not resolve dependencies after 3 attempts"
exit 1
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
@@ -53,6 +86,11 @@ jobs:
# to aggregate. Chromium-only - other engines silently skip.
PW_COVERAGE: "1"
PLAYWRIGHT_JSON_OUTPUT_FILE: ${{ github.workspace }}/frontend/playwright-report/results.json
# Internal mirror, as in backend-build.yml. Empty on Dependabot and
# fork PRs, where the build falls back to Maven Central.
MAVEN_USER: ${{ secrets.MAVEN_USER }}
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
MAVEN_PUBLIC_URL: ${{ secrets.MAVEN_PUBLIC_URL }}
run: task e2e:live
- name: Flag flaky tests
# Runs regardless of the test outcome: a flaky test (passed on retry)
@@ -66,6 +104,10 @@ jobs:
- name: Generate JaCoCo report from e2e:live .exec
if: always()
id: live-coverage
env:
MAVEN_USER: ${{ secrets.MAVEN_USER }}
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
MAVEN_PUBLIC_URL: ${{ secrets.MAVEN_PUBLIC_URL }}
# `if: always()` so even a failed test run still produces a
# report from whatever flows did exercise the backend before
# the failure. The task itself tolerates a missing .exec