Merge JaCoCo coverage reports the "right" way (#3650)

* Merge JaCoCo coverage reports the "right" way

* Generate code coverage report when "check" lifecycle task is run
This commit is contained in:
Matthew Haughton
2021-05-21 20:29:51 +10:00
committed by GitHub
parent 506c491f50
commit f5fe1d1e50
5 changed files with 127 additions and 30 deletions

View File

@@ -25,7 +25,7 @@ jobs:
java-version: 11
- name: Generate Coverage Report
run: ./gradlew jacocoTestReport --no-build-cache -x :detekt-gradle-plugin:test
run: ./gradlew jacocoMergedReport --no-build-cache -x :detekt-gradle-plugin:test
- name: Publish Coverage
if: success()

View File

@@ -2,8 +2,6 @@ import io.gitlab.arturbosch.detekt.Detekt
import io.gitlab.arturbosch.detekt.DetektCreateBaselineTask
plugins {
kotlin("jvm") apply false
jacoco
packaging
releasing
detekt
@@ -19,33 +17,6 @@ allprojects {
version = Versions.currentOrSnapshot()
}
jacoco.toolVersion = libs.versions.jacoco.get()
tasks {
jacocoTestReport {
executionData.setFrom(fileTree(project.rootDir.absolutePath).include("**/build/jacoco/*.exec"))
val examplesOrTestUtils = setOf(
"detekt-bom",
"detekt-test",
"detekt-test-utils",
"detekt-sample-extensions"
)
subprojects
.filterNot { it.name in examplesOrTestUtils }
.forEach {
this@jacocoTestReport.sourceSets(it.sourceSets.main.get())
this@jacocoTestReport.dependsOn(it.tasks.test)
}
reports {
xml.isEnabled = true
xml.destination = file("$buildDir/reports/jacoco/report.xml")
}
}
}
val analysisDir = file(projectDir)
val baselineFile = file("$rootDir/config/detekt/baseline.xml")
val configFile = file("$rootDir/config/detekt/detekt.yml")

View File

@@ -1,5 +1,6 @@
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
@@ -46,6 +47,39 @@ tasks.withType<Test>().configureEach {
}
}
// Share sources folder with other projects for aggregated JaCoCo reports
configurations.create("transitiveSourcesElements") {
isVisible = false
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.DOCUMENTATION))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named("source-folders"))
}
sourceSets.main.get().withConvention(KotlinSourceSet::class) { kotlin }.srcDirs.forEach {
outgoing.artifact(it)
}
}
// Share the coverage data to be aggregated for the whole product
configurations.create("coverageDataElements") {
isVisible = false
isCanBeResolved = false
isCanBeConsumed = true
attributes {
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.DOCUMENTATION))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named("jacoco-coverage-data"))
}
// This will cause the test task to run if the coverage data is requested by the aggregation task
outgoing.artifact(
tasks.test.map { task ->
task.extensions.getByType<JacocoTaskExtension>().destinationFile!!
}
)
}
tasks.withType<KotlinCompile>().configureEach {
kotlinOptions {
jvmTarget = Versions.JVM_TARGET

View File

@@ -0,0 +1,91 @@
plugins {
id("java")
id("jacoco")
}
jacoco.toolVersion = libs.versions.jacoco.get()
dependencies {
implementation(projects.customChecks)
implementation(projects.detektApi)
implementation(projects.detektCli)
implementation(projects.detektCore)
implementation(projects.detektFormatting)
implementation(projects.detektGenerator)
implementation(projects.detektGradlePlugin)
implementation(projects.detektMetrics)
implementation(projects.detektParser)
implementation(projects.detektPsiUtils)
implementation(projects.detektReportHtml)
implementation(projects.detektReportSarif)
implementation(projects.detektReportTxt)
implementation(projects.detektReportXml)
implementation(projects.detektRules)
implementation(projects.detektRulesComplexity)
implementation(projects.detektRulesCoroutines)
implementation(projects.detektRulesDocumentation)
implementation(projects.detektRulesEmpty)
implementation(projects.detektRulesErrorprone)
implementation(projects.detektRulesExceptions)
implementation(projects.detektRulesNaming)
implementation(projects.detektRulesPerformance)
implementation(projects.detektRulesStyle)
implementation(projects.detektTooling)
}
// A resolvable configuration to collect source code
val jacocoSourceDirs: Configuration by configurations.creating {
isVisible = false
isCanBeResolved = true
isCanBeConsumed = false
isTransitive = false
extendsFrom(configurations.implementation.get())
attributes {
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.DOCUMENTATION))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named("source-folders"))
}
}
// A resolvable configuration to collect JaCoCo coverage data
val jacocoExecutionData: Configuration by configurations.creating {
isVisible = false
isCanBeResolved = true
isCanBeConsumed = false
isTransitive = false
extendsFrom(configurations.implementation.get())
attributes {
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.DOCUMENTATION))
attribute(DocsType.DOCS_TYPE_ATTRIBUTE, objects.named("jacoco-coverage-data"))
}
}
val jacocoClassDirs: Configuration by configurations.creating {
extendsFrom(configurations.implementation.get())
isVisible = false
isCanBeResolved = true
isCanBeConsumed = false
isTransitive = false
attributes {
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.CLASSES))
}
}
val jacocoMergedReport by tasks.registering(JacocoReport::class) {
description = "Merge JaCoCo reports from dependencies."
group = "verification"
executionData.from(jacocoExecutionData.incoming.artifacts.artifactFiles)
sourceDirectories.from(jacocoSourceDirs.incoming.artifacts.artifactFiles)
classDirectories.from(jacocoClassDirs.incoming.artifacts.artifactFiles)
reports {
xml.required.set(true)
html.required.set(true)
}
}
tasks.check {
dependsOn(jacocoMergedReport)
}

View File

@@ -1,5 +1,6 @@
rootProject.name = "detekt"
include(
"code-coverage-report",
"custom-checks",
"detekt-api",
"detekt-cli",