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.
Files changed (176) hide show
  1. package/dist/index.js +143 -0
  2. package/package.json +27 -0
  3. package/skills/Android Ecosystem/Baseline Profile Generator/SKILL.md +277 -0
  4. package/skills/Android Ecosystem/Glance/SKILL.md +315 -0
  5. package/skills/Android Platform/Configuration/SKILL.md +201 -0
  6. package/skills/Android Platform/Filesystem/SKILL.md +216 -0
  7. package/skills/Android Platform/Lifecycle/SKILL.md +233 -0
  8. package/skills/Android Platform/Manifest/SKILL.md +226 -0
  9. package/skills/Android Platform/Process Death Recovery/SKILL.md +214 -0
  10. package/skills/Android Platform/Resources/SKILL.md +234 -0
  11. package/skills/Android Platform/SavedStateHandle/SKILL.md +217 -0
  12. package/skills/Android Platform/State Restoration/SKILL.md +210 -0
  13. package/skills/Architecture/Bounded Context/SKILL.md +207 -0
  14. package/skills/Architecture/Clean Architecture/SKILL.md +229 -0
  15. package/skills/Architecture/Domain Modeling/SKILL.md +236 -0
  16. package/skills/Architecture/Entity Design/SKILL.md +243 -0
  17. package/skills/Architecture/Feature Isolation/SKILL.md +216 -0
  18. package/skills/Architecture/MVI/SKILL.md +224 -0
  19. package/skills/Architecture/MVVM/SKILL.md +198 -0
  20. package/skills/Architecture/Modularization/SKILL.md +194 -0
  21. package/skills/Architecture/Offline First/SKILL.md +249 -0
  22. package/skills/Architecture/Repository Pattern/SKILL.md +216 -0
  23. package/skills/Architecture/Side Effect Management/SKILL.md +278 -0
  24. package/skills/Architecture/State Management/SKILL.md +229 -0
  25. package/skills/Architecture/Unidirectional Data Flow/SKILL.md +196 -0
  26. package/skills/Architecture/Use Case Design/SKILL.md +244 -0
  27. package/skills/Architecture/Value Object/SKILL.md +226 -0
  28. package/skills/Build Infrastructure/Build Orchestration/SKILL.md +257 -0
  29. package/skills/Build Infrastructure/Dependency Compatibility Resolver/SKILL.md +259 -0
  30. package/skills/Build Infrastructure/Environment Validator/SKILL.md +311 -0
  31. package/skills/Build System/Build Cache/SKILL.md +233 -0
  32. package/skills/Build System/Build Flavor Strategy/SKILL.md +171 -0
  33. package/skills/Build System/Build Variant/SKILL.md +215 -0
  34. package/skills/Build System/Convention Plugin/SKILL.md +288 -0
  35. package/skills/Build System/Dependency Management/SKILL.md +261 -0
  36. package/skills/Build System/Gradle/SKILL.md +284 -0
  37. package/skills/Build System/Incremental Build/SKILL.md +199 -0
  38. package/skills/Build System/KAPT/SKILL.md +198 -0
  39. package/skills/Build System/KSP/SKILL.md +263 -0
  40. package/skills/Build System/Module Dependency Graph Validation/SKILL.md +223 -0
  41. package/skills/Build System/Specialized/C++/SKILL.md +308 -0
  42. package/skills/Build System/Specialized/JNI/SKILL.md +306 -0
  43. package/skills/Build System/Specialized/NDK/SKILL.md +264 -0
  44. package/skills/Build System/Version Catalog/SKILL.md +304 -0
  45. package/skills/Concurrency/Background Processing/SKILL.md +185 -0
  46. package/skills/Concurrency/Channel/SKILL.md +207 -0
  47. package/skills/Concurrency/Coroutine/SKILL.md +200 -0
  48. package/skills/Concurrency/Flow/SKILL.md +179 -0
  49. package/skills/Concurrency/Mutex Strategy/SKILL.md +185 -0
  50. package/skills/Concurrency/SharedFlow/SKILL.md +171 -0
  51. package/skills/Concurrency/StateFlow/SKILL.md +175 -0
  52. package/skills/Concurrency/Structured Concurrency/SKILL.md +197 -0
  53. package/skills/Concurrency/Synchronization Policy/SKILL.md +192 -0
  54. package/skills/Core Language/Annotation Processing/SKILL.md +224 -0
  55. package/skills/Core Language/DSL/SKILL.md +186 -0
  56. package/skills/Core Language/Extension Functions Design/SKILL.md +191 -0
  57. package/skills/Core Language/Immutability/SKILL.md +156 -0
  58. package/skills/Core Language/KMP/SKILL.md +182 -0
  59. package/skills/Core Language/Kotlin/SKILL.md +187 -0
  60. package/skills/Core Language/Reactive State Management/SKILL.md +228 -0
  61. package/skills/Core Language/Reactive Streams/SKILL.md +235 -0
  62. package/skills/Core Language/Serialization/SKILL.md +191 -0
  63. package/skills/Data Layer/Cache Strategy/SKILL.md +261 -0
  64. package/skills/Data Layer/Conflict Resolution/SKILL.md +248 -0
  65. package/skills/Data Layer/DAO/SKILL.md +225 -0
  66. package/skills/Data Layer/DTO Mapping/SKILL.md +269 -0
  67. package/skills/Data Layer/DataStore/SKILL.md +264 -0
  68. package/skills/Data Layer/Database Versioning Strategy/SKILL.md +215 -0
  69. package/skills/Data Layer/Encrypted Database/SKILL.md +212 -0
  70. package/skills/Data Layer/File Storage/SKILL.md +247 -0
  71. package/skills/Data Layer/Indexing/SKILL.md +184 -0
  72. package/skills/Data Layer/Key-Value Store Strategy/SKILL.md +185 -0
  73. package/skills/Data Layer/Merge Strategy/SKILL.md +240 -0
  74. package/skills/Data Layer/Migration/SKILL.md +243 -0
  75. package/skills/Data Layer/Paging/SKILL.md +264 -0
  76. package/skills/Data Layer/Proto DataStore/SKILL.md +250 -0
  77. package/skills/Data Layer/Room/SKILL.md +244 -0
  78. package/skills/Data Layer/SQLite/SKILL.md +255 -0
  79. package/skills/Data Layer/Sync Engine/SKILL.md +268 -0
  80. package/skills/Dependency Injection/Dagger/SKILL.md +283 -0
  81. package/skills/Dependency Injection/Hilt/SKILL.md +345 -0
  82. package/skills/Dependency Injection/Koin/SKILL.md +282 -0
  83. package/skills/Developer Experience/Detekt/SKILL.md +272 -0
  84. package/skills/Developer Experience/Lint Rule/SKILL.md +281 -0
  85. package/skills/Google Ecosystem/Analytics/SKILL.md +281 -0
  86. package/skills/Google Ecosystem/Crashlytics/SKILL.md +234 -0
  87. package/skills/Google Ecosystem/Firebase/SKILL.md +200 -0
  88. package/skills/Google Ecosystem/Firebase Messaging/SKILL.md +266 -0
  89. package/skills/Media/Audio/SKILL.md +257 -0
  90. package/skills/Media/Camera/SKILL.md +229 -0
  91. package/skills/Media/CameraX/SKILL.md +295 -0
  92. package/skills/Media/ExoPlayer/SKILL.md +258 -0
  93. package/skills/Media/Video/SKILL.md +228 -0
  94. package/skills/Meta Skills/Domain Error Model/SKILL.md +238 -0
  95. package/skills/Meta Skills/Error Handling/SKILL.md +255 -0
  96. package/skills/Meta Skills/Error Mapping/SKILL.md +232 -0
  97. package/skills/Meta Skills/Failure Strategy/SKILL.md +294 -0
  98. package/skills/Meta Skills/Migration Strategy/SKILL.md +305 -0
  99. package/skills/Meta Skills/User Friendly Errors/SKILL.md +334 -0
  100. package/skills/Navigation/Deep Navigation/SKILL.md +209 -0
  101. package/skills/Navigation/Navigation/SKILL.md +215 -0
  102. package/skills/Navigation/Nested Navigation/SKILL.md +214 -0
  103. package/skills/Networking/API Contract/SKILL.md +220 -0
  104. package/skills/Networking/Authentication/SKILL.md +210 -0
  105. package/skills/Networking/Certificate Pinning/SKILL.md +167 -0
  106. package/skills/Networking/Fallback Strategy/SKILL.md +182 -0
  107. package/skills/Networking/Ktor/SKILL.md +219 -0
  108. package/skills/Networking/Multipart Upload/SKILL.md +213 -0
  109. package/skills/Networking/OkHttp/SKILL.md +193 -0
  110. package/skills/Networking/REST/SKILL.md +178 -0
  111. package/skills/Networking/Rate Limiting/SKILL.md +170 -0
  112. package/skills/Networking/Retrofit/SKILL.md +241 -0
  113. package/skills/Networking/Retry-Backoff/SKILL.md +181 -0
  114. package/skills/Networking/Server-Sent Events (SSE)/SKILL.md +196 -0
  115. package/skills/Networking/WebSocket/SKILL.md +224 -0
  116. package/skills/Observability/Crash Reporting/SKILL.md +219 -0
  117. package/skills/Observability/Logging/SKILL.md +168 -0
  118. package/skills/Observability/Metrics/SKILL.md +227 -0
  119. package/skills/Observability/Structured Logging/SKILL.md +234 -0
  120. package/skills/Performance/ANR Prevention/SKILL.md +192 -0
  121. package/skills/Performance/Allocation Optimization/SKILL.md +179 -0
  122. package/skills/Performance/App Startup/SKILL.md +183 -0
  123. package/skills/Performance/Baseline Profile/SKILL.md +205 -0
  124. package/skills/Performance/Battery Optimization/SKILL.md +192 -0
  125. package/skills/Performance/Benchmark/SKILL.md +182 -0
  126. package/skills/Performance/Bitmap Optimization/SKILL.md +178 -0
  127. package/skills/Performance/Compose Optimization/SKILL.md +187 -0
  128. package/skills/Performance/Heap Management/SKILL.md +184 -0
  129. package/skills/Performance/Macrobenchmark/SKILL.md +214 -0
  130. package/skills/Performance/Memory Leak Prevention/SKILL.md +218 -0
  131. package/skills/Performance/Rendering Performance/SKILL.md +205 -0
  132. package/skills/Performance/Startup Optimization/SKILL.md +219 -0
  133. package/skills/Security/Biometric/SKILL.md +224 -0
  134. package/skills/Security/Certificate Transparency/SKILL.md +158 -0
  135. package/skills/Security/Cryptography/SKILL.md +244 -0
  136. package/skills/Security/Encrypted Storage/SKILL.md +273 -0
  137. package/skills/Security/Frida Detection/SKILL.md +230 -0
  138. package/skills/Security/Hook Detection/SKILL.md +197 -0
  139. package/skills/Security/Keystore/SKILL.md +272 -0
  140. package/skills/Security/Network Security Config/SKILL.md +186 -0
  141. package/skills/Security/Obfuscation/SKILL.md +226 -0
  142. package/skills/Security/Proguard/SKILL.md +202 -0
  143. package/skills/Security/R8/SKILL.md +234 -0
  144. package/skills/Security/Reverse Engineering Resistance/SKILL.md +267 -0
  145. package/skills/Security/Root Detection/SKILL.md +220 -0
  146. package/skills/Security/Secure Networking/SKILL.md +220 -0
  147. package/skills/System Integration/AlarmManager/SKILL.md +182 -0
  148. package/skills/System Integration/App Widget/SKILL.md +182 -0
  149. package/skills/System Integration/Deep Link/SKILL.md +187 -0
  150. package/skills/System Integration/Foreground Service/SKILL.md +212 -0
  151. package/skills/System Integration/Notification/SKILL.md +237 -0
  152. package/skills/System Integration/WorkManager/SKILL.md +256 -0
  153. package/skills/System Integration/clipboard/SKILL.md +155 -0
  154. package/skills/System Integration/share-intent/SKILL.md +182 -0
  155. package/skills/Testing/Compose Testing/SKILL.md +296 -0
  156. package/skills/Testing/Espresso/SKILL.md +292 -0
  157. package/skills/Testing/Fake Data/SKILL.md +245 -0
  158. package/skills/Testing/Integration Testing/SKILL.md +288 -0
  159. package/skills/Testing/Mocking/SKILL.md +229 -0
  160. package/skills/Testing/Snapshot Testing/SKILL.md +259 -0
  161. package/skills/Testing/UI Testing/SKILL.md +293 -0
  162. package/skills/Testing/Unit Testing/SKILL.md +309 -0
  163. package/skills/UI System/Bottom Sheet Patterns/SKILL.md +279 -0
  164. package/skills/UI System/Compose/SKILL.md +296 -0
  165. package/skills/UI System/Compose Animation/SKILL.md +281 -0
  166. package/skills/UI System/Compose Multiplatform/SKILL.md +261 -0
  167. package/skills/UI System/Compose Navigation/SKILL.md +255 -0
  168. package/skills/UI System/Compose Performance/SKILL.md +274 -0
  169. package/skills/UI System/Design System/SKILL.md +217 -0
  170. package/skills/UI System/Empty State Strategy/SKILL.md +208 -0
  171. package/skills/UI System/Keyboard Navigation/SKILL.md +214 -0
  172. package/skills/UI System/Loading Strategy/SKILL.md +254 -0
  173. package/skills/UI System/Material 3/SKILL.md +279 -0
  174. package/skills/UI System/RTL/SKILL.md +179 -0
  175. package/src/index.ts +182 -0
  176. package/tsconfig.json +19 -0
@@ -0,0 +1,311 @@
1
+ ---
2
+ name: environment-validator
3
+ description: >
4
+ Validating the build environment before running Android builds.
5
+ Load this skill when ensuring required tools are installed, verifying
6
+ SDK versions, checking environment variables, or creating pre-build
7
+ validation tasks that fail fast with clear error messages.
8
+ ---
9
+
10
+ # Environment Validator
11
+
12
+ ## Overview
13
+ Environment validation ensures the build environment has all required tools, SDKs, and configuration before the build starts. Without validation, builds fail with cryptic errors mid-way through. A good validator fails fast with clear, actionable messages.
14
+
15
+ ---
16
+
17
+ ## Core Principles
18
+
19
+ - **Fail fast** — validate before any build work begins
20
+ - Provide **clear, actionable error messages** — tell the developer exactly what to fix
21
+ - Validate in `settings.gradle.kts` or a `preBuild` task — earliest possible point
22
+ - Check **required tools** (Java, Android SDK, NDK if needed) and **environment variables**
23
+ - Validation must be **fast** — it runs on every build
24
+
25
+ ---
26
+
27
+ ## Gradle Wrapper Version Validation
28
+
29
+ ```kotlin
30
+ // settings.gradle.kts
31
+ // ✅ Validate Gradle wrapper version
32
+ val minGradleVersion = "8.7"
33
+ val currentVersion = gradle.gradleVersion
34
+
35
+ if (GradleVersion.version(currentVersion) < GradleVersion.version(minGradleVersion)) {
36
+ throw GradleException(
37
+ """
38
+ ❌ Gradle $minGradleVersion or higher is required.
39
+ Current version: $currentVersion
40
+
41
+ Fix: Run ./gradlew wrapper --gradle-version=$minGradleVersion
42
+ """.trimIndent()
43
+ )
44
+ }
45
+ ```
46
+
47
+ ---
48
+
49
+ ## Java Version Validation
50
+
51
+ ```kotlin
52
+ // settings.gradle.kts or root build.gradle.kts
53
+ // ✅ Validate Java version
54
+ val minJavaVersion = JavaVersion.VERSION_17
55
+ val currentJavaVersion = JavaVersion.current()
56
+
57
+ if (currentJavaVersion < minJavaVersion) {
58
+ throw GradleException(
59
+ """
60
+ ❌ Java $minJavaVersion or higher is required.
61
+ Current version: $currentJavaVersion
62
+
63
+ Fix: Install JDK 17+ and set JAVA_HOME:
64
+ export JAVA_HOME=${'$'}(/usr/libexec/java_home -v 17)
65
+ """.trimIndent()
66
+ )
67
+ }
68
+ ```
69
+
70
+ ---
71
+
72
+ ## Android SDK Validation
73
+
74
+ ```kotlin
75
+ // root build.gradle.kts
76
+ // ✅ Validate Android SDK is installed
77
+ subprojects {
78
+ afterEvaluate {
79
+ val androidExtension = extensions.findByName("android") ?: return@afterEvaluate
80
+ tasks.register("validateAndroidSdk") {
81
+ group = "verification"
82
+ doLast {
83
+ val sdkDir = System.getenv("ANDROID_HOME")
84
+ ?: System.getenv("ANDROID_SDK_ROOT")
85
+ ?: "${System.getProperty("user.home")}/Library/Android/sdk"
86
+
87
+ if (!File(sdkDir).exists()) {
88
+ throw GradleException(
89
+ """
90
+ ❌ Android SDK not found at: $sdkDir
91
+
92
+ Fix: Install Android Studio or set ANDROID_HOME:
93
+ export ANDROID_HOME=~/Library/Android/sdk
94
+ """.trimIndent()
95
+ )
96
+ }
97
+
98
+ val compileSdkVersion = 35
99
+ val platformDir = File(sdkDir, "platforms/android-$compileSdkVersion")
100
+ if (!platformDir.exists()) {
101
+ throw GradleException(
102
+ """
103
+ ❌ Android SDK platform $compileSdkVersion not installed.
104
+
105
+ Fix: Open Android Studio → SDK Manager → Install Android $compileSdkVersion
106
+ Or run: sdkmanager "platforms;android-$compileSdkVersion"
107
+ """.trimIndent()
108
+ )
109
+ }
110
+ }
111
+ }
112
+
113
+ tasks.named("preBuild") {
114
+ dependsOn("validateAndroidSdk")
115
+ }
116
+ }
117
+ }
118
+ ```
119
+
120
+ ---
121
+
122
+ ## Environment Variables Validation
123
+
124
+ ```kotlin
125
+ // build.gradle.kts (app)
126
+ // ✅ Validate required environment variables for release builds
127
+ tasks.register("validateReleaseEnvironment") {
128
+ group = "verification"
129
+ onlyIf { gradle.taskGraph.hasTask(":app:assembleRelease") }
130
+
131
+ doLast {
132
+ val required = mapOf(
133
+ "KEYSTORE_PATH" to "Path to the release keystore file",
134
+ "KEYSTORE_PASSWORD" to "Password for the keystore",
135
+ "KEY_ALIAS" to "Key alias in the keystore",
136
+ "KEY_PASSWORD" to "Password for the key"
137
+ )
138
+
139
+ val missing = required.filter { (key, _) ->
140
+ System.getenv(key).isNullOrBlank()
141
+ }
142
+
143
+ if (missing.isNotEmpty()) {
144
+ throw GradleException(
145
+ buildString {
146
+ appendLine("❌ Missing required environment variables for release build:")
147
+ missing.forEach { (key, description) ->
148
+ appendLine(" - $key: $description")
149
+ }
150
+ appendLine()
151
+ appendLine("Fix: Set these variables in your CI environment or local .env file.")
152
+ }
153
+ )
154
+ }
155
+ }
156
+ }
157
+
158
+ tasks.named("preBuild") {
159
+ dependsOn("validateReleaseEnvironment")
160
+ }
161
+ ```
162
+
163
+ ---
164
+
165
+ ## google-services.json Validation
166
+
167
+ ```kotlin
168
+ // app/build.gradle.kts
169
+ // ✅ Validate google-services.json exists before build
170
+ tasks.register("validateGoogleServices") {
171
+ group = "verification"
172
+ doLast {
173
+ val googleServicesFile = file("google-services.json")
174
+ if (!googleServicesFile.exists()) {
175
+ throw GradleException(
176
+ """
177
+ ❌ google-services.json not found at: ${googleServicesFile.absolutePath}
178
+
179
+ Fix:
180
+ 1. Go to Firebase Console → Project Settings → Your App
181
+ 2. Download google-services.json
182
+ 3. Place it in the app/ directory
183
+
184
+ Note: Never commit this file to public repositories.
185
+ """.trimIndent()
186
+ )
187
+ }
188
+ }
189
+ }
190
+
191
+ tasks.named("preBuild") {
192
+ dependsOn("validateGoogleServices")
193
+ }
194
+ ```
195
+
196
+ ---
197
+
198
+ ## Convention Plugin for Environment Validation
199
+
200
+ ```kotlin
201
+ // build-logic/convention/src/main/kotlin/EnvironmentValidationPlugin.kt
202
+ class EnvironmentValidationPlugin : Plugin<Project> {
203
+ override fun apply(target: Project) {
204
+ target.tasks.register("validateEnvironment") {
205
+ group = "verification"
206
+ description = "Validates build environment prerequisites"
207
+
208
+ doLast {
209
+ val errors = mutableListOf<String>()
210
+
211
+ // Java version
212
+ if (JavaVersion.current() < JavaVersion.VERSION_17) {
213
+ errors += "Java 17+ required (current: ${JavaVersion.current()})"
214
+ }
215
+
216
+ // Gradle version
217
+ if (GradleVersion.version(target.gradle.gradleVersion) <
218
+ GradleVersion.version("8.7")) {
219
+ errors += "Gradle 8.7+ required (current: ${target.gradle.gradleVersion})"
220
+ }
221
+
222
+ // ANDROID_HOME
223
+ val androidHome = System.getenv("ANDROID_HOME")
224
+ ?: System.getenv("ANDROID_SDK_ROOT")
225
+ if (androidHome.isNullOrBlank()) {
226
+ errors += "ANDROID_HOME environment variable not set"
227
+ }
228
+
229
+ if (errors.isNotEmpty()) {
230
+ throw GradleException(
231
+ buildString {
232
+ appendLine("❌ Build environment validation failed:")
233
+ errors.forEach { appendLine(" • $it") }
234
+ appendLine()
235
+ appendLine("Fix each issue above and try again.")
236
+ }
237
+ )
238
+ }
239
+
240
+ println("✅ Build environment validation passed")
241
+ }
242
+ }
243
+
244
+ target.tasks.configureEach {
245
+ if (name == "preBuild") {
246
+ dependsOn("validateEnvironment")
247
+ }
248
+ }
249
+ }
250
+ }
251
+ ```
252
+
253
+ ---
254
+
255
+ ## local.properties Validation
256
+
257
+ ```kotlin
258
+ // root build.gradle.kts
259
+ // ✅ Validate local.properties exists and has required keys
260
+ tasks.register("validateLocalProperties") {
261
+ group = "verification"
262
+ doLast {
263
+ val localProps = file("local.properties")
264
+ if (!localProps.exists()) {
265
+ throw GradleException(
266
+ """
267
+ ❌ local.properties not found.
268
+
269
+ Fix: Create local.properties in the project root with:
270
+ sdk.dir=/path/to/your/android/sdk
271
+
272
+ Android Studio creates this automatically — open the project in AS.
273
+ """.trimIndent()
274
+ )
275
+ }
276
+
277
+ val props = java.util.Properties().apply {
278
+ load(localProps.inputStream())
279
+ }
280
+
281
+ if (props.getProperty("sdk.dir").isNullOrBlank()) {
282
+ throw GradleException(
283
+ """
284
+ ❌ sdk.dir not set in local.properties.
285
+
286
+ Fix: Add to local.properties:
287
+ sdk.dir=/Users/yourname/Library/Android/sdk
288
+ """.trimIndent()
289
+ )
290
+ }
291
+ }
292
+ }
293
+ ```
294
+
295
+ ---
296
+
297
+ ## Anti-Patterns
298
+
299
+ - Validation that runs too late — after expensive tasks have already started
300
+ - Cryptic error messages — "SDK not found" without telling where it looked
301
+ - Validating everything on every build — slow, check only what's needed
302
+ - Not validating in CI — environment assumption mismatches cause mysterious failures
303
+ - Hardcoding paths in validation — use environment variables and standard locations
304
+
305
+ ---
306
+
307
+ ## Related Skills
308
+ - `build-orchestration` — task ordering and build pipeline
309
+ - `gradle` — Gradle task configuration
310
+ - `build-variant` — validating per-variant requirements
311
+ - `ci-cd` — environment setup in CI pipeline
@@ -0,0 +1,233 @@
1
+ ---
2
+ name: build-cache
3
+ description: >
4
+ Gradle build cache setup for local and remote caching in Android projects.
5
+ Load this skill when configuring build cache, speeding up CI builds,
6
+ sharing cached outputs across team members, or debugging cache misses.
7
+ ---
8
+
9
+ # Build Cache
10
+
11
+ ## Overview
12
+ Gradle Build Cache stores task outputs (compiled classes, resources, generated code) and reuses them when the same task runs again with identical inputs. Local cache helps individual developers; remote cache shares outputs across the whole team and CI — dramatically reducing build times.
13
+
14
+ ---
15
+
16
+ ## Core Principles
17
+
18
+ - Local cache is **always worth enabling** — zero configuration cost, significant speedup
19
+ - Remote cache requires a server — Gradle Enterprise, self-hosted, or GitHub Actions cache
20
+ - Cache keys are computed from task **inputs** — any input change = cache miss
21
+ - **Configuration cache** and **build cache** are complementary but different
22
+ - Never cache tasks with **non-deterministic outputs** — timestamps, random values
23
+
24
+ ---
25
+
26
+ ## Local Cache Setup
27
+
28
+ ```properties
29
+ # gradle.properties
30
+ org.gradle.caching=true # ✅ enable local build cache
31
+ org.gradle.parallel=true # parallel execution benefits from cache
32
+ ```
33
+
34
+ ```kotlin
35
+ // settings.gradle.kts — explicit local cache config (optional)
36
+ buildCache {
37
+ local {
38
+ isEnabled = true
39
+ directory = File(rootDir, ".gradle/build-cache")
40
+ removeUnusedEntriesAfterDays = 30
41
+ }
42
+ }
43
+ ```
44
+
45
+ ---
46
+
47
+ ## Remote Cache Setup
48
+
49
+ ### Gradle Enterprise / Develocity
50
+
51
+ ```kotlin
52
+ // settings.gradle.kts
53
+ plugins {
54
+ id("com.gradle.develocity") version "3.18"
55
+ }
56
+
57
+ develocity {
58
+ buildScan {
59
+ termsOfUseUrl = "https://gradle.com/terms-of-service"
60
+ termsOfUseAgree = "yes"
61
+ }
62
+ }
63
+
64
+ buildCache {
65
+ local { isEnabled = true }
66
+ remote<HttpBuildCache> {
67
+ url = uri("https://gradle-cache.example.com/cache/")
68
+ credentials {
69
+ username = System.getenv("GRADLE_CACHE_USERNAME")
70
+ password = System.getenv("GRADLE_CACHE_PASSWORD")
71
+ }
72
+ isPush = System.getenv("CI") == "true" // only CI pushes to remote
73
+ isEnabled = true
74
+ }
75
+ }
76
+ ```
77
+
78
+ ### GitHub Actions Cache (Free Alternative)
79
+
80
+ ```yaml
81
+ # .github/workflows/build.yml
82
+ - name: Setup Gradle
83
+ uses: gradle/actions/setup-gradle@v3
84
+ with:
85
+ cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
86
+ # Automatically caches ~/.gradle and build outputs
87
+ ```
88
+
89
+ ---
90
+
91
+ ## Verifying Cache Effectiveness
92
+
93
+ ```bash
94
+ # ✅ Run build twice — second should show FROM-CACHE
95
+ ./gradlew assembleDebug
96
+ ./gradlew clean
97
+ ./gradlew assembleDebug
98
+ # Expected: :app:compileDebugKotlin FROM-CACHE
99
+
100
+ # ✅ Check cache hit rate
101
+ ./gradlew assembleDebug --build-cache --info 2>&1 | grep "FROM-CACHE\|UP-TO-DATE\|EXECUTED"
102
+
103
+ # ✅ Build scan for detailed cache analysis
104
+ ./gradlew assembleDebug --scan
105
+ ```
106
+
107
+ ---
108
+
109
+ ## Cache Miss Debugging
110
+
111
+ ```bash
112
+ # ✅ Find why a task isn't cached
113
+ ./gradlew assembleDebug --info 2>&1 | grep -A5 "compileDebugKotlin"
114
+ # Look for: "Input property ... has changed"
115
+
116
+ # ✅ Task input fingerprint
117
+ ./gradlew assembleDebug --rerun-tasks # force all tasks to run
118
+ # Then compare with cached run inputs
119
+
120
+ # Common cache miss causes:
121
+ # - Absolute paths in task inputs
122
+ # - Timestamps in generated files
123
+ # - Environment variables not declared as inputs
124
+ # - Non-deterministic code generation
125
+ ```
126
+
127
+ ---
128
+
129
+ ## Making Custom Tasks Cacheable
130
+
131
+ ```kotlin
132
+ // ✅ Declare task as cacheable with proper input/output declarations
133
+ @CacheableTask
134
+ abstract class GenerateApiTask : DefaultTask() {
135
+
136
+ @get:InputFiles
137
+ @get:PathSensitive(PathSensitivity.RELATIVE) // ✅ relative paths = cache-portable
138
+ abstract val inputSpecs: ConfigurableFileCollection
139
+
140
+ @get:Input
141
+ abstract val apiVersion: Property<String>
142
+
143
+ @get:OutputDirectory
144
+ abstract val outputDir: DirectoryProperty
145
+
146
+ @TaskAction
147
+ fun generate() {
148
+ val output = outputDir.get().asFile
149
+ output.mkdirs()
150
+ inputSpecs.forEach { spec ->
151
+ // generate code from spec
152
+ }
153
+ }
154
+ }
155
+
156
+ // ✅ Register
157
+ tasks.register<GenerateApiTask>("generateApi") {
158
+ inputSpecs.from(fileTree("src/api/specs"))
159
+ apiVersion.set("v2")
160
+ outputDir.set(layout.buildDirectory.dir("generated/api"))
161
+ }
162
+ ```
163
+
164
+ ---
165
+
166
+ ## Path Sensitivity
167
+
168
+ ```kotlin
169
+ // ✅ Use PathSensitivity to make inputs cache-portable
170
+ @get:InputFiles
171
+ @get:PathSensitive(PathSensitivity.RELATIVE) // only relative path matters
172
+ abstract val sourceFiles: ConfigurableFileCollection
173
+
174
+ @get:InputFiles
175
+ @get:PathSensitive(PathSensitivity.NAME_ONLY) // only filename matters
176
+ abstract val resourceFiles: ConfigurableFileCollection
177
+
178
+ @get:InputFiles
179
+ @get:PathSensitive(PathSensitivity.NONE) // only content matters, not path
180
+ abstract val configFiles: ConfigurableFileCollection
181
+
182
+ // ❌ Absolute path (default) — cache misses on different machines
183
+ @get:InputFiles
184
+ abstract val files: ConfigurableFileCollection // absolute path = machine-specific
185
+ ```
186
+
187
+ ---
188
+
189
+ ## CI Cache Configuration
190
+
191
+ ```yaml
192
+ # .github/workflows/build.yml
193
+ jobs:
194
+ build:
195
+ runs-on: ubuntu-latest
196
+ steps:
197
+ - uses: actions/checkout@v4
198
+
199
+ - uses: actions/setup-java@v4
200
+ with:
201
+ distribution: temurin
202
+ java-version: 17
203
+
204
+ # ✅ Cache Gradle dependencies and build outputs
205
+ - name: Setup Gradle
206
+ uses: gradle/actions/setup-gradle@v3
207
+ with:
208
+ cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
209
+
210
+ - name: Build
211
+ run: ./gradlew assembleDebug
212
+ env:
213
+ CI: true
214
+ ```
215
+
216
+ ---
217
+
218
+ ## Anti-Patterns
219
+
220
+ - Not enabling local cache — free speedup left on the table
221
+ - Absolute paths in task inputs — cache miss on every machine
222
+ - Non-deterministic task outputs — cache entries become stale/incorrect
223
+ - Pushing to remote cache from developer machines — pollutes cache with unverified outputs
224
+ - `@CacheableTask` without `@PathSensitive` on file inputs — over-broad cache invalidation
225
+ - Timestamps or build numbers as task inputs — always a cache miss
226
+
227
+ ---
228
+
229
+ ## Related Skills
230
+ - `incremental-build` — incremental task execution
231
+ - `gradle` — Gradle build configuration
232
+ - `build-orchestration` — remote cache in multi-project builds
233
+ - `ci-cd` — cache configuration in CI pipeline
@@ -0,0 +1,171 @@
1
+ ---
2
+ name: build-flavor-strategy
3
+ description: >
4
+ Strategy for designing product flavors and build variant structure.
5
+ Load this skill when deciding how many flavors to create, what each
6
+ flavor dimension should represent, and how to keep variants manageable.
7
+ ---
8
+
9
+ # Build Flavor Strategy
10
+
11
+ ## Overview
12
+ Product flavors define what variant of the app is built — different environments, tiers, or feature sets. A poorly designed flavor structure leads to exponential variant count, complex CI pipelines, and unmaintainable build files. This skill defines how to design flavor structure deliberately.
13
+
14
+ ---
15
+
16
+ ## Core Principles
17
+
18
+ - Fewer flavors = simpler CI, faster builds, less maintenance
19
+ - Each flavor dimension should represent a **clearly different product concern**
20
+ - Prefer **build types** for environment differences — flavors for product differences
21
+ - Avoid flavors for things that can be done with **feature flags** or **Remote Config**
22
+ - Document the variant matrix — every combination must have a clear purpose
23
+
24
+ ---
25
+
26
+ ## Common Flavor Patterns
27
+
28
+ ### Pattern 1: Environment Only (Most Common)
29
+
30
+ ```kotlin
31
+ // ✅ Use when you need different backend environments
32
+ flavorDimensions += "environment"
33
+
34
+ productFlavors {
35
+ create("dev") {
36
+ dimension = "environment"
37
+ applicationIdSuffix = ".dev"
38
+ buildConfigField("String", "API_URL", "\"https://dev.api.example.com/\"")
39
+ }
40
+ create("staging") {
41
+ dimension = "environment"
42
+ applicationIdSuffix = ".staging"
43
+ buildConfigField("String", "API_URL", "\"https://staging.api.example.com/\"")
44
+ }
45
+ create("prod") {
46
+ dimension = "environment"
47
+ buildConfigField("String", "API_URL", "\"https://api.example.com/\"")
48
+ }
49
+ }
50
+ // Variants: devDebug, devRelease, stagingDebug, stagingRelease, prodDebug, prodRelease
51
+ ```
52
+
53
+ ### Pattern 2: Tier Only
54
+
55
+ ```kotlin
56
+ // ✅ Use when distributing free vs paid version of same app
57
+ flavorDimensions += "tier"
58
+
59
+ productFlavors {
60
+ create("free") {
61
+ dimension = "tier"
62
+ buildConfigField("Boolean", "IS_PREMIUM", "false")
63
+ }
64
+ create("premium") {
65
+ dimension = "tier"
66
+ buildConfigField("Boolean", "IS_PREMIUM", "true")
67
+ }
68
+ }
69
+ ```
70
+
71
+ ### Pattern 3: Two Dimensions (Use Sparingly)
72
+
73
+ ```kotlin
74
+ // ✅ Only when both dimensions represent truly independent product axes
75
+ flavorDimensions += listOf("environment", "tier")
76
+
77
+ // Results in: devFreeDebug, devPremiumDebug, prodFreeRelease, prodPremiumRelease...
78
+ // 8 variants — manageable if most are excluded
79
+
80
+ android {
81
+ variantFilter {
82
+ // Only build dev+free and prod+premium — others don't make sense
83
+ val env = flavors.find { it.dimension == "environment" }?.name
84
+ val tier = flavors.find { it.dimension == "tier" }?.name
85
+ if ((env == "dev" && tier == "premium") || (env == "prod" && tier == "free")) {
86
+ ignore = true
87
+ }
88
+ }
89
+ }
90
+ ```
91
+
92
+ ---
93
+
94
+ ## Environment via Build Type vs Flavor
95
+
96
+ ```kotlin
97
+ // ✅ Environment differences → Build Types (simpler)
98
+ // Use when dev/staging/prod differ only in config (URL, keys)
99
+ buildTypes {
100
+ debug { buildConfigField("String", "API_URL", "\"https://dev.api.com/\"") }
101
+ create("staging") { buildConfigField("String", "API_URL", "\"https://staging.api.com/\"") }
102
+ release { buildConfigField("String", "API_URL", "\"https://api.com/\"") }
103
+ }
104
+
105
+ // ✅ Environment via Flavors
106
+ // Use when environments need different:
107
+ // - Firebase projects (different google-services.json)
108
+ // - App IDs (can install dev and prod side by side)
109
+ // - Dependencies (dev has debug tools, prod doesn't)
110
+ ```
111
+
112
+ ---
113
+
114
+ ## Decision Framework
115
+
116
+ ```
117
+ Do you need separate Firebase projects per environment?
118
+ YES → Use flavors (each flavor can have its own google-services.json)
119
+ NO → Use build types
120
+
121
+ Do you need to install dev and prod side by side?
122
+ YES → Use flavors (different applicationId per flavor)
123
+ NO → Use build types + applicationIdSuffix
124
+
125
+ Do you have multiple product tiers (free/paid)?
126
+ YES → Add a tier flavor dimension
127
+ NO → Use feature flags or Remote Config
128
+
129
+ Would Remote Config solve this without a new flavor?
130
+ YES → Use Remote Config — avoid the flavor
131
+ NO → Proceed with flavor
132
+ ```
133
+
134
+ ---
135
+
136
+ ## Variant Matrix Documentation
137
+
138
+ ```markdown
139
+ <!-- Always document the variant matrix in the project -->
140
+
141
+ ## Build Variant Matrix
142
+
143
+ | Variant | Purpose | Used By |
144
+ |---------|---------|---------|
145
+ | devDebug | Local development | Developers |
146
+ | devRelease | Dev build for QA | QA team |
147
+ | stagingRelease | Pre-prod testing | QA + stakeholders |
148
+ | prodRelease | Production release | Play Store |
149
+
150
+ ### Excluded Variants
151
+ - stagingDebug — unnecessary (staging = pre-prod, always release config)
152
+ - prodDebug — security risk (debuggable prod build)
153
+ ```
154
+
155
+ ---
156
+
157
+ ## Anti-Patterns
158
+
159
+ - More than 2 flavor dimensions — variant count explodes (3 dims × 2 values = 8+ variants)
160
+ - Using flavors for feature flags — use Remote Config instead, no rebuild needed
161
+ - No variant filtering — building all combinations wastes CI time
162
+ - Flavors with overlapping purposes with build types — pick one
163
+ - Not documenting the variant matrix — developers don't know which variant to use
164
+
165
+ ---
166
+
167
+ ## Related Skills
168
+ - `build-variant` — implementing build types and flavors
169
+ - `gradle` — Gradle build configuration
170
+ - `remote-config` — replacing flavor-based feature switching
171
+ - `ci-cd` — building specific variants in CI pipeline