A gradle plugin for detecting regressions in Jetpack Compose / Compose Multiplatform:
- New restartable but not skippable @Composables are added
- New unstable classes are added (only triggers if they are used as a @Composable parameter)
- New @dynamic properties are added
- New unstable parameters are added to a @Composable
In an Android project, Compose Guard adds 3 tasks:
<variant>ComposeCompilerGenerate
(example./gradlew releaseComposeCompilerGenerate
)- Generate golden compose metrics to compare against
<variant>ComposeCompilerCheck
(example./gradlew releaseComposeCompilerCheck
)- Generates new metrics and compares against golden values
./gradlew composeCompilerClean
- Deletes all compiler metrics
In a Multiplatform project, Compose Guard adds the same 2 Check
and Generate
tasks (as well as a root composeCompilerClean
task) for each supported target following the pattern <target><variant if applicable>ComposeCompilerGenerate
<target><variant>ComposeCompilerGenerate
- Examples:
./gradlew androidReleaseComposeCompilerGenerate
,./gradlew jvmComposeCompilerGenerate
,./gradlew iosArm64ComposeCompilerGenerate
,./gradlew jsComposeCompilerGenerate
,./gradlew wasmJsComposeCompilerGenerate
- Generate golden compose metrics to compare against
- Examples:
<target><variant>ComposeCompilerCheck
- Examples:
./gradlew androidReleaseComposeCompilerCheck
,./gradlew jvmComposeCompilerCheck
,./gradlew iosArm64ComposeCompilerCheck
,./gradlew jsComposeCompilerCheck
,./gradlew wasmJsComposeCompilerCheck
- Generates new metrics and compares against golden values
- Examples:
./gradlew composeCompilerClean
- Deletes all compiler metrics
✅ | ✅ | ✅ | ✅ |
In your root build file:
plugins {
id("com.joetr.compose.guard") version "<latest version>" apply false
}
In any module you want to apply checks:
plugins {
id("com.joetr.compose.guard")
}
Each check that is performed has the ability to be turned off in case it is not useful to you.
composeGuardCheck {
errorOnNewDynamicProperties = false // defaults to true
errorOnNewRestartableButNotSkippableComposables = false // defaults to true
errorOnNewUnstableClasses = false // defaults to true
errorOnNewUnstableParams = false // defaults to true
/**
* In strong skipping mode (https://developer.android.com/develop/ui/compose/performance/stability/strongskipping)
* you may not care about new unstable params if the composable is already skippable
*/
ignoreUnstableParamsOnSkippableComposables = true // defaults to false
/**
* If baseline metrics are missing, the check task will no longer fail and will instead just report
* all checks.
*/
reportAllOnMissingBaseline = true // defaults to false
/**
* Stability cannot be automatically inferred across module boundaries. With this option enabled,
* any properties marked as 'runtime' stability will be inferred to be unstable. If you can guarantee properties
* as stable across module boundaries, mark them as so.
*/
assumeRuntimeStabilityAsUnstable = true // defaults to false
}
The output directory of the golden metrics has the ability to be configured as well.
composeGuardGenerate {
outputDirectory = layout.projectDirectory.dir("custom_dir").asFile
}
Additionally, if you would prefer complete control over how the metrics are generated, you can disable this plugin from configuring the Kotlin compile task. This is intended advanced users that prefer compiler performance over easy baseline generation. With this set, the plugin no longer configures anything in the Kotlin compile task. So an end user would be responsible for generating the golden metrics and the check metrics before running the check task.
composeGuard {
configureKotlinTasks = false // defaults to true
}
This is required to test.
- Install gnupg - https://formulae.brew.sh/formula/gnupg
- Generate a key - https://central.sonatype.org/publish/requirements/gpg/#generating-a-key-pair
gpg --full-generate-key
- List keys and grab newly generated key (40 digits)
gpg --list-keys
gpg --export-secret-keys THE_KEY_THAT_YOU_JUST_GENERATED > composeguard.gpg
- Modify your gradle home
gradle.properties
with the following:
signing.keyId=LAST_8_DIGITS_OF_KEY
signing.password=PASSWORD_USED_TO_GENERATE_KEY
signing.secretKeyRingFile=/Users/YOURUSERNAME/.gnupg/composeguard.gpg (or wherever you stored the keyring you generated earlier)
This project uses this tool to ensure the public binary API wasn't changed in a way that makes it binary incompatible.
The tool allows dumping binary API of a JVM part of a Kotlin library that is public in the sense of Kotlin visibilities.
To generate a new binary dump, run ./gradlew apiDump
in the root of the project.