From 1657d5e45991cde16b54c74adf88e28e6ebec6b7 Mon Sep 17 00:00:00 2001 From: mattbalza Date: Fri, 7 Aug 2026 19:13:33 +0200 Subject: [PATCH 1/2] ci(mobile): cache Gradle so the APK build stops re-downloading Maven Central MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Mobile job caches Hermit and pub but not Gradle, so every run re-resolved the entire Android/Kotlin dependency graph over the network. Run 31196146152 got a 429 from repo.maven.apache.org resolving kotlin-gradle-plugins-bom while evaluating mobile/android/settings.gradle.kts, and Flutter's built-in retry waits 100ms — both attempts died inside the same rate-limit window, 6s apart. Caching ~/.gradle/caches and ~/.gradle/wrapper removes the round trip entirely on a warm key rather than retrying it, and shortens the build besides. --- .github/workflows/ci.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e65157705a..af03e76236 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -869,8 +869,31 @@ jobs: run: cd mobile && flutter analyze - name: Test run: cd mobile && flutter test + # Without this, every APK build re-resolves the whole Android/Kotlin graph + # from Maven Central, which rate-limits us (run 31196146152 died on a 429 for + # kotlin-gradle-plugins-bom while resolving settings.gradle.kts). Flutter's own + # retry waits 100ms, so both attempts land inside the same 429 window. + # simplify: a cold cache still makes the round trip; add a retry if that recurs. + - name: Restore Gradle cache + id: gradle-cache + uses: actions/cache/restore@caa296126883cff596d87d8935842f9db880ef25 # v5 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: gradle-${{ runner.os }}-${{ hashFiles('mobile/android/**/*.gradle*', 'mobile/android/gradle.properties', 'mobile/android/gradle/wrapper/gradle-wrapper.properties', 'mobile/pubspec.lock') }} + restore-keys: gradle-${{ runner.os }}- - name: Build Android debug APK run: just mobile-build-android + - name: Save Gradle cache + if: always() && steps.gradle-cache.outputs.cache-hit != 'true' + uses: actions/cache/save@caa296126883cff596d87d8935842f9db880ef25 # v5 + continue-on-error: true + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: gradle-${{ runner.os }}-${{ hashFiles('mobile/android/**/*.gradle*', 'mobile/android/gradle.properties', 'mobile/android/gradle/wrapper/gradle-wrapper.properties', 'mobile/pubspec.lock') }} security: name: Security From bb5525d850015f765d44a15f11c9cb66c4874b1a Mon Sep 17 00:00:00 2001 From: mattbalza Date: Fri, 7 Aug 2026 19:38:21 +0200 Subject: [PATCH 2/2] ci(mobile): cache only modules-2, not the whole Gradle cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first version cached all of ~/.gradle/caches, which came out at 2429 MB. The repo shares a 10 GB Actions cache budget with the cargo, pnpm and Hermit entries, and LRU eviction would have pushed those out to keep this one. modules-2 holds the downloaded artifacts — the network dependency that got 429'd. Everything else under caches/ is derived (build-cache, transforms, jars): losing it costs CPU to recompute, which is not what was failing. --- .github/workflows/ci.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index af03e76236..df579c3edd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -873,13 +873,19 @@ jobs: # from Maven Central, which rate-limits us (run 31196146152 died on a 429 for # kotlin-gradle-plugins-bom while resolving settings.gradle.kts). Flutter's own # retry waits 100ms, so both attempts land inside the same 429 window. + # + # modules-2 only, not all of ~/.gradle/caches: modules-2 is the downloaded + # artifacts, which is the network dependency being fixed. The rest is derived + # (build-cache, transforms, jars) — caching it took the entry to 2.4 GB against + # a repo-wide 10 GB budget shared with the cargo, pnpm and Hermit caches, and + # would have evicted them to save CPU we are not short of. # simplify: a cold cache still makes the round trip; add a retry if that recurs. - name: Restore Gradle cache id: gradle-cache uses: actions/cache/restore@caa296126883cff596d87d8935842f9db880ef25 # v5 with: path: | - ~/.gradle/caches + ~/.gradle/caches/modules-2 ~/.gradle/wrapper key: gradle-${{ runner.os }}-${{ hashFiles('mobile/android/**/*.gradle*', 'mobile/android/gradle.properties', 'mobile/android/gradle/wrapper/gradle-wrapper.properties', 'mobile/pubspec.lock') }} restore-keys: gradle-${{ runner.os }}- @@ -891,7 +897,7 @@ jobs: continue-on-error: true with: path: | - ~/.gradle/caches + ~/.gradle/caches/modules-2 ~/.gradle/wrapper key: gradle-${{ runner.os }}-${{ hashFiles('mobile/android/**/*.gradle*', 'mobile/android/gradle.properties', 'mobile/android/gradle/wrapper/gradle-wrapper.properties', 'mobile/pubspec.lock') }}