Skip to content
Draft
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
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ jobs:
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}

- name: ⚙️ Check coverage for debug variant (includes unit & screenshot tests)
run: ./gradlew testDebugUnitTest :tests:uitests:verifyPaparazziDebug :app:koverXmlReportGplayDebug :app:koverHtmlReportGplayDebug :app:koverVerifyAll $CI_GRADLE_ARG_PROPERTIES
run: ./gradlew testDebugUnitTest :tests:uitests:verifyPaparazziDebug :koverXmlReportMerged :koverHtmlReportMerged :koverVerifyAll $CI_GRADLE_ARG_PROPERTIES

- name: 🚫 Upload kover failed coverage reports
if: failure()
Expand Down Expand Up @@ -101,5 +101,5 @@ jobs:
with:
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}
files: app/build/reports/kover/reportGplayDebug.xml
files: build/reports/kover/reportMerged.xml
verbose: true
3 changes: 1 addition & 2 deletions annotations/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@
* Please see LICENSE files in the repository root for full details.
*/
plugins {
alias(libs.plugins.kotlin.jvm)
id("com.android.lint")
id("io.element.jvm-library")
}
6 changes: 0 additions & 6 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@ import extension.allFeaturesImpl
import extension.allLibrariesImpl
import extension.allServicesImpl
import extension.buildConfigFieldStr
import extension.koverDependencies
import extension.locales
import extension.setupDependencyInjection
import extension.setupKover
import extension.testCommonDependencies
import java.util.Locale

Expand All @@ -41,8 +39,6 @@ plugins {
// alias(libs.plugins.gms.google.services)
}

setupKover()

android {
namespace = "io.element.android.x"

Expand Down Expand Up @@ -316,8 +312,6 @@ dependencies {
testCommonDependencies(libs)
testImplementation(projects.libraries.matrix.test)
testImplementation(projects.services.toolbox.test)

koverDependencies()
}

tasks.withType<GenerateBuildConfig>().configureEach {
Expand Down
15 changes: 1 addition & 14 deletions libraries/core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,7 @@
* Please see LICENSE files in the repository root for full details.
*/
plugins {
id("java-library")
id("com.android.lint")
alias(libs.plugins.kotlin.jvm)
}

java {
sourceCompatibility = Versions.javaVersion
targetCompatibility = Versions.javaVersion
}

kotlin {
jvmToolchain {
languageVersion = Versions.javaLanguageVersion
}
id("io.element.jvm-library")
}

dependencies {
Expand Down
3 changes: 1 addition & 2 deletions libraries/di/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
*/

plugins {
alias(libs.plugins.kotlin.jvm)
id("com.android.lint")
id("io.element.jvm-library")
}

dependencies {
Expand Down
100 changes: 48 additions & 52 deletions plugins/src/main/kotlin/extension/KoverExtension.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,27 @@ import kotlinx.kover.gradle.plugin.dsl.CoverageUnit
import kotlinx.kover.gradle.plugin.dsl.GroupingEntityType
import kotlinx.kover.gradle.plugin.dsl.KoverProjectExtension
import kotlinx.kover.gradle.plugin.dsl.KoverVariantCreateConfig
import org.gradle.api.Action
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.assign
import org.gradle.kotlin.dsl.configure
import java.io.File

enum class KoverVariant(val variantName: String) {
Presenters("presenters"),
States("states"),
Views("views"),
}

val koverVariants = KoverVariant.values().map { it.variantName }
val koverVariants = KoverVariant.entries.map { it.variantName }

val localAarProjects = listOf(
":libraries:rustsdk",
":libraries:textcomposer:lib"
)

val excludedKoverSubProjects = listOf(
":app",
":appconfig",
":annotations",
":codegen",
":tests:testutils",
Expand All @@ -42,24 +43,63 @@ val excludedKoverSubProjects = listOf(
":libraries:core",
":libraries:coroutines",
":libraries:di",
":tests:detekt-rules",
":tests:konsist",
":tests:testutils",
) + localAarProjects

private fun Project.kover(action: Action<KoverProjectExtension>) {
(this as org.gradle.api.plugins.ExtensionAware).extensions.configure("kover", action)
private fun Project.kover(any: Any) {
this.dependencies.add("kover", any)
}

fun Project.setupKover() {
// If the project is excluded from Kover, don't apply anything
if (path in excludedKoverSubProjects) return

// Apply the plugin
apply(plugin = "org.jetbrains.kotlinx.kover")

// Create verify all task joining all existing verification tasks
tasks.register("koverVerifyAll") {
group = "verification"
description = "Verifies the code coverage of all subprojects."
val dependencies = listOf(":app:koverVerifyGplayDebug") + koverVariants.map { ":app:koverVerify${it.replaceFirstChar(Char::titlecase)}" }
val dependencies = listOf(":koverVerifyMerged") + koverVariants.map { ":app:koverVerify${it.replaceFirstChar(Char::titlecase)}" }
dependsOn(dependencies)
}
// https://kotlin.github.io/kotlinx-kover/
// Run `./gradlew :app:koverHtmlReport` to get report at ./app/build/reports/kover
// Run `./gradlew :app:koverXmlReport` to get XML report
kover {
extensions.configure<KoverProjectExtension> {
currentProject {
// Create custom variants for verification
for (variant in koverVariants) {
createVariant(variant) {
defaultVariants(project)

// Using the cache for coverage verification seems to be flaky, so we disable it for now.
val taskName = "koverCachedVerify${variant.replaceFirstChar(Char::titlecase)}"
val cachedTask = project.tasks.findByName(taskName)
cachedTask?.let {
it.outputs.upToDateWhen { false }
}
}
}

// Create merged variant
createVariant("merged") {
defaultVariants(project)
}
}

// If it's the root project, set up kover for subprojects
if (project.path == ":") {
for (project in project.subprojects) {
if (project.path !in excludedKoverSubProjects && File(project.projectDir, "build.gradle.kts").exists()) {
kover(project)
}
}
}

reports {
filters {
excludes {
Expand Down Expand Up @@ -194,54 +234,10 @@ fun Project.setupKover() {
}
}

fun Project.applyKoverPluginToAllSubProjects() = rootProject.subprojects {
if (project.path !in localAarProjects) {
apply(plugin = "org.jetbrains.kotlinx.kover")
kover {
currentProject {
for (variant in koverVariants) {
createVariant(variant) {
defaultVariants(project)
}
}
}
}

project.afterEvaluate {
for (variant in koverVariants) {
// Using the cache for coverage verification seems to be flaky, so we disable it for now.
val taskName = "koverCachedVerify${variant.replaceFirstChar(Char::titlecase)}"
val cachedTask = project.tasks.findByName(taskName)
cachedTask?.let {
it.outputs.upToDateWhen { false }
}
}
}
}
}

fun KoverVariantCreateConfig.defaultVariants(project: Project) {
if (project.name == "app") {
if (project.path == ":app") {
addWithDependencies("gplayDebug")
} else {
addWithDependencies("debug", "jvm", optional = true)
}
}

fun Project.koverSubprojects() = project.rootProject.subprojects
.filter {
it.project.projectDir.resolve("build.gradle.kts").exists()
}
.map { it.path }
.sorted()
.filter {
it !in excludedKoverSubProjects
}

fun Project.koverDependencies() {
project.koverSubprojects()
.forEach {
// println("Add $it to kover")
dependencies.add("kover", project(it))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import extension.androidConfig
import extension.commonDependencies
import extension.composeConfig
import extension.composeDependencies
import extension.setupKover
import org.gradle.accessors.dm.LibrariesForLibs

val libs = the<LibrariesForLibs>()
Expand All @@ -37,6 +38,8 @@ kotlin {
}
}

setupKover()

dependencies {
commonDependencies(libs)
composeDependencies(libs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import extension.androidConfig
import extension.commonDependencies
import extension.composeConfig
import extension.composeDependencies
import extension.setupKover
import org.gradle.accessors.dm.LibrariesForLibs

val libs = the<LibrariesForLibs>()
Expand All @@ -37,6 +38,8 @@ kotlin {
}
}

setupKover()

dependencies {
commonDependencies(libs)
composeDependencies(libs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
*/
import extension.androidConfig
import extension.commonDependencies
import extension.setupKover
import org.gradle.accessors.dm.LibrariesForLibs

val libs = the<LibrariesForLibs>()
Expand All @@ -33,6 +34,8 @@ kotlin {
}
}

setupKover()

dependencies {
commonDependencies(libs)
coreLibraryDesugaring(libs.android.desugar)
Expand Down
4 changes: 2 additions & 2 deletions plugins/src/main/kotlin/io.element.android-root.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import extension.applyKoverPluginToAllSubProjects
import extension.setupKover

plugins {
id("org.jetbrains.kotlinx.kover") apply false
}

applyKoverPluginToAllSubProjects()
setupKover()
28 changes: 28 additions & 0 deletions plugins/src/main/kotlin/io.element.jvm-library.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2022-2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/

/**
* This will generate the plugin "io.element.jvm-library", used in pure JVM libraries.
*/
import extension.setupKover
import org.gradle.accessors.dm.LibrariesForLibs

val libs = the<LibrariesForLibs>()
plugins {
id("org.jetbrains.kotlin.jvm")
id("com.autonomousapps.dependency-analysis")
id("com.android.lint")
}

kotlin {
jvmToolchain {
languageVersion = Versions.javaLanguageVersion
}
}

setupKover()
Loading