@@ -12,6 +12,8 @@ plugins {
1212 alias(libs.plugins.google.services)
1313 alias(libs.plugins.protobuf)
1414 alias(libs.plugins.room)
15+ alias(libs.plugins.detekt)
16+ alias(libs.plugins.spotless)
1517}
1618
1719// https://developer.android.com/studio/publish/app-signing#secure-key
@@ -83,8 +85,11 @@ android {
8385 keyPassword = " android"
8486 }
8587 create(" release" ) {
86- val keystoreFile = keystoreProperties.getProperty(" storeFile" ).takeIf { it.isNotBlank() }
87- ?.let { rootProject.file(it) }
88+ val keystoreFile =
89+ keystoreProperties
90+ .getProperty(" storeFile" )
91+ .takeIf { it.isNotBlank() }
92+ ?.let { rootProject.file(it) }
8893 storeFile = if (keystoreFile?.exists() == true ) keystoreFile else null
8994 // storeFile = rootProject.file(keystoreProperties.getProperty("storeFile"))
9095 storePassword = keystoreProperties.getProperty(" storePassword" )
@@ -105,7 +110,7 @@ android {
105110 isShrinkResources = false
106111 proguardFiles(
107112 getDefaultProguardFile(" proguard-android-optimize.txt" ),
108- " proguard-rules.pro"
113+ " proguard-rules.pro" ,
109114 )
110115 signingConfig = signingConfigs.getByName(" release" )
111116 ndk {
@@ -137,7 +142,7 @@ android {
137142 }
138143 testOptions {
139144 unitTests {
140- isReturnDefaultValues = true // mockito
145+ isReturnDefaultValues = true // mockito
141146 isIncludeAndroidResources = true // robolectric
142147 }
143148 }
@@ -171,12 +176,46 @@ protobuf {
171176}
172177
173178composeCompiler {
174- featureFlags = setOf (
175- ComposeFeatureFlag .StrongSkipping .disabled(),
176- ComposeFeatureFlag .OptimizeNonSkippingGroups ,
177- )
179+ featureFlags =
180+ setOf (
181+ ComposeFeatureFlag .StrongSkipping .disabled(),
182+ ComposeFeatureFlag .OptimizeNonSkippingGroups ,
183+ )
178184 reportsDestination = layout.buildDirectory.dir(" compose_compiler" )
179185}
186+
187+ // Linting Configuration
188+ val isCI = System .getenv(" CI" ).toBoolean()
189+
190+ tasks.withType< io.gitlab.arturbosch.detekt.Detekt > ().configureEach {
191+ ignoreFailures = ! isCI
192+ reports {
193+ html.required.set(! isCI)
194+ md.required.set(! isCI)
195+ sarif.required.set(true )
196+ txt.required.set(false )
197+ xml.required.set(isCI)
198+ }
199+ }
200+
201+ spotless {
202+ val ktlintVersion = " 1.0.1"
203+ kotlin {
204+ target(" **/*.kt" )
205+ targetExclude(" **/build/**/*.kt" , " **/generated/**/*.kt" )
206+ ktlint(ktlintVersion).setEditorConfigPath(rootProject.file(" .editorconfig" ).absolutePath)
207+ trimTrailingWhitespace()
208+ endWithNewline()
209+ }
210+
211+ kotlinGradle {
212+ target(" *.gradle.kts" )
213+ ktlint(ktlintVersion)
214+ trimTrailingWhitespace()
215+ endWithNewline()
216+ }
217+ }
218+
180219dependencies {
181220 implementation(fileTree(" libs" ) { include(" *.aar" ) })
182221 implementation(libs.jna) { artifact { type = " aar" } }
@@ -273,10 +312,14 @@ dependencies {
273312 testImplementation(libs.test.mockito.kotlin)
274313 testImplementation(libs.test.robolectric)
275314 testImplementation(libs.test.turbine)
315+ // Linting
316+ detektPlugins(libs.detekt.formatting)
317+ detektPlugins(libs.detekt.compose.rules)
276318}
277319ksp {
278- // cool but strict: https://developer.android.com/jetpack/androidx/releases/room#2.6.0
279- // arg("room.generateKotlin", "true")
320+ arg(" room.schemaLocation" , " $projectDir /schemas" )
321+ arg(" room.incremental" , " true" )
322+ arg(" room.expandProjection" , " true" )
280323}
281324// https://developer.android.com/jetpack/androidx/releases/room#gradle-plugin
282325room {
@@ -288,3 +331,24 @@ tasks.withType<Test> {
288331 // showStandardStreams = true
289332 }
290333}
334+
335+ tasks.register(" lintAll" ) {
336+ group = " verification"
337+ description = " Run all linting tools"
338+ dependsOn(" detekt" , " spotlessCheck" )
339+ }
340+
341+ tasks.register(" formatAll" ) {
342+ group = " formatting"
343+ description = " Apply all formatting tools"
344+ dependsOn(" spotlessApply" )
345+ }
346+
347+ tasks.register(" preCommit" ) {
348+ group = " verification"
349+ description = " Run checks that should pass before committing (fast subset)"
350+ dependsOn(" spotlessCheck" )
351+ doLast {
352+ println (" ✅ Pre-commit checks passed!" )
353+ }
354+ }
0 commit comments