Skip to content

trOnk12/compose-guard

Repository files navigation

compose-guard 🛡️

Catch Compose stability regressions before they reach production.

License

Jetpack Compose skips recomposing a composable only when all its parameters are stable. When they're not, Compose recomposes on every state change — causing UI jank, battery drain, and frame drops that users notice. These regressions are invisible in code review.

compose-guard integrates into your CI pipeline and fails the build when a PR introduces new unstable composables that weren't there before.


The problem

Your team is writing Compose code. Someone adds a data class with a List<> property, or passes a ViewModel directly into a composable. The UI starts recomposing 40x per second instead of 2x. Nobody notices until production. Users complain about lag.

Google's Compose Compiler already detects this — but it writes the results to a text file that nobody reads.

compose-guard makes stability a hard gate, like a lint rule that can't be ignored.


Installation

Add to your module's build.gradle.kts:

plugins {
    id("io.github.composeguard") version "0.1.0"
}

Enable Compose compiler metrics (required — add once to your build):

// build.gradle.kts
android {
    kotlinOptions {
        freeCompilerArgs += listOf(
            "-P", "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=${layout.buildDirectory.get()}/compose_metrics",
            "-P", "plugin:androidx.compose.compiler.plugins.kotlin:metricsDestination=${layout.buildDirectory.get()}/compose_metrics"
        )
    }
}

Usage

Step 1 — Generate baseline (run once, commit the file):

./gradlew generateComposeGuardBaseline
# → creates compose-guard-baseline.json in your project root
# → commit this file to your repository

Step 2 — Check in CI (runs on every PR):

./gradlew checkComposeGuard

When a PR introduces a stability regression, the build fails:

╔══════════════════════════════════════════════╗
║       ❌  COMPOSE GUARD FAILED               ║
╚══════════════════════════════════════════════╝

1 new stability regression(s) detected:

  HomeScreen → now UNSTABLE (was stable in baseline)
    unstable param: viewModel: HomeViewModel
    Fix: Add @Stable/@Immutable to unstable types, or wrap lambdas in remember { }

Run './gradlew generateComposeGuardBaseline' ONLY after intentional changes.
Never update the baseline just to make the check pass.

GitHub Actions

# .github/workflows/compose-guard.yml
name: Compose Guard

on:
  pull_request:
    branches: [ main, master ]

jobs:
  stability-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'
      - name: Build with metrics
        run: ./gradlew compileDebugKotlin
      - name: Check Compose stability
        run: ./gradlew checkComposeGuard

Configuration

composeGuard {
    // Fail build on new unstable composables (default: true)
    failOnNewUnstable.set(true)

    // Baseline file location (default: "compose-guard-baseline.json")
    baselineFile.set("compose-guard-baseline.json")

    // Metrics directory (default: build/compose_metrics)
    // metricsOutputDir.set(layout.buildDirectory.dir("compose_metrics"))
}

How it works

  1. Compose compiler metrics — Google's Kotlin compiler plugin generates a *-composables.txt file listing every @Composable and whether it's skippable/stable
  2. Baseline — compose-guard reads that file and saves a JSON snapshot of which composables are stable
  3. CI check — on every build, compares current state to baseline. If a previously-stable composable is now unstable → build fails with actionable error

Why this matters

Without compose-guard With compose-guard
Stability regressions discovered in production Caught at PR review time
Manual investigation with Android Studio profiler Instant diagnosis in CI output
"Why is the app laggy?" — nobody knows Exact composable + parameter identified

Contributing

Issues and PRs welcome. See CONTRIBUTING.md.

License

Apache 2.0 — see LICENSE.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages