diff --git a/apps/flipcash/app/build.gradle.kts b/apps/flipcash/app/build.gradle.kts index d7ef61b2d2..fea7f6daa1 100644 --- a/apps/flipcash/app/build.gradle.kts +++ b/apps/flipcash/app/build.gradle.kts @@ -1,3 +1,4 @@ +import com.android.build.api.artifact.SingleArtifact import com.android.build.api.variant.BuildConfigField import com.bugsnag.gradle.dsl.debug import com.bugsnag.gradle.dsl.release @@ -194,6 +195,28 @@ kotlin { } } +// Fails when an asset the app can't start without is missing from the merged assets. A library on +// the KMP android target drops its assets unless it sets `androidResources { enable = true }`, and +// that build still succeeds: :libs:currency-math lost its curve tables that way in #1894, and every +// launch crashed (Bugsnag 6aadeebd). +abstract class CheckPackagedAssets : DefaultTask() { + @get:InputFiles + @get:PathSensitive(PathSensitivity.RELATIVE) + abstract val assetsDir: DirectoryProperty + + @get:Input + abstract val required: ListProperty + + @TaskAction + fun check() { + val dir = assetsDir.get().asFile + val missing = required.get().filterNot { dir.resolve(it).isFile } + if (missing.isNotEmpty()) { + throw GradleException("Merged assets in $dir are missing: ${missing.joinToString()}") + } + } +} + // Expose Compose testTags as resource-ids (for UiAutomator/Maestro/baseline-profile // generation) on every variant EXCEPT the shipping `release` — keeps internal ids like // `seed_input_field` out of the production wallet build. Read in App.kt as @@ -208,6 +231,17 @@ androidComponents { "testTags exposed as resource-ids; false only for shipping release", ), ) + + val checkCurveAssets = tasks.register( + "check${variant.name.replaceFirstChar { it.uppercase() }}CurveAssets", + ) { + assetsDir.set(variant.artifacts.get(SingleArtifact.ASSETS)) + required.set(listOf("discrete_pricing_table.bin", "discrete_cumulative_table.bin")) + } + if (variant.name == "release") { + tasks.matching { it.name == "bundleRelease" || it.name == "assembleRelease" } + .configureEach { dependsOn(checkCurveAssets) } + } } } diff --git a/build.gradle.kts b/build.gradle.kts index 1033c682a0..83acacc192 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -93,4 +93,6 @@ tasks.register("flipcashTestDebug") { dependsOn(gradle.includedBuild("build-logic").task(":convention:test")) // EVENTS.md is generated from events.toml but checked in; fail when someone edits one alone. dependsOn(":libs:analytics-events:checkAnalyticsEventsPage") + // The app's merged assets still carry the files it needs to start, such as the curve tables. + dependsOn(":apps:flipcash:app:checkDebugCurveAssets") } diff --git a/libs/currency-math/build.gradle.kts b/libs/currency-math/build.gradle.kts index 89c2dc44ea..a50969b4ee 100644 --- a/libs/currency-math/build.gradle.kts +++ b/libs/currency-math/build.gradle.kts @@ -5,6 +5,9 @@ plugins { kotlin { android { namespace = "${Gradle.codeNamespace}.libs.currency.math" + // The KMP android target skips res and assets unless this is on, and the curve tables + // ship as assets. Without it the app has no tables and crashes on the first token balance. + androidResources { enable = true } withDeviceTestBuilder {}.configure { instrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" }