Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 21 additions & 6 deletions build-logic/convention/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ dependencies {
compileOnly(libs.ktlint.gradlePlugin)
compileOnly(libs.spotless.gradlePlugin)
implementation(libs.truth)

compileOnly(libs.firebase.crashlytics.gradlePlugin)
compileOnly(libs.firebase.performance.gradlePlugin)
}

tasks {
Expand All @@ -54,6 +57,16 @@ gradlePlugin {
implementationClass = "AndroidApplicationFlavorsConventionPlugin"
}

register("androidFirebase") {
id = "org.convention.android.application.firebase"
implementationClass = "AndroidApplicationFirebaseConventionPlugin"
}

register("androidLint") {
id = "org.convention.android.application.lint"
implementationClass = "AndroidLintConventionPlugin"
}

// This can removed after migration
register("androidLibrary") {
id = "mifos.android.library"
Expand Down Expand Up @@ -94,17 +107,19 @@ gradlePlugin {
}

// KMP & CMP Plugins
register("kmpLibrary") {
id = "mifos.kmp.library"
implementationClass = "KMPLibraryConventionPlugin"
}
register("cmpFeature") {
id = "mifos.cmp.feature"
id = "org.convention.cmp.feature"
implementationClass = "CMPFeatureConventionPlugin"
}

register("kmpKoin") {
id = "mifos.kmp.koin"
id = "org.convention.kmp.koin"
implementationClass = "KMPKoinConventionPlugin"
}

register("kmpLibrary") {
id = "org.convention.kmp.library"
implementationClass = "KMPLibraryConventionPlugin"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ class AndroidApplicationConventionPlugin : Plugin<Project> {
apply("mifos.detekt.plugin")
apply("mifos.spotless.plugin")
apply("mifos.git.hooks")
apply("org.convention.android.application.lint")
apply("org.convention.android.application.firebase")

}

extensions.configure<ApplicationExtension> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@


import com.android.build.api.dsl.ApplicationExtension
import com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies
import org.mifos.mobile.libs

class AndroidApplicationFirebaseConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
apply(plugin = "com.google.gms.google-services")
apply(plugin = "com.google.firebase.crashlytics")

dependencies {
val bom = libs.findLibrary("firebase-bom").get()
"implementation"(platform(bom))
"implementation"(libs.findLibrary("firebase.analytics").get())
"implementation"(libs.findLibrary("firebase.crashlytics").get())
}

extensions.configure<ApplicationExtension> {
buildTypes.configureEach {
// Disable the Crashlytics mapping file upload. This feature should only be
// enabled if a Firebase backend is available and configured in
// google-services.json.
configure<CrashlyticsExtension> {
mappingFileUploadEnabled = true
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

import com.android.build.api.dsl.ApplicationExtension
import com.android.build.api.dsl.LibraryExtension
import com.android.build.api.dsl.Lint
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure

class AndroidLintConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
when {
pluginManager.hasPlugin("com.android.application") ->
configure<ApplicationExtension> { lint(Lint::configure) }

pluginManager.hasPlugin("com.android.library") ->
configure<LibraryExtension> { lint(Lint::configure) }

else -> {
apply(plugin = "com.android.lint")
configure<Lint>(Lint::configure)
}
}
}
}
}

private fun Lint.configure() {
xmlReport = true
sarifReport = true
checkDependencies = true
disable += "GradleDependency"
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ class CMPFeatureConventionPlugin : Plugin<Project> {
override fun apply(target: Project) {
with(target) {
with(pluginManager) {
apply("mifos.kmp.library")
apply("mifos.kmp.koin")
apply("org.convention.kmp.library")
apply("org.convention.kmp.koin")
apply("org.jetbrains.kotlin.plugin.compose")
apply("org.jetbrains.compose")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import com.android.build.api.instrumentation.AsmClassVisitorFactory
import com.android.build.api.instrumentation.ClassContext
import com.android.build.api.instrumentation.ClassData
import com.android.build.api.instrumentation.InstrumentationParameters
import org.gradle.api.provider.SetProperty
import org.gradle.api.tasks.Input
import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.FieldVisitor

class FieldSkippingClassVisitor(
apiVersion: Int,
nextClassVisitor: ClassVisitor,
) : ClassVisitor(apiVersion, nextClassVisitor) {

// Returning null from this method will cause the ClassVisitor to strip all fields from the class.
override fun visitField(
access: Int,
name: String?,
descriptor: String?,
signature: String?,
value: Any?
): FieldVisitor? = null

abstract class Factory : AsmClassVisitorFactory<Parameters> {

private val excludedClasses
get() = parameters.get().classes.get()

override fun isInstrumentable(classData: ClassData): Boolean =
classData.className in excludedClasses

override fun createClassVisitor(
classContext: ClassContext,
nextClassVisitor: ClassVisitor,
): ClassVisitor {
return FieldSkippingClassVisitor(
apiVersion = instrumentationContext.apiVersion.get(),
nextClassVisitor = nextClassVisitor,
)
}
}

abstract class Parameters : InstrumentationParameters {
@get:Input
abstract val classes: SetProperty<String>
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class KMPLibraryConventionPlugin : Plugin<Project> {
with(pluginManager) {
apply("com.android.library")
apply("org.jetbrains.kotlin.multiplatform")
apply("mifos.kmp.koin")
apply("org.convention.kmp.koin")
apply("mifos.detekt.plugin")
apply("mifos.spotless.plugin")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package org.mifos.mobile


import com.android.build.api.dsl.CommonExtension
import com.android.build.api.dsl.ManagedVirtualDevice
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.invoke

/**
* Configure project for Gradle managed devices
*/
internal fun configureGradleManagedDevices(
commonExtension: CommonExtension<*, *, *, *, *, *>,
) {
val pixel4 = DeviceConfig("Pixel 4", 30, "aosp-atd")
val pixel6 = DeviceConfig("Pixel 6", 31, "aosp")
val pixelC = DeviceConfig("Pixel C", 30, "aosp-atd")

val localDevices = listOf(pixel4, pixel6, pixelC)
val ciDevices = listOf(pixel4, pixelC)

commonExtension.testOptions {
managedDevices {
allDevices {
localDevices.forEach { deviceConfig ->
maybeCreate(deviceConfig.taskName, ManagedVirtualDevice::class.java).apply {
device = deviceConfig.device
apiLevel = deviceConfig.apiLevel
systemImageSource = deviceConfig.systemImageSource
}
}
}
groups {
maybeCreate("ci").apply {
ciDevices.forEach { deviceConfig ->
targetDevices.add(allDevices[deviceConfig.taskName])
}
}
}
}
}
}

private data class DeviceConfig(
val device: String,
val apiLevel: Int,
val systemImageSource: String,
) {
val taskName = buildString {
append(device.lowercase().replace(" ", ""))
append("api")
append(apiLevel.toString())
append(systemImageSource.replace("-", ""))
}
}
Loading
Loading