A powerful Gradle Plugin for Android projects that tracks, compares, and reports build performance metrics β including total build time, per-module durations, per-task durations, and regressions between builds.
Never let your build times creep up again. π
A Gradle Plugin is a build-time tool β it runs during your build process, not inside your app. It never becomes part of your APK. It hooks into Gradle's lifecycle to observe, measure, or modify how your project is built.
This is fundamentally different from a regular Android library:
| Regular Library (e.g. Retrofit) | Gradle Plugin (e.g. BuildPulse) | |
|---|---|---|
| Added via | implementation(...) in module's build.gradle.kts |
id(...) in root plugins {} block |
| Runs | Inside your app, on a device | During the build, on your machine |
| Part of APK? | β Yes | β No |
| Examples | Coil, Room, OkHttp | Hilt, KSP, BuildPulse |
- β±οΈ Total build time tracking β measures how long your entire build takes
- π¦ Module-level breakdown β see which modules (
:app,:feature-login,:core-network) are slowest - π§ Task-level breakdown β drill down into individual Gradle tasks
- π Regression detection β compares current build vs previous build and flags slowdowns
- π¨ CI enforcement β optionally fail the build if a regression exceeds your threshold
- π HTML report β generates a beautiful visual report at
buildpulse/build-metrics.html - πΎ Metrics persistence β saves metrics to
buildpulse/build-metrics.jsonfor comparison across builds - π― Zero dependencies β pure Gradle + Kotlin stdlib, no external libraries
Add the plugin to your root build.gradle.kts:
plugins {
id("io.github.PatilParas05.buildpulse-android") version "1.0.0" // β Add this
}That's it! Sync your project and run a build.
Always use the latest version from the Gradle Plugin Portal.
BuildPulse runs automatically every time you build your project. No special commands needed.
./gradlew assembleDebugConsole Output:
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π BuildPulse β Metrics Summary β
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
Total build time: 25.3s (first run)
Module Breakdown (sorted by time β)
βββββββββββββββββββββββββββββββββββββ
app 40,056 ms
core-network 22,347 ms
feature-login 16,987 ms
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
./gradlew assembleDebugConsole Output:
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
β π BuildPulse β Metrics Summary β
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
Total build time: 18.2s (-7.1s β
)
Module Breakdown (sorted by time β)
βββββββββββββββββββββββββββββββββββββ
app 28,120 ms (-11,936 ms β
)
core-network 15,230 ms (-7,117 ms β
)
feature-login 12,450 ms (-4,537 ms β
)
β
BuildPulse CI Check: no regressions detected.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Open buildpulse/build-metrics.html in your browser for an interactive dashboard:
buildpulse/
βββ build-metrics.json β raw metrics data
βββ build-metrics.html β open this in browser β
In Android Studio:
- Find the file in Project panel
- Right-click β Open In β Browser
All options are configured in the buildPulse { } block in your root build.gradle.kts:
| Option | Type | Default | Description |
|---|---|---|---|
enabled |
Boolean |
true |
Enable or disable the plugin entirely |
trackTasks |
Boolean |
true |
Track individual task durations |
trackModules |
Boolean |
true |
Roll up task times into module totals |
failOnRegression |
Boolean |
false |
Fail the build if a regression is detected |
maxAllowedIncreaseMs |
Long |
500L |
Threshold in ms above which a slowdown is a regression |
outputDir |
String |
"buildpulse" |
Directory where JSON and HTML reports are written |
generatedHtmlReport |
Boolean |
true |
Whether to generate the HTML visual report |
buildPulse {
failOnRegression = true // β Fail builds on regression
maxAllowedIncreaseMs = 500L // β Max allowed slowdown
}Now if any module gets slower by more than 500ms, the build fails:
β BuildPulse CI Check FAILED β regression detected!
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Regressions (threshold exceeded) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β [Module] app +720 ms
β prev: 28,120 ms β now: 28,840 ms
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
BUILD FAILED
buildpulse-android/
βββ plugin/ # The Gradle plugin source
β βββ src/main/kotlin/
β βββ dev/paraspatil/buildpulse/
β βββ BuildPulsePlugin.kt # Plugin entry point
β βββ BuildPulseExtension.kt # DSL configuration
β βββ TaskTimingListener.kt # Hooks into Gradle task lifecycle
β βββ MetricsCollector.kt # Aggregates timing data
β βββ MetricsStore.kt # Saves/loads metrics as JSON
β βββ MetricsComparator.kt # Diffs current vs previous build
β βββ ReportGenerator.kt # Console report
β βββ HtmlReportGenerator.kt # HTML report
β βββ CIEnforcer.kt # Fails build on regression
β βββ model/
β βββ BuildMetrics.kt # Data models
βββ app/ # Sample Android app
βββ feature-login/ # Sample feature module
βββ core-network/ # Sample core module
βββ buildpulse/ # Generated output (after build)
βββ build-metrics.json
βββ build-metrics.html
- Plugin Registration:
BuildPulsePluginregisters aTaskExecutionListenerviaTaskTimingListener - Task Tracking: Before each task runs, it records a start timestamp; after completion, it calculates elapsed time
- Build Finished: When
gradle.buildFinishedfires,MetricsCollectoraggregates task times into module totals - Load Previous:
MetricsStoreloads the previous build's metrics from JSON (if it exists) - Comparison:
MetricsComparatordiffs the two builds to find regressions and improvements - Console Report:
ReportGeneratorprints a summary to the console - HTML Report:
HtmlReportGeneratorwrites a visual dashboard to disk - CI Enforcement:
CIEnforceroptionally throws aGradleExceptionif regressions exceed the threshold
- How Gradle plugins work internally and how they differ from Android libraries
- How
TaskExecutionListenerhooks into the build lifecycle - How composite builds (
includeBuild) allow local plugin development without publishing - How plugin marker artifacts work and the Gradle Plugin Portal submission process
- How to serialize/deserialize build metrics manually (without a JSON library)
- How to generate HTML reports from Kotlin string templates
- How to enforce build quality gates in CI/CD pipelines
Contributions are welcome! Please:
- Fork the repo
- Create a feature branch (
git checkout -b feature/amazing) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing) - Open a Pull Request
MIT License - see LICENSE file for details.
Paras Patil
- GitHub: @PatilParas05
- LinkedIn: Paras Patil
- Gradle Plugin: BuildPulse Android
Built with β€οΈ to solve a real pain point in Android development.
If BuildPulse helped you catch a build regression, give it a β!
- π Bug reports: GitHub Issues
- π¬ Questions: GitHub Discussions
- π Plugin Page: Gradle Plugin Portal
If you find BuildPulse useful:
- β Star this repo
- π¦ Share on Twitter
- π Write a blog post about it
- π¬ Tell your teammates
- π Gradle Plugin Portal β Official plugin page
- π Report an Issue β Found a bug?
- π‘ Request a Feature β Have an idea?
Made with β and Kotlin
BuildPulse β’ Keep Your Builds Fast π
