Skip to content
Open
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
2 changes: 2 additions & 0 deletions aggregates/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ plugins {
alias(libs.plugins.kotlin.compose.compiler)
}

apply(from = "${project.rootDir}/jacoco/jacoco-kmp.gradle.kts")

kotlin {
androidLibrary {
namespace = "org.dhis2.mobile.aggregates"
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ allprojects {
cacheChangingModulesFor(0, TimeUnit.SECONDS)
eachDependency {
if (requested.group == "org.jacoco")
useVersion("0.8.10")
useVersion(libs.versions.jacoco.get())
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions commonskmm/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ plugins {
alias(libs.plugins.kotlin.serialization)
}

apply(from = "${project.rootDir}/jacoco/jacoco-kmp.gradle.kts")

kotlin {
compilerOptions {
freeCompilerArgs.add("-Xcontext-parameters")
Expand Down
157 changes: 157 additions & 0 deletions jacoco/jacoco-kmp.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
apply(plugin = "jacoco")

// Check if this is a Kotlin Multiplatform project
val isKmpProject = plugins.hasPlugin("org.jetbrains.kotlin.multiplatform")
val isAndroidProject = plugins.hasPlugin("com.android.library") || plugins.hasPlugin("com.android.application")

tasks.register("jacocoReport", JacocoReport::class) {
group = "Coverage"
description = "Generate XML/HTML code coverage reports"

// Set source directories based on project type
if (isKmpProject) {
// For KMP projects, include all source sets
sourceDirectories.setFrom(
layout.projectDirectory.dir("src/commonMain/kotlin"),
layout.projectDirectory.dir("src/androidMain/kotlin"),
layout.projectDirectory.dir("src/commonTest/kotlin"),
layout.projectDirectory.dir("src/androidUnitTest/kotlin")
Comment on lines +13 to +18

Copilot AI Jan 29, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sourceDirectories configuration includes test source directories (src/commonTest/kotlin and src/androidUnitTest/kotlin). Source directories should only contain production code, not test code. Test directories should be excluded from code coverage source directories to ensure accurate coverage reporting. Remove lines 17-18 that include test directories.

Suggested change
// For KMP projects, include all source sets
sourceDirectories.setFrom(
layout.projectDirectory.dir("src/commonMain/kotlin"),
layout.projectDirectory.dir("src/androidMain/kotlin"),
layout.projectDirectory.dir("src/commonTest/kotlin"),
layout.projectDirectory.dir("src/androidUnitTest/kotlin")
// For KMP projects, include only production source sets
sourceDirectories.setFrom(
layout.projectDirectory.dir("src/commonMain/kotlin"),
layout.projectDirectory.dir("src/androidMain/kotlin")

Copilot uses AI. Check for mistakes.
)
} else {
// For Android projects
sourceDirectories.setFrom("${project.projectDir}/src/main/java")
}

val excludes = mutableSetOf<String>(
"android/databinding/**/*.class",
"**/android/databinding/*Binding.class",
"**/android/databinding/*",
"**/androidx/databinding/*",
"**/BR.*",
"**/R.class",
"**/R\$*.class",
"**/BuildConfig.*",
"**/Manifest*.*",
"**/*Test*.*",
"android/**/*.*",
"**/*MapperImpl*.*",
"**/*\$ViewInjector*.*",
"**/*\$ViewBinder*.*",
"**/BuildConfig.*",
"**/*Component*.*",
"**/*BR*.*",
"**/Manifest*.*",
Comment on lines +40 to +43

Copilot AI Jan 29, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exclusion pattern "/BuildConfig.*" is duplicated on lines 33 and 40, and "/Manifest*.*" is duplicated on lines 34 and 43. These duplicates should be removed to keep the exclusion list clean and maintainable.

Suggested change
"**/BuildConfig.*",
"**/*Component*.*",
"**/*BR*.*",
"**/Manifest*.*",
"**/*Component*.*",
"**/*BR*.*",

Copilot uses AI. Check for mistakes.
"**/*\$Lambda\$*.*",
"**/*Companion*.*",
"**/*Module*.*",
"**/*Dagger*.*",
"**/*MembersInjector*.*",
"**/*_MembersInjector.class",
"**/*_Factory*.*",
"**/*_Provide*Factory*.*",
"**/*Extensions*.*",
"**/*\$Result.*",
"**/*\$Result\$*.*",
"**/*JsonAdapter.*",
"**/databinding/*.*",
"**/customviews/*.*",
"**/ui/*.class",
"**/*Activity.*",
"**/Activity*.*",
"**/*Activity*.*",
"**/*Fragment.*",
"**/Fragment*.*",
"**/*View.*",
"**/*Adapter.*",
"**/*Contract*.*",
"**/*Bindings*.*",
"**/AutoValue*.*",
"**/*\$*",
"**/*Navigator.*",
"**/*\$*\$*.*",

Copilot AI Jan 29, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The duplicate pattern "/$$." on line 71 is redundant as it's already covered by the more general pattern "/$" on line 69. The more general pattern will match any file with a dollar sign in its name, which includes files with multiple dollar signs. Consider removing the duplicate pattern on line 71.

Suggested change
"**/*\$*\$*.*",

Copilot uses AI. Check for mistakes.
"**/animations/*.*",
"**/*Holder*.*",
"**/*Dialog*.*",
"**/*Service*.*",
"**/*Button*.*",
"**/SearchTEList.*",
"**/lambda\$*\$*.*"
)
Comment on lines +25 to +79

Copilot AI Jan 30, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The excludes list contains duplicate entries. Line 33 and 40 both have "/BuildConfig.", and lines 34 and 43 both have "/Manifest.*". Consider removing these duplicates to keep the configuration clean and maintainable.

Copilot uses AI. Check for mistakes.
Comment on lines +25 to +79

Copilot AI Jan 30, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exclusions list contains duplicate entries. Lines 33 and 40 both have "/BuildConfig.*", and lines 34 and 43 both have "/Manifest*.*". Remove the duplicate entries to keep the configuration clean.

Suggested change
val excludes = mutableSetOf<String>(
"android/databinding/**/*.class",
"**/android/databinding/*Binding.class",
"**/android/databinding/*",
"**/androidx/databinding/*",
"**/BR.*",
"**/R.class",
"**/R\$*.class",
"**/BuildConfig.*",
"**/Manifest*.*",
"**/*Test*.*",
"android/**/*.*",
"**/*MapperImpl*.*",
"**/*\$ViewInjector*.*",
"**/*\$ViewBinder*.*",
"**/BuildConfig.*",
"**/*Component*.*",
"**/*BR*.*",
"**/Manifest*.*",
"**/*\$Lambda\$*.*",
"**/*Companion*.*",
"**/*Module*.*",
"**/*Dagger*.*",
"**/*MembersInjector*.*",
"**/*_MembersInjector.class",
"**/*_Factory*.*",
"**/*_Provide*Factory*.*",
"**/*Extensions*.*",
"**/*\$Result.*",
"**/*\$Result\$*.*",
"**/*JsonAdapter.*",
"**/databinding/*.*",
"**/customviews/*.*",
"**/ui/*.class",
"**/*Activity.*",
"**/Activity*.*",
"**/*Activity*.*",
"**/*Fragment.*",
"**/Fragment*.*",
"**/*View.*",
"**/*Adapter.*",
"**/*Contract*.*",
"**/*Bindings*.*",
"**/AutoValue*.*",
"**/*\$*",
"**/*Navigator.*",
"**/*\$*\$*.*",
"**/animations/*.*",
"**/*Holder*.*",
"**/*Dialog*.*",
"**/*Service*.*",
"**/*Button*.*",
"**/SearchTEList.*",
"**/lambda\$*\$*.*"
)
val excludes = mutableSetOf<String>(
"android/databinding/**/*.class",
"**/android/databinding/*Binding.class",
"**/android/databinding/*",
"**/androidx/databinding/*",
"**/BR.*",
"**/R.class",
"**/R\$*.class",
"**/BuildConfig.*",
"**/Manifest*.*",
"**/*Test*.*",
"android/**/*.*",
"**/*MapperImpl*.*",
"**/*\$ViewInjector*.*",
"**/*\$ViewBinder*.*",
"**/*Component*.*",
"**/*BR*.*",
"**/*\$Lambda\$*.*",
"**/*Companion*.*",
"**/*Module*.*",
"**/*Dagger*.*",
"**/*MembersInjector*.*",
"**/*_MembersInjector.class",
"**/*_Factory*.*",
"**/*_Provide*Factory*.*",
"**/*Extensions*.*",
"**/*\$Result.*",
"**/*\$Result\$*.*",
"**/*JsonAdapter.*",
"**/databinding/*.*",
"**/customviews/*.*",
"**/ui/*.class",
"**/*Activity.*",
"**/Activity*.*",
"**/*Activity*.*",
"**/*Fragment.*",
"**/Fragment*.*",
"**/*View.*",
"**/*Adapter.*",
"**/*Contract*.*",
"**/*Bindings*.*",
"**/AutoValue*.*",
"**/*\$*",
"**/*Navigator.*",
"**/*\$*\$*.*",
"**/animations/*.*",
"**/*Holder*.*",
"**/*Dialog*.*",
"**/*Service*.*",
"**/*Button*.*",
"**/SearchTEList.*",
"**/lambda\$*\$*.*"
)

Copilot uses AI. Check for mistakes.

// Set class directories based on project type
val classDirectoriesList = mutableListOf<Any>()

if (isAndroidProject) {
// Android project class directories
val javaClassesApp = fileTree(layout.buildDirectory.dir("intermediates/javac/dhisDebug")){
exclude(excludes)
}
val kotlinClassesApp = fileTree(layout.buildDirectory.dir("tmp/kotlin-classes/dhisDebug")){
exclude(excludes)
}
val javaClasses = fileTree(layout.buildDirectory.dir("intermediates/javac/debug")){
exclude(excludes)
}
val kotlinClasses = fileTree(layout.buildDirectory.dir("tmp/kotlin-classes/debug")){
exclude(excludes)
}

classDirectoriesList.addAll(listOf(javaClassesApp, kotlinClassesApp, javaClasses, kotlinClasses))
Comment on lines +85 to +99

Copilot AI Feb 10, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Android classDirectories are hard-coded to dhisDebug and debug. Modules like login define product flavors, so their debug variants will be like <flavor>Debug (e.g., dhis2Debug) and won’t be picked up by either of these paths, resulting in missing coverage. Consider collecting variant-specific class dirs dynamically (e.g., via Android Components/Variants API or by globbing over intermediates/javac/*Debug and tmp/kotlin-classes/*Debug).

Suggested change
// Android project class directories
val javaClassesApp = fileTree(layout.buildDirectory.dir("intermediates/javac/dhisDebug")){
exclude(excludes)
}
val kotlinClassesApp = fileTree(layout.buildDirectory.dir("tmp/kotlin-classes/dhisDebug")){
exclude(excludes)
}
val javaClasses = fileTree(layout.buildDirectory.dir("intermediates/javac/debug")){
exclude(excludes)
}
val kotlinClasses = fileTree(layout.buildDirectory.dir("tmp/kotlin-classes/debug")){
exclude(excludes)
}
classDirectoriesList.addAll(listOf(javaClassesApp, kotlinClassesApp, javaClasses, kotlinClasses))
// Android project class directories - include all *Debug variants
val javaDebugClasses = fileTree(layout.buildDirectory) {
// e.g. intermediates/javac/dhisDebug/classes/**, intermediates/javac/dhis2Debug/classes/**, etc.
include("intermediates/javac/*Debug/classes/**")
exclude(excludes)
}
val kotlinDebugClasses = fileTree(layout.buildDirectory) {
// e.g. tmp/kotlin-classes/dhisDebug/**, tmp/kotlin-classes/dhis2Debug/**, etc.
include("tmp/kotlin-classes/*Debug/**")
exclude(excludes)
}
classDirectoriesList.addAll(listOf(javaDebugClasses, kotlinDebugClasses))

Copilot uses AI. Check for mistakes.
}

if (isKmpProject) {
// KMP project class directories
val commonClasses = fileTree(layout.buildDirectory.dir("classes/kotlin/common")){

Copilot AI Jan 30, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The class directory path "classes/kotlin/common" might be incorrect for KMP projects. Kotlin Multiplatform typically uses paths like "classes/kotlin/commonMain" for common source set compilation. Verify this path matches the actual build output directory structure, or consider using "classes/kotlin/commonMain" instead.

Suggested change
val commonClasses = fileTree(layout.buildDirectory.dir("classes/kotlin/common")){
val commonClasses = fileTree(layout.buildDirectory.dir("classes/kotlin/commonMain")){

Copilot uses AI. Check for mistakes.
exclude(excludes)
}
val androidClasses = fileTree(layout.buildDirectory.dir("classes/kotlin/android")){
exclude(excludes)
}
val jvmClasses = fileTree(layout.buildDirectory.dir("classes/kotlin/jvm")){
Comment on lines +104 to +110

Copilot AI Jan 30, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The class directory paths "classes/kotlin/android" and "classes/kotlin/jvm" might be incorrect for KMP projects. Kotlin Multiplatform typically uses paths like "classes/kotlin/android/main" and "classes/kotlin/jvm/main" for target-specific compilation. Verify these paths match the actual build output directory structure.

Suggested change
val commonClasses = fileTree(layout.buildDirectory.dir("classes/kotlin/common")){
exclude(excludes)
}
val androidClasses = fileTree(layout.buildDirectory.dir("classes/kotlin/android")){
exclude(excludes)
}
val jvmClasses = fileTree(layout.buildDirectory.dir("classes/kotlin/jvm")){
val commonClasses = fileTree(layout.buildDirectory.dir("classes/kotlin/common/main")){
exclude(excludes)
}
val androidClasses = fileTree(layout.buildDirectory.dir("classes/kotlin/android/main")){
exclude(excludes)
}
val jvmClasses = fileTree(layout.buildDirectory.dir("classes/kotlin/jvm/main")){

Copilot uses AI. Check for mistakes.
exclude(excludes)
}

classDirectoriesList.addAll(listOf(commonClasses, androidClasses, jvmClasses))
Comment on lines +103 to +114

Copilot AI Jan 29, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The class directory paths for KMP projects may not be accurate. Kotlin Multiplatform projects typically output compiled classes to paths like "classes/kotlin/jvm/main", "classes/kotlin/android/debug", etc., not just "classes/kotlin/common" or "classes/kotlin/android". The actual paths depend on the target configuration. Consider verifying these paths match the actual KMP build output structure or making them more flexible to handle different KMP target configurations.

Suggested change
// KMP project class directories
val commonClasses = fileTree(layout.buildDirectory.dir("classes/kotlin/common")){
exclude(excludes)
}
val androidClasses = fileTree(layout.buildDirectory.dir("classes/kotlin/android")){
exclude(excludes)
}
val jvmClasses = fileTree(layout.buildDirectory.dir("classes/kotlin/jvm")){
exclude(excludes)
}
classDirectoriesList.addAll(listOf(commonClasses, androidClasses, jvmClasses))
// KMP project class directories - include all KMP targets/variants under classes/kotlin
val kmpClasses = fileTree(layout.buildDirectory) {
include(
"classes/kotlin/**/main/**",
"classes/kotlin/**/debug/**",
"classes/kotlin/**/release/**"
)
exclude(excludes)
}
classDirectoriesList.add(kmpClasses)

Copilot uses AI. Check for mistakes.
}

classDirectories.setFrom(files(classDirectoriesList))

// Execution data - look for both .exec and .ec files
val unitTestsData = fileTree(layout.buildDirectory.dir("jacoco")) {
include("*.exec")
}
val androidTestsData = fileTree(layout.buildDirectory.dir("outputs/code_coverage")) {
include(listOf("**/*.ec"))
}

executionData.setFrom(files(listOf(unitTestsData, androidTestsData)))

// Add test task dependencies based on project type
if (isAndroidProject) {
val testTask = tasks.findByName("testDebugUnitTest")
val androidTestTask = tasks.findByName("connectedDebugAndroidTest")

if (testTask != null) dependsOn(testTask)
if (androidTestTask != null) dependsOn(androidTestTask)
}

if (isKmpProject) {
val commonTestTask = tasks.findByName("testDebugUnitTest") ?: tasks.findByName("test")
val androidTestTask = tasks.findByName("connectedDebugAndroidTest") ?: tasks.findByName("androidTest")

if (commonTestTask != null) dependsOn(commonTestTask)
if (androidTestTask != null) dependsOn(androidTestTask)
Comment on lines +138 to +143

Copilot AI Jan 29, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test task name "test" used here may not exist for Kotlin Multiplatform projects. KMP projects typically have platform-specific test tasks like "allTests", "testDebugUnitTest", "jvmTest", "desktopTest", etc. Consider using more specific task names or making this conditional based on the actual available test tasks. The same applies to "androidTest" on line 140 which is typically named "testDebugUnitTest" or "testReleaseUnitTest" for Android unit tests.

Copilot uses AI. Check for mistakes.
}

Comment on lines +129 to +145

Copilot AI Feb 10, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For KMP Android library modules both isAndroidProject and isKmpProject are true, so the same Android test tasks can be added to dependsOn twice (once in each block). This is harmless but makes the task configuration harder to reason about; consider collapsing the dependency wiring into a single block that deduplicates tasks.

Suggested change
// Add test task dependencies based on project type
if (isAndroidProject) {
val testTask = tasks.findByName("testDebugUnitTest")
val androidTestTask = tasks.findByName("connectedDebugAndroidTest")
if (testTask != null) dependsOn(testTask)
if (androidTestTask != null) dependsOn(androidTestTask)
}
if (isKmpProject) {
val commonTestTask = tasks.findByName("testDebugUnitTest") ?: tasks.findByName("test")
val androidTestTask = tasks.findByName("connectedDebugAndroidTest") ?: tasks.findByName("androidTest")
if (commonTestTask != null) dependsOn(commonTestTask)
if (androidTestTask != null) dependsOn(androidTestTask)
}
// Add test task dependencies based on project type, deduplicating tasks
val testTaskNames = mutableSetOf<String>()
if (isAndroidProject) {
// Standard Android unit and instrumentation test tasks
testTaskNames.add("testDebugUnitTest")
testTaskNames.add("connectedDebugAndroidTest")
}
if (isKmpProject) {
// KMP projects may use the same Android tasks or fall back to generic ones
val commonTestName = if (tasks.findByName("testDebugUnitTest") != null) {
"testDebugUnitTest"
} else {
"test"
}
val androidTestName = if (tasks.findByName("connectedDebugAndroidTest") != null) {
"connectedDebugAndroidTest"
} else {
"androidTest"
}
testTaskNames.add(commonTestName)
testTaskNames.add(androidTestName)
}
testTaskNames.forEach { taskName ->
val task = tasks.findByName(taskName)
if (task != null) dependsOn(task)
}

Copilot uses AI. Check for mistakes.
fun JacocoReportsContainer.reports() {
xml.required.set(true)
xml.outputLocation.set(layout.buildDirectory.file("coverage-report/jacocoTestReport.xml"))

html.required.set(true)
html.outputLocation.set(layout.buildDirectory.dir("coverage-report"))
}

reports {
reports()
}
}
38 changes: 21 additions & 17 deletions jacoco/jacoco.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ tasks.register("jacocoReport", JacocoReport::class) {
group = "Coverage"
description = "Generate XML/HTML code coverage reports for coverage.ec"

// Make sure tests are run before generating the report
// Only add dependencies if the tasks exist
val testTask = tasks.findByName("testDebugUnitTest")
val androidTestTask = tasks.findByName("connectedDebugAndroidTest")

if (testTask != null) {
dependsOn(testTask)
}
if (androidTestTask != null) {
dependsOn(androidTestTask)
}

sourceDirectories.setFrom("${project.projectDir}/src/main/java")

val excludes = mutableSetOf<String>(
Expand Down Expand Up @@ -62,18 +74,18 @@ tasks.register("jacocoReport", JacocoReport::class) {
"**/lambda\$*\$*.*"
)

val javaClassesApp = fileTree("${buildDir}/intermediates/javac/dhisDebug"){
val javaClassesApp = fileTree(layout.buildDirectory.dir("intermediates/javac/dhisDebug")){
exclude(
excludes
)
}
val kotlinClassesApp = fileTree("${buildDir}/tmp/kotlin-classes/dhisDebug"){
val kotlinClassesApp = fileTree(layout.buildDirectory.dir("tmp/kotlin-classes/dhisDebug")){
exclude(excludes)
}
val javaClasses = fileTree("${buildDir}/intermediates/javac/debug"){
val javaClasses = fileTree(layout.buildDirectory.dir("intermediates/javac/debug")){
exclude(excludes)
}
val kotlinClasses = fileTree("${buildDir}/tmp/kotlin-classes/debug"){
val kotlinClasses = fileTree(layout.buildDirectory.dir("tmp/kotlin-classes/debug")){
exclude(excludes)
}

Expand All @@ -88,10 +100,10 @@ tasks.register("jacocoReport", JacocoReport::class) {
)
)

val unitTestsData = fileTree("${buildDir}/jacoco") {
val unitTestsData = fileTree(layout.buildDirectory.dir("jacoco")) {
include("*.exec")
}
val androidTestsData = fileTree("${buildDir}/outputs/code_coverage") {
val androidTestsData = fileTree(layout.buildDirectory.dir("outputs/code_coverage")) {
include(listOf("**/*.ec"))
}

Expand All @@ -106,23 +118,15 @@ tasks.register("jacocoReport", JacocoReport::class) {

fun JacocoReportsContainer.reports() {
xml.required.set(true)
xml.outputLocation.set(file("${buildDir}/coverage-report/jacocoTestReport.xml"))
xml.outputLocation.set(layout.buildDirectory.file("coverage-report/jacocoTestReport.xml"))

html.required.set(true)
html.outputLocation.set(file("${buildDir}/coverage-report"))
html.outputLocation.set(layout.buildDirectory.dir("coverage-report"))
}

reports {
reports()
}
}

/*android {
buildTypes {
getByName("debug") {
// jacoco test coverage reports both for
// androidTest and test source sets
testCoverageEnabled = false
}
}
}*/

2 changes: 2 additions & 0 deletions login/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ plugins {
alias(libs.plugins.kotlin.serialization)
}

apply(from = "${project.rootDir}/jacoco/jacoco-kmp.gradle.kts")

kotlin {

compilerOptions {
Expand Down
2 changes: 2 additions & 0 deletions sync/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ plugins {
alias(libs.plugins.kotlin.serialization)
}

apply(from = "${project.rootDir}/jacoco/jacoco-kmp.gradle.kts")

kotlin {

compilerOptions {
Expand Down
2 changes: 2 additions & 0 deletions tracker/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ plugins {
alias(libs.plugins.kotlin.compose.compiler)
}

apply(from = "${project.rootDir}/jacoco/jacoco-kmp.gradle.kts")

kotlin {
androidLibrary {
namespace = "org.dhis2.mobile.tracker"
Expand Down
Loading