Add Gradle cache to Android release builds #251

Closed
opened 2026-05-25 16:46:46 +00:00 by guettlibot · 2 comments
guettlibot commented 2026-05-25 16:46:46 +00:00 (Migrated from codeberg.org)

Fixes Bottleneck 1 from #244 (~5–10 min savings).

File: ci/main.go

BuildAndroidRelease() and BuildAndroidApk() go through the setup()codegenBase()pubGetLayer()toolchain() chain. None of these mount the Gradle named cache volume. When Dagger's execution cache misses (i.e. any source file in androidSrc() has changed), Gradle downloads all its dependencies from scratch on every run.

By contrast, BuildAndroidDebugApks() already explicitly mounts the cache:

m.setup(m.firebaseSrc()).
    WithMountedCache("/home/ci/.gradle", dag.CacheVolume("gradle-cache"), ...)

Implementation plan

Introduce an androidBase() helper that wraps setup(androidSrc()) and attaches the Gradle cache, then use it in the Android build functions:

func (m *Ci) androidBase() *dagger.Container {
    return m.setup(m.androidSrc()).
        WithMountedCache("/home/ci/.gradle", dag.CacheVolume("gradle-cache"),
            dagger.ContainerWithMountedCacheOpts{Owner: "ci"})
}

Then update:

  • BuildAndroidRelease(): replace m.setup(m.androidSrc()) with m.androidBase()
  • setupKeystore(): replace m.setup(m.androidSrc()) with m.androidBase()
  • BuildAndroidDebugApks(): replace m.setup(m.firebaseSrc()).WithMountedCache(...) with a firebaseBase() equivalent (same pattern but starting from m.setup(m.firebaseSrc()))

Expected saving: ~5–10 min on runs where source changed. The Gradle cache fix alone should bring typical runtime from ~25 min down to ~12–15 min on source-change runs, and near-instant on unchanged code.

Risk: Adding a mutable cache volume means Dagger cannot include the Gradle cache content in its content-addressable execution key for the build step — it treats such steps as always-re-runnable when the source changes. This is the intended Dagger trade-off and is already accepted for BuildAndroidDebugApks(). The Dagger execution cache still deduplicates unchanged source → identical container snapshot runs.

Open question

Does the Gradle cache volume (gradle-cache) survive Dagger engine restarts / dagger prune runs? The ci.yml prunes the cache before and after every check run. If prune evicts the Gradle cache volume, the benefit disappears on the first run after every CI check. Worth checking whether the named volume survives pruning at 75 GB / targeting 50 GB.

Fixes Bottleneck 1 from #244 (~5–10 min savings). **File:** `ci/main.go` `BuildAndroidRelease()` and `BuildAndroidApk()` go through the `setup()` → `codegenBase()` → `pubGetLayer()` → `toolchain()` chain. **None of these mount the Gradle named cache volume.** When Dagger's execution cache misses (i.e. any source file in `androidSrc()` has changed), Gradle downloads all its dependencies from scratch on every run. By contrast, `BuildAndroidDebugApks()` already explicitly mounts the cache: ```go m.setup(m.firebaseSrc()). WithMountedCache("/home/ci/.gradle", dag.CacheVolume("gradle-cache"), ...) ``` ## Implementation plan Introduce an `androidBase()` helper that wraps `setup(androidSrc())` and attaches the Gradle cache, then use it in the Android build functions: ```go func (m *Ci) androidBase() *dagger.Container { return m.setup(m.androidSrc()). WithMountedCache("/home/ci/.gradle", dag.CacheVolume("gradle-cache"), dagger.ContainerWithMountedCacheOpts{Owner: "ci"}) } ``` Then update: - `BuildAndroidRelease()`: replace `m.setup(m.androidSrc())` with `m.androidBase()` - `setupKeystore()`: replace `m.setup(m.androidSrc())` with `m.androidBase()` - `BuildAndroidDebugApks()`: replace `m.setup(m.firebaseSrc()).WithMountedCache(...)` with a `firebaseBase()` equivalent (same pattern but starting from `m.setup(m.firebaseSrc())`) **Expected saving:** ~5–10 min on runs where source changed. The Gradle cache fix alone should bring typical runtime from ~25 min down to ~12–15 min on source-change runs, and near-instant on unchanged code. **Risk:** Adding a mutable cache volume means Dagger cannot include the Gradle cache content in its content-addressable execution key for the build step — it treats such steps as always-re-runnable when the source changes. This is the intended Dagger trade-off and is already accepted for `BuildAndroidDebugApks()`. The Dagger execution cache still deduplicates unchanged source → identical container snapshot runs. ## Open question Does the Gradle cache volume (`gradle-cache`) survive Dagger engine restarts / `dagger prune` runs? The `ci.yml` prunes the cache before and after every check run. If prune evicts the Gradle cache volume, the benefit disappears on the first run after every CI check. Worth checking whether the named volume survives pruning at 75 GB / targeting 50 GB.
guettlibot commented 2026-05-25 16:52:08 +00:00 (Migrated from codeberg.org)

Automatic merge of PR #252 failed (PR is still open after the merge command). Please merge manually.

Automatic merge of PR #252 failed (PR is still open after the merge command). Please merge manually.
guettlibot commented 2026-05-25 17:01:16 +00:00 (Migrated from codeberg.org)

Automatic merge of PR #252 failed (PR is still open after the merge command). Please merge manually.

Automatic merge of PR #252 failed (PR is still open after the merge command). Please merge manually.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: guettli/sharedinbox#251