Skip to content

fix(build): stop KMP host tests building release variants and debug manifests changing per commit - #1948

Merged
bmc08gt merged 3 commits into
code/cashfrom
fix/ci-gradle-cache-misses
Nov 3, 2026
Merged

bmc08gt merged 3 commits into
code/cashfrom
fix/ci-gradle-cache-misses

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Unit tests takes about 16 minutes, and on warm code/cash pushes most of that is work the build cache should have skipped. Run 41547433541 restored the previous commit's cache and still executed 2,821 of 4,584 actionable tasks. Three causes:

1. KMP modules built release copies of their Android dependencies. The single-variant KMP Android target picks one build type from each Android-library dependency, and AGP defaults that to release. flipcashTestDebug therefore compiled 25 Android libraries twice, debug for their own tests and release for the KMP host tests: 444 release-variant tasks, compileReleaseKotlin included. Both KMP convention plugins now set localDependencySelection { selectBuildTypeFrom = [debug, release] }. The task graph drops from 5,932 tasks to 5,426, with no release tasks left.

This changes what the KMP host tests run against: debug builds of those libraries instead of release builds. The debug app already runs on the debug builds. The app's own releaseRuntimeClasspath resolves by the app's attributes and is untouched.

2. The app read the commit SHA while configuring. bugsnagBuildId ran git rev-parse HEAD at configuration time and went into every variant's manifest. Each commit changed the debug manifest, re-ran :apps:flipcash:app:testDebugUnitTest, and invalidated the configuration cache. Bugsnag is off in debug, so debug now gets the constant "debug". The SHA is a lazy provider wired only into non-debug variants and the mapping upload.

versionCode (git rev-list --count) has the same shape, but CI's fetch-depth: 1 checkout always counts 1, so it doesn't vary there and this PR leaves it alone.

3. The configuration cache never survived a run. Every run logs "no cached configuration is available" and spends about a minute configuring (23:43:08 to the first project task at 23:44:05 in that run). setup-gradle saves the configuration cache only with cache-encryption-key, since the entry holds the provisioned API keys. Both jobs now pass secrets.GRADLE_ENCRYPTION_KEY. Until that secret exists, the input is empty and setup-gradle skips the configuration cache as it does today.

Measured locally, fresh checkout per run against a warm local build cache, generateEmojiList flipcashTestDebug:

Executed From cache Compile Kotlin executed Unit-test tasks executed
Before, empty commit 2,121 2,468 2 1
After, empty commit, versionCode 1 as on CI 1,948 2,195 0 0
Before, one string added to apps/flipcash/core 2,879 1,766 102 70
After, same string 2,705 1,496 96 70

The remaining executed tasks on an empty commit are AGP's non-cacheable packaging and copy tasks.

The last two rows are what CI saw on run 41547433541: its counts match the "before, one string" row (102 compile, 70 unit-test tasks executed). That commit added strings to apps/flipcash/core, which most modules depend on, so their R classes change and their compile and test tasks re-run legitimately. This PR doesn't change that; moving resources out of core or narrowing what depends on it is a separate change.

The AGP KMP library target is single-variant and picks the release build
type of each Android-library dependency by default. flipcashTestDebug
runs the KMP host tests next to the Android modules' debug unit tests,
so it also built a release copy of 25 Android libraries:
compileReleaseKotlin, processReleaseManifest, the release resource and
jar tasks. Selecting debug first drops the task graph from 4584 to 4139
actionable tasks with no release-variant tasks left.

The app's releaseRuntimeClasspath still resolves releaseRuntimeElements,
so release builds package the same libraries as before.
bugsnagBuildId ran `git rev-parse HEAD` while configuring and went into
the manifest of every variant, so each new commit changed the debug
manifest that flipcashTestDebug builds and invalidated the configuration
cache.

Bugsnag is disabled for debug and nothing reads the build UUID there, so
debug now gets the constant "debug" and the SHA is a lazy provider wired
into the other variants' manifests and the mapping upload. With this and
the KMP fix, a new commit with no source changes, built from a fresh
checkout against a warm local cache with versionCode at the 1 that
CI's shallow clone produces, runs no compile or test task: 1945
executed, 2195 from cache, all of the executed ones AGP's non-cacheable
packaging and copy tasks.
Every run logs "Calculating task graph as no cached configuration is
available" and spends about a minute configuring (23:43:08 to the first
project task at 23:44:05 in run 41547433541). setup-gradle saves and
restores the configuration cache only when given cache-encryption-key,
because the entry holds the API keys from local.properties. Without the
GRADLE_ENCRYPTION_KEY secret it skips that step, so this is a no-op
until the secret exists.
@bmc08gt bmc08gt self-assigned this Nov 3, 2026
@bmc08gt
bmc08gt requested a review from jeffyanta as a code owner November 3, 2026 02:40
@github-actions github-actions Bot added type: fix Bug fix area: build-system Gradle, convention plugins, build-logic labels Nov 3, 2026
@bmc08gt
bmc08gt merged commit dc3f585 into code/cash Nov 3, 2026
5 checks passed
bmc08gt added a commit that referenced this pull request Nov 3, 2026
…ee-pane

* origin/code/cash: (44 commits)
  refactor(chat-list): move the chat list into a KMP module and wire it into the desktop graph (#1950)
  build(deps): bump dev.zacsweers.metro from 1.4.5 to 1.5.1 (#1901)
  feat(flipcash): add return-payment contract scaffolding (#1949)
  refactor(chat-ui): make shared/chat-ui a KMP module (#1934)
  build(deps): bump com.google.firebase:firebase-bom from 34.19.0 to 35.1.0 (#1900)
  build(deps): bump io.ktor:ktor-network from 3.4.1 to 3.6.0 (#1909)
  build(deps): bump rinku from 1.6.0 to 1.9.0 (#1907)
  build(deps): bump androidx.webkit:webkit from 1.17.0 to 1.18.0 (#1906)
  build(deps): bump agp from 9.4.1 to 9.5.0 (#1905)
  build(deps): bump androidx-datastore from 1.2.1 to 1.3.0 (#1904)
  build(deps): bump compose-multiplatform from 1.12.1 to 1.12.2 (#1903)
  build(deps): bump com.google.android.gms:play-services-base (#1902)
  build(deps): bump okhttp from 5.5.0 to 5.5.1 (#1899)
  refactor(messenger): split ChatViewModel's reducer into per-area files (#1933)
  refactor(amount-entry): make shared/amount-entry a KMP module (#1932)
  fix(build): stop KMP host tests building release variants and debug manifests changing per commit (#1948)
  refactor(theme): collapse Avenir into one family with a real Medium face (#1947)
  perf: run independent hot-path calls concurrently (#1945)
  docs(claude): test gestures with device input and keep mode state at screen level (#1943)
  build: bump Flipcash to 2026.11.2
  ...

# Conflicts:
#	CLAUDE.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: build-system Gradle, convention plugins, build-logic type: fix Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant