android-sdd 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +143 -0
- package/package.json +27 -0
- package/skills/Android Ecosystem/Baseline Profile Generator/SKILL.md +277 -0
- package/skills/Android Ecosystem/Glance/SKILL.md +315 -0
- package/skills/Android Platform/Configuration/SKILL.md +201 -0
- package/skills/Android Platform/Filesystem/SKILL.md +216 -0
- package/skills/Android Platform/Lifecycle/SKILL.md +233 -0
- package/skills/Android Platform/Manifest/SKILL.md +226 -0
- package/skills/Android Platform/Process Death Recovery/SKILL.md +214 -0
- package/skills/Android Platform/Resources/SKILL.md +234 -0
- package/skills/Android Platform/SavedStateHandle/SKILL.md +217 -0
- package/skills/Android Platform/State Restoration/SKILL.md +210 -0
- package/skills/Architecture/Bounded Context/SKILL.md +207 -0
- package/skills/Architecture/Clean Architecture/SKILL.md +229 -0
- package/skills/Architecture/Domain Modeling/SKILL.md +236 -0
- package/skills/Architecture/Entity Design/SKILL.md +243 -0
- package/skills/Architecture/Feature Isolation/SKILL.md +216 -0
- package/skills/Architecture/MVI/SKILL.md +224 -0
- package/skills/Architecture/MVVM/SKILL.md +198 -0
- package/skills/Architecture/Modularization/SKILL.md +194 -0
- package/skills/Architecture/Offline First/SKILL.md +249 -0
- package/skills/Architecture/Repository Pattern/SKILL.md +216 -0
- package/skills/Architecture/Side Effect Management/SKILL.md +278 -0
- package/skills/Architecture/State Management/SKILL.md +229 -0
- package/skills/Architecture/Unidirectional Data Flow/SKILL.md +196 -0
- package/skills/Architecture/Use Case Design/SKILL.md +244 -0
- package/skills/Architecture/Value Object/SKILL.md +226 -0
- package/skills/Build Infrastructure/Build Orchestration/SKILL.md +257 -0
- package/skills/Build Infrastructure/Dependency Compatibility Resolver/SKILL.md +259 -0
- package/skills/Build Infrastructure/Environment Validator/SKILL.md +311 -0
- package/skills/Build System/Build Cache/SKILL.md +233 -0
- package/skills/Build System/Build Flavor Strategy/SKILL.md +171 -0
- package/skills/Build System/Build Variant/SKILL.md +215 -0
- package/skills/Build System/Convention Plugin/SKILL.md +288 -0
- package/skills/Build System/Dependency Management/SKILL.md +261 -0
- package/skills/Build System/Gradle/SKILL.md +284 -0
- package/skills/Build System/Incremental Build/SKILL.md +199 -0
- package/skills/Build System/KAPT/SKILL.md +198 -0
- package/skills/Build System/KSP/SKILL.md +263 -0
- package/skills/Build System/Module Dependency Graph Validation/SKILL.md +223 -0
- package/skills/Build System/Specialized/C++/SKILL.md +308 -0
- package/skills/Build System/Specialized/JNI/SKILL.md +306 -0
- package/skills/Build System/Specialized/NDK/SKILL.md +264 -0
- package/skills/Build System/Version Catalog/SKILL.md +304 -0
- package/skills/Concurrency/Background Processing/SKILL.md +185 -0
- package/skills/Concurrency/Channel/SKILL.md +207 -0
- package/skills/Concurrency/Coroutine/SKILL.md +200 -0
- package/skills/Concurrency/Flow/SKILL.md +179 -0
- package/skills/Concurrency/Mutex Strategy/SKILL.md +185 -0
- package/skills/Concurrency/SharedFlow/SKILL.md +171 -0
- package/skills/Concurrency/StateFlow/SKILL.md +175 -0
- package/skills/Concurrency/Structured Concurrency/SKILL.md +197 -0
- package/skills/Concurrency/Synchronization Policy/SKILL.md +192 -0
- package/skills/Core Language/Annotation Processing/SKILL.md +224 -0
- package/skills/Core Language/DSL/SKILL.md +186 -0
- package/skills/Core Language/Extension Functions Design/SKILL.md +191 -0
- package/skills/Core Language/Immutability/SKILL.md +156 -0
- package/skills/Core Language/KMP/SKILL.md +182 -0
- package/skills/Core Language/Kotlin/SKILL.md +187 -0
- package/skills/Core Language/Reactive State Management/SKILL.md +228 -0
- package/skills/Core Language/Reactive Streams/SKILL.md +235 -0
- package/skills/Core Language/Serialization/SKILL.md +191 -0
- package/skills/Data Layer/Cache Strategy/SKILL.md +261 -0
- package/skills/Data Layer/Conflict Resolution/SKILL.md +248 -0
- package/skills/Data Layer/DAO/SKILL.md +225 -0
- package/skills/Data Layer/DTO Mapping/SKILL.md +269 -0
- package/skills/Data Layer/DataStore/SKILL.md +264 -0
- package/skills/Data Layer/Database Versioning Strategy/SKILL.md +215 -0
- package/skills/Data Layer/Encrypted Database/SKILL.md +212 -0
- package/skills/Data Layer/File Storage/SKILL.md +247 -0
- package/skills/Data Layer/Indexing/SKILL.md +184 -0
- package/skills/Data Layer/Key-Value Store Strategy/SKILL.md +185 -0
- package/skills/Data Layer/Merge Strategy/SKILL.md +240 -0
- package/skills/Data Layer/Migration/SKILL.md +243 -0
- package/skills/Data Layer/Paging/SKILL.md +264 -0
- package/skills/Data Layer/Proto DataStore/SKILL.md +250 -0
- package/skills/Data Layer/Room/SKILL.md +244 -0
- package/skills/Data Layer/SQLite/SKILL.md +255 -0
- package/skills/Data Layer/Sync Engine/SKILL.md +268 -0
- package/skills/Dependency Injection/Dagger/SKILL.md +283 -0
- package/skills/Dependency Injection/Hilt/SKILL.md +345 -0
- package/skills/Dependency Injection/Koin/SKILL.md +282 -0
- package/skills/Developer Experience/Detekt/SKILL.md +272 -0
- package/skills/Developer Experience/Lint Rule/SKILL.md +281 -0
- package/skills/Google Ecosystem/Analytics/SKILL.md +281 -0
- package/skills/Google Ecosystem/Crashlytics/SKILL.md +234 -0
- package/skills/Google Ecosystem/Firebase/SKILL.md +200 -0
- package/skills/Google Ecosystem/Firebase Messaging/SKILL.md +266 -0
- package/skills/Media/Audio/SKILL.md +257 -0
- package/skills/Media/Camera/SKILL.md +229 -0
- package/skills/Media/CameraX/SKILL.md +295 -0
- package/skills/Media/ExoPlayer/SKILL.md +258 -0
- package/skills/Media/Video/SKILL.md +228 -0
- package/skills/Meta Skills/Domain Error Model/SKILL.md +238 -0
- package/skills/Meta Skills/Error Handling/SKILL.md +255 -0
- package/skills/Meta Skills/Error Mapping/SKILL.md +232 -0
- package/skills/Meta Skills/Failure Strategy/SKILL.md +294 -0
- package/skills/Meta Skills/Migration Strategy/SKILL.md +305 -0
- package/skills/Meta Skills/User Friendly Errors/SKILL.md +334 -0
- package/skills/Navigation/Deep Navigation/SKILL.md +209 -0
- package/skills/Navigation/Navigation/SKILL.md +215 -0
- package/skills/Navigation/Nested Navigation/SKILL.md +214 -0
- package/skills/Networking/API Contract/SKILL.md +220 -0
- package/skills/Networking/Authentication/SKILL.md +210 -0
- package/skills/Networking/Certificate Pinning/SKILL.md +167 -0
- package/skills/Networking/Fallback Strategy/SKILL.md +182 -0
- package/skills/Networking/Ktor/SKILL.md +219 -0
- package/skills/Networking/Multipart Upload/SKILL.md +213 -0
- package/skills/Networking/OkHttp/SKILL.md +193 -0
- package/skills/Networking/REST/SKILL.md +178 -0
- package/skills/Networking/Rate Limiting/SKILL.md +170 -0
- package/skills/Networking/Retrofit/SKILL.md +241 -0
- package/skills/Networking/Retry-Backoff/SKILL.md +181 -0
- package/skills/Networking/Server-Sent Events (SSE)/SKILL.md +196 -0
- package/skills/Networking/WebSocket/SKILL.md +224 -0
- package/skills/Observability/Crash Reporting/SKILL.md +219 -0
- package/skills/Observability/Logging/SKILL.md +168 -0
- package/skills/Observability/Metrics/SKILL.md +227 -0
- package/skills/Observability/Structured Logging/SKILL.md +234 -0
- package/skills/Performance/ANR Prevention/SKILL.md +192 -0
- package/skills/Performance/Allocation Optimization/SKILL.md +179 -0
- package/skills/Performance/App Startup/SKILL.md +183 -0
- package/skills/Performance/Baseline Profile/SKILL.md +205 -0
- package/skills/Performance/Battery Optimization/SKILL.md +192 -0
- package/skills/Performance/Benchmark/SKILL.md +182 -0
- package/skills/Performance/Bitmap Optimization/SKILL.md +178 -0
- package/skills/Performance/Compose Optimization/SKILL.md +187 -0
- package/skills/Performance/Heap Management/SKILL.md +184 -0
- package/skills/Performance/Macrobenchmark/SKILL.md +214 -0
- package/skills/Performance/Memory Leak Prevention/SKILL.md +218 -0
- package/skills/Performance/Rendering Performance/SKILL.md +205 -0
- package/skills/Performance/Startup Optimization/SKILL.md +219 -0
- package/skills/Security/Biometric/SKILL.md +224 -0
- package/skills/Security/Certificate Transparency/SKILL.md +158 -0
- package/skills/Security/Cryptography/SKILL.md +244 -0
- package/skills/Security/Encrypted Storage/SKILL.md +273 -0
- package/skills/Security/Frida Detection/SKILL.md +230 -0
- package/skills/Security/Hook Detection/SKILL.md +197 -0
- package/skills/Security/Keystore/SKILL.md +272 -0
- package/skills/Security/Network Security Config/SKILL.md +186 -0
- package/skills/Security/Obfuscation/SKILL.md +226 -0
- package/skills/Security/Proguard/SKILL.md +202 -0
- package/skills/Security/R8/SKILL.md +234 -0
- package/skills/Security/Reverse Engineering Resistance/SKILL.md +267 -0
- package/skills/Security/Root Detection/SKILL.md +220 -0
- package/skills/Security/Secure Networking/SKILL.md +220 -0
- package/skills/System Integration/AlarmManager/SKILL.md +182 -0
- package/skills/System Integration/App Widget/SKILL.md +182 -0
- package/skills/System Integration/Deep Link/SKILL.md +187 -0
- package/skills/System Integration/Foreground Service/SKILL.md +212 -0
- package/skills/System Integration/Notification/SKILL.md +237 -0
- package/skills/System Integration/WorkManager/SKILL.md +256 -0
- package/skills/System Integration/clipboard/SKILL.md +155 -0
- package/skills/System Integration/share-intent/SKILL.md +182 -0
- package/skills/Testing/Compose Testing/SKILL.md +296 -0
- package/skills/Testing/Espresso/SKILL.md +292 -0
- package/skills/Testing/Fake Data/SKILL.md +245 -0
- package/skills/Testing/Integration Testing/SKILL.md +288 -0
- package/skills/Testing/Mocking/SKILL.md +229 -0
- package/skills/Testing/Snapshot Testing/SKILL.md +259 -0
- package/skills/Testing/UI Testing/SKILL.md +293 -0
- package/skills/Testing/Unit Testing/SKILL.md +309 -0
- package/skills/UI System/Bottom Sheet Patterns/SKILL.md +279 -0
- package/skills/UI System/Compose/SKILL.md +296 -0
- package/skills/UI System/Compose Animation/SKILL.md +281 -0
- package/skills/UI System/Compose Multiplatform/SKILL.md +261 -0
- package/skills/UI System/Compose Navigation/SKILL.md +255 -0
- package/skills/UI System/Compose Performance/SKILL.md +274 -0
- package/skills/UI System/Design System/SKILL.md +217 -0
- package/skills/UI System/Empty State Strategy/SKILL.md +208 -0
- package/skills/UI System/Keyboard Navigation/SKILL.md +214 -0
- package/skills/UI System/Loading Strategy/SKILL.md +254 -0
- package/skills/UI System/Material 3/SKILL.md +279 -0
- package/skills/UI System/RTL/SKILL.md +179 -0
- package/src/index.ts +182 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: build-orchestration
|
|
3
|
+
description: >
|
|
4
|
+
Build orchestration for Android multi-module projects — task ordering,
|
|
5
|
+
parallel builds, and coordinating complex build pipelines.
|
|
6
|
+
Load this skill when optimizing multi-module build order, configuring
|
|
7
|
+
parallel execution, or designing the build pipeline for CI/CD.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Build Orchestration
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
Build orchestration is the coordination of Gradle tasks across modules — ensuring they run in the right order, in parallel where possible, and with the right inputs/outputs declared. In multi-module projects, a poorly orchestrated build is the single biggest source of wasted build time.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Core Principles
|
|
18
|
+
|
|
19
|
+
- Gradle determines task order from **dependency declarations** — not manual ordering
|
|
20
|
+
- Tasks that don't depend on each other run **in parallel** when `org.gradle.parallel=true`
|
|
21
|
+
- The **critical path** is the longest chain of dependent tasks — optimize it first
|
|
22
|
+
- Declare task **inputs and outputs** correctly — enables parallelism and caching
|
|
23
|
+
- Module **dependency graph shape** determines maximum parallelism
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Parallel Build Configuration
|
|
28
|
+
|
|
29
|
+
```properties
|
|
30
|
+
# gradle.properties
|
|
31
|
+
org.gradle.parallel=true # ✅ enable parallel task execution
|
|
32
|
+
org.gradle.workers.max=8 # max parallel workers (default = CPU cores)
|
|
33
|
+
org.gradle.caching=true # tasks restored from cache run "instantly"
|
|
34
|
+
org.gradle.configuration-cache=true
|
|
35
|
+
org.gradle.jvmargs=-Xmx6g -XX:+UseParallelGC
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Module Dependency Graph and Parallelism
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
# Wide graph = more parallelism
|
|
44
|
+
:app
|
|
45
|
+
├── :feature:home ← builds in parallel
|
|
46
|
+
├── :feature:auth ← builds in parallel
|
|
47
|
+
├── :feature:profile ← builds in parallel
|
|
48
|
+
└── :core:network ← shared, built once
|
|
49
|
+
|
|
50
|
+
# Deep/narrow graph = sequential, slower
|
|
51
|
+
:app → :feature:home → :core:ui → :core:common
|
|
52
|
+
# Each must wait for the previous — no parallelism
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```kotlin
|
|
56
|
+
// ✅ Avoid deep chains — prefer wide, shallow dependency graphs
|
|
57
|
+
// feature modules should only depend on :core:*, not on each other
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Task Dependencies
|
|
63
|
+
|
|
64
|
+
```kotlin
|
|
65
|
+
// ✅ Explicit task ordering when needed
|
|
66
|
+
tasks.named("generateBuildConfig") {
|
|
67
|
+
mustRunAfter("clean")
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// ✅ Finalizer task — runs after another regardless of success/failure
|
|
71
|
+
tasks.named("assembleRelease") {
|
|
72
|
+
finalizedBy("uploadToStore")
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ✅ Lifecycle task — aggregate multiple tasks
|
|
76
|
+
tasks.register("buildAll") {
|
|
77
|
+
group = "build"
|
|
78
|
+
description = "Build all variants"
|
|
79
|
+
dependsOn(
|
|
80
|
+
":app:assembleDebug",
|
|
81
|
+
":app:assembleRelease",
|
|
82
|
+
":app:bundleRelease"
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Build Lifecycle Hooks
|
|
90
|
+
|
|
91
|
+
```kotlin
|
|
92
|
+
// ✅ Run a task before every build
|
|
93
|
+
tasks.named("preBuild") {
|
|
94
|
+
dependsOn("validateModuleDependencies")
|
|
95
|
+
dependsOn("assertModuleGraph")
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ✅ Run code quality checks as part of build
|
|
99
|
+
tasks.named("check") {
|
|
100
|
+
dependsOn("detekt")
|
|
101
|
+
dependsOn("ktlintCheck")
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ✅ Hook into assemble
|
|
105
|
+
tasks.configureEach {
|
|
106
|
+
if (name == "assembleRelease") {
|
|
107
|
+
doFirst {
|
|
108
|
+
println("Starting release build: ${project.version}")
|
|
109
|
+
}
|
|
110
|
+
doLast {
|
|
111
|
+
println("Release build complete")
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Multi-Module Build Order
|
|
120
|
+
|
|
121
|
+
```kotlin
|
|
122
|
+
// ✅ Gradle determines order automatically from module dependencies
|
|
123
|
+
// :core:common compiles first (no deps)
|
|
124
|
+
// :core:network compiles after :core:common
|
|
125
|
+
// :feature:home compiles after :core:network
|
|
126
|
+
// :app compiles last (depends on all features)
|
|
127
|
+
|
|
128
|
+
// ✅ Verify build order with
|
|
129
|
+
// ./gradlew :app:assembleDebug --dry-run
|
|
130
|
+
// Shows tasks in order without executing
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Composite Builds
|
|
136
|
+
|
|
137
|
+
```kotlin
|
|
138
|
+
// ✅ Include build-logic as a composite build
|
|
139
|
+
// settings.gradle.kts
|
|
140
|
+
pluginManagement {
|
|
141
|
+
includeBuild("build-logic")
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// ✅ Multiple composite builds
|
|
145
|
+
pluginManagement {
|
|
146
|
+
includeBuild("build-logic")
|
|
147
|
+
includeBuild("shared-conventions")
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Benefits:
|
|
151
|
+
// - build-logic plugins are compiled separately
|
|
152
|
+
// - Changes to build-logic don't invalidate app module caches
|
|
153
|
+
// - Build-logic can be shared across projects
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Build Scan Integration
|
|
159
|
+
|
|
160
|
+
```kotlin
|
|
161
|
+
// settings.gradle.kts
|
|
162
|
+
plugins {
|
|
163
|
+
id("com.gradle.develocity") version "3.18"
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
develocity {
|
|
167
|
+
buildScan {
|
|
168
|
+
termsOfUseUrl = "https://gradle.com/terms-of-service"
|
|
169
|
+
termsOfUseAgree = "yes"
|
|
170
|
+
publishing.onlyIf { System.getenv("CI") == "true" }
|
|
171
|
+
|
|
172
|
+
tag(if (System.getenv("CI") == "true") "CI" else "Local")
|
|
173
|
+
value("Git Branch", System.getenv("GITHUB_REF_NAME") ?: "local")
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## CI Build Matrix
|
|
181
|
+
|
|
182
|
+
```yaml
|
|
183
|
+
# .github/workflows/build.yml
|
|
184
|
+
jobs:
|
|
185
|
+
build:
|
|
186
|
+
strategy:
|
|
187
|
+
matrix:
|
|
188
|
+
task: [assembleDebug, test, lint, detekt]
|
|
189
|
+
runs-on: ubuntu-latest
|
|
190
|
+
steps:
|
|
191
|
+
- uses: actions/checkout@v4
|
|
192
|
+
- uses: gradle/actions/setup-gradle@v3
|
|
193
|
+
- name: Run ${{ matrix.task }}
|
|
194
|
+
run: ./gradlew ${{ matrix.task }}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Build Time Analysis
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
# ✅ Profile build
|
|
203
|
+
./gradlew assembleDebug --profile
|
|
204
|
+
# Open: build/reports/profile/profile-*.html
|
|
205
|
+
|
|
206
|
+
# ✅ Build scan (detailed — requires Gradle Enterprise or free plan)
|
|
207
|
+
./gradlew assembleDebug --scan
|
|
208
|
+
|
|
209
|
+
# ✅ Find the critical path
|
|
210
|
+
./gradlew assembleDebug --scan
|
|
211
|
+
# Build scan shows critical path in timeline view
|
|
212
|
+
|
|
213
|
+
# ✅ Identify slowest tasks
|
|
214
|
+
./gradlew assembleDebug --profile 2>&1 | grep "ms :" | sort -t' ' -k1 -rn | head -20
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Optimizing the Critical Path
|
|
220
|
+
|
|
221
|
+
```kotlin
|
|
222
|
+
// The critical path is typically:
|
|
223
|
+
// :app:compileDebugKotlin → :app:mergeDebugResources → :app:packageDebug
|
|
224
|
+
|
|
225
|
+
// ✅ Strategy 1: Move code out of :app into feature modules
|
|
226
|
+
// Less code in :app = faster :app:compileDebugKotlin
|
|
227
|
+
|
|
228
|
+
// ✅ Strategy 2: Use @JvmField and @JvmStatic where appropriate
|
|
229
|
+
// Reduces generated code size
|
|
230
|
+
|
|
231
|
+
// ✅ Strategy 3: Avoid annotation processing in :app
|
|
232
|
+
// Move annotated classes to feature/core modules
|
|
233
|
+
|
|
234
|
+
// ✅ Strategy 4: Use Baseline Profiles
|
|
235
|
+
// Reduces ART compilation burden at install time (not build time)
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Anti-Patterns
|
|
241
|
+
|
|
242
|
+
- All code in `:app` — no parallelism possible, everything sequential
|
|
243
|
+
- Feature modules depending on each other — forces sequential builds
|
|
244
|
+
- Missing `org.gradle.parallel=true` — single-threaded builds
|
|
245
|
+
- No build caching — every CI run starts from scratch
|
|
246
|
+
- Too many custom task hooks — interference with Gradle's optimization
|
|
247
|
+
- Running all checks in one sequential job in CI — parallelize with job matrix
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Related Skills
|
|
252
|
+
- `gradle` — Gradle build fundamentals
|
|
253
|
+
- `build-cache` — caching task outputs
|
|
254
|
+
- `incremental-build` — UP-TO-DATE checks
|
|
255
|
+
- `modularization` — module structure for build parallelism
|
|
256
|
+
- `module-dependency-graph-validation` — keeping the graph valid
|
|
257
|
+
- `environment-validator` — validating build environment before running
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dependency-compatibility-resolver
|
|
3
|
+
description: >
|
|
4
|
+
Detecting and resolving dependency version conflicts in Android/Gradle projects.
|
|
5
|
+
Load this skill when a dependency causes a version conflict, when builds fail
|
|
6
|
+
due to duplicate classes, or when upgrading a library causes transitive
|
|
7
|
+
dependency issues.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Dependency Compatibility Resolver
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
Dependency conflicts occur when multiple libraries require different versions of the same transitive dependency. Gradle resolves these automatically using its "highest version wins" strategy — but this can silently break things. This skill provides systematic techniques to detect, diagnose, and resolve conflicts correctly.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Core Principles
|
|
18
|
+
|
|
19
|
+
- **Understand the conflict first** — don't just force a version blindly
|
|
20
|
+
- "Highest version wins" is Gradle's default — it usually works but not always
|
|
21
|
+
- Conflicts between **major versions** are often breaking — require careful testing
|
|
22
|
+
- Use **BOM** to align library groups — Firebase, Compose, OkHttp suites
|
|
23
|
+
- Document **why** a version was forced — future maintainers need context
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Detecting Conflicts
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# ✅ View full dependency tree
|
|
31
|
+
./gradlew :app:dependencies --configuration debugRuntimeClasspath
|
|
32
|
+
|
|
33
|
+
# ✅ Find all versions of a specific dependency
|
|
34
|
+
./gradlew :app:dependencyInsight \
|
|
35
|
+
--configuration debugRuntimeClasspath \
|
|
36
|
+
--dependency okhttp
|
|
37
|
+
|
|
38
|
+
# ✅ Find duplicate classes (build error)
|
|
39
|
+
# Error: Duplicate class kotlin.collections.jdk8.CollectionsJDK8Kt found in modules
|
|
40
|
+
# → Two libraries bring different versions of kotlin-stdlib
|
|
41
|
+
|
|
42
|
+
# ✅ Check for version conflicts summary
|
|
43
|
+
./gradlew :app:dependencies --configuration debugRuntimeClasspath 2>&1 | grep " -> "
|
|
44
|
+
# Lines with " -> " show where Gradle picked a different version than requested
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Reading the Dependency Tree
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
# ✅ How to read dependency tree output
|
|
53
|
+
+--- com.squareup.retrofit2:retrofit:2.11.0
|
|
54
|
+
| +--- com.squareup.okhttp3:okhttp:4.12.0 (*) ← (*) = already shown
|
|
55
|
+
| \--- com.squareup.okio:okio:3.6.0
|
|
56
|
+
\--- com.squareup.okhttp3:logging-interceptor:4.12.0
|
|
57
|
+
\--- com.squareup.okhttp3:okhttp:4.12.0 (*)
|
|
58
|
+
|
|
59
|
+
# ✅ Version conflict shown as:
|
|
60
|
+
+--- com.example:library-a:1.0.0
|
|
61
|
+
| \--- com.squareup.okhttp3:okhttp:3.14.9 -> 4.12.0
|
|
62
|
+
# ^^^^^^^^^^
|
|
63
|
+
# Gradle upgraded from 3.x to 4.x
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Resolution Strategies
|
|
69
|
+
|
|
70
|
+
### Strategy 1: Force a Specific Version
|
|
71
|
+
|
|
72
|
+
```kotlin
|
|
73
|
+
// ✅ Use when you need to pin a transitive dependency
|
|
74
|
+
configurations.all {
|
|
75
|
+
resolutionStrategy {
|
|
76
|
+
force("com.squareup.okhttp3:okhttp:4.12.0")
|
|
77
|
+
force("org.jetbrains.kotlin:kotlin-stdlib:2.0.0")
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ✅ Document the reason
|
|
82
|
+
configurations.all {
|
|
83
|
+
resolutionStrategy.eachDependency {
|
|
84
|
+
if (requested.group == "com.squareup.okhttp3") {
|
|
85
|
+
useVersion("4.12.0")
|
|
86
|
+
because("Library X requires 3.x but we need 4.x features; verified compatible")
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Strategy 2: Exclude Transitive Dependency
|
|
93
|
+
|
|
94
|
+
```kotlin
|
|
95
|
+
// ✅ When a library brings an unwanted transitive dep
|
|
96
|
+
implementation(libs.some.library) {
|
|
97
|
+
exclude(group = "com.google.guava", module = "guava-jre")
|
|
98
|
+
// guava-jre conflicts with guava-android — exclude jre version
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ✅ Exclude globally across all configurations
|
|
102
|
+
configurations.all {
|
|
103
|
+
exclude(group = "commons-logging", module = "commons-logging")
|
|
104
|
+
// replaced by SLF4J — exclude old binding
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Strategy 3: Use BOM for Aligned Versions
|
|
109
|
+
|
|
110
|
+
```kotlin
|
|
111
|
+
// ✅ BOM ensures all modules in a suite use the same version
|
|
112
|
+
dependencies {
|
|
113
|
+
// OkHttp BOM
|
|
114
|
+
implementation(platform("com.squareup.okhttp3:okhttp-bom:4.12.0"))
|
|
115
|
+
implementation("com.squareup.okhttp3:okhttp")
|
|
116
|
+
implementation("com.squareup.okhttp3:logging-interceptor")
|
|
117
|
+
// Both use 4.12.0 — no conflict possible
|
|
118
|
+
|
|
119
|
+
// Firebase BOM
|
|
120
|
+
implementation(platform(libs.firebase.bom))
|
|
121
|
+
implementation(libs.firebase.analytics)
|
|
122
|
+
implementation(libs.firebase.crashlytics)
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Strategy 4: Substitute a Dependency
|
|
127
|
+
|
|
128
|
+
```kotlin
|
|
129
|
+
// ✅ Replace one dependency with another (e.g., different artifact for Android)
|
|
130
|
+
configurations.all {
|
|
131
|
+
resolutionStrategy.dependencySubstitution {
|
|
132
|
+
// Replace guava-jre with guava-android
|
|
133
|
+
substitute(module("com.google.guava:guava-jre"))
|
|
134
|
+
.using(module("com.google.guava:guava:32.1.3-android"))
|
|
135
|
+
.because("Android requires -android variant, not -jre")
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Common Conflict Scenarios
|
|
143
|
+
|
|
144
|
+
### Kotlin Stdlib Conflict
|
|
145
|
+
|
|
146
|
+
```kotlin
|
|
147
|
+
// Problem: Multiple kotlin-stdlib versions
|
|
148
|
+
// Solution: Force to match project Kotlin version
|
|
149
|
+
configurations.all {
|
|
150
|
+
resolutionStrategy.eachDependency {
|
|
151
|
+
if (requested.group == "org.jetbrains.kotlin" &&
|
|
152
|
+
requested.name.startsWith("kotlin-")) {
|
|
153
|
+
useVersion(libs.versions.kotlin.get())
|
|
154
|
+
because("Align all Kotlin modules to project Kotlin version")
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### OkHttp 3 vs 4 Conflict
|
|
161
|
+
|
|
162
|
+
```kotlin
|
|
163
|
+
// Problem: Library A needs OkHttp 3.x, app uses 4.x
|
|
164
|
+
// Solution: Force 4.x — OkHttp 4 is mostly backward compatible
|
|
165
|
+
configurations.all {
|
|
166
|
+
resolutionStrategy.force("com.squareup.okhttp3:okhttp:4.12.0")
|
|
167
|
+
}
|
|
168
|
+
// ✅ Test the library that needed 3.x still works
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Duplicate Class Error
|
|
172
|
+
|
|
173
|
+
```kotlin
|
|
174
|
+
// Error: Duplicate class kotlin.collections.jdk8.CollectionsJDK8Kt
|
|
175
|
+
// Cause: kotlin-stdlib-jdk8 merged into kotlin-stdlib in Kotlin 1.8+
|
|
176
|
+
// Solution: Exclude the separate artifact
|
|
177
|
+
|
|
178
|
+
configurations.all {
|
|
179
|
+
resolutionStrategy.eachDependency {
|
|
180
|
+
if (requested.group == "org.jetbrains.kotlin" &&
|
|
181
|
+
(requested.name == "kotlin-stdlib-jdk7" ||
|
|
182
|
+
requested.name == "kotlin-stdlib-jdk8")) {
|
|
183
|
+
useTarget("org.jetbrains.kotlin:kotlin-stdlib:${requested.version}")
|
|
184
|
+
because("kotlin-stdlib-jdk7/8 merged into kotlin-stdlib since 1.8")
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Guava JRE vs Android
|
|
191
|
+
|
|
192
|
+
```kotlin
|
|
193
|
+
// Problem: Some libraries bring guava-jre which has Java 8+ APIs not on Android
|
|
194
|
+
configurations.all {
|
|
195
|
+
resolutionStrategy.dependencySubstitution {
|
|
196
|
+
substitute(module("com.google.guava:guava"))
|
|
197
|
+
.using(module("com.google.guava:guava:32.1.3-android"))
|
|
198
|
+
.because("Android requires -android variant")
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Verification After Resolution
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
# ✅ Verify the resolved version is what you expect
|
|
209
|
+
./gradlew :app:dependencyInsight \
|
|
210
|
+
--dependency okhttp \
|
|
211
|
+
--configuration debugRuntimeClasspath
|
|
212
|
+
|
|
213
|
+
# ✅ Run tests to verify compatibility
|
|
214
|
+
./gradlew test
|
|
215
|
+
./gradlew connectedAndroidTest
|
|
216
|
+
|
|
217
|
+
# ✅ Check for duplicate classes
|
|
218
|
+
./gradlew assembleDebug 2>&1 | grep "Duplicate class"
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Documenting Resolutions
|
|
224
|
+
|
|
225
|
+
```kotlin
|
|
226
|
+
// ✅ Always explain why a version was forced
|
|
227
|
+
configurations.all {
|
|
228
|
+
resolutionStrategy.eachDependency {
|
|
229
|
+
when {
|
|
230
|
+
requested.group == "com.squareup.okhttp3" -> {
|
|
231
|
+
useVersion("4.12.0")
|
|
232
|
+
because(
|
|
233
|
+
"Library X still requests OkHttp 3.14 but is compatible with 4.x. " +
|
|
234
|
+
"Verified with X's test suite on 2024-11-15. " +
|
|
235
|
+
"Remove this override when X releases 2.0 with native OkHttp 4 support."
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Anti-Patterns
|
|
246
|
+
|
|
247
|
+
- Blindly forcing a version without testing — can break the library that needed the old version
|
|
248
|
+
- Not documenting resolution reasons — future maintainers don't know why it's forced
|
|
249
|
+
- Excluding a dep without verifying the library works without it — runtime crash
|
|
250
|
+
- Ignoring `-> x.y.z` in dependency tree — silent upgrades can break things
|
|
251
|
+
- Forcing an older version when Gradle upgraded for good reason — misses security fixes
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Related Skills
|
|
256
|
+
- `dependency-management` — dependency configurations and upgrades
|
|
257
|
+
- `version-catalog` — centralized version management
|
|
258
|
+
- `gradle` — Gradle build configuration
|
|
259
|
+
- `build-cache` — cache invalidation after dependency changes
|