Skip to content

Commit

Permalink
Merge pull request #55 from nicbell/feature/kover_update
Browse files Browse the repository at this point in the history
Migrate to KTS & Upgrade Kover to 0.7.3
  • Loading branch information
nicbell authored Nov 17, 2023
2 parents 2b5dd1c + 3fdc9d8 commit 57c72f2
Show file tree
Hide file tree
Showing 11 changed files with 147 additions and 120 deletions.
16 changes: 4 additions & 12 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,13 @@ jobs:
- name: Unit tests
run: ./gradlew testDebugUnitTest
- name: Kover report
run: ./gradlew koverMergedReport
# - name: Add coverage report to PR
# id: kover
# uses: mi-kas/[email protected]
# with:
# path: ${{ github.workspace }}/build/reports/kover/merged/xml/report.xml
# token: ${{ secrets.GITHUB_TOKEN }}
# title: Code Coverage
# update-comment: true
# min-coverage-overall: 80
# min-coverage-changed-files: 80
run: ./gradlew koverHtmlReport koverXmlReport
- name: Kover dump
run: ./gradlew koverDump -q
- name: Codecov
uses: codecov/codecov-action@v3
with:
files: ./build/reports/kover/merged/xml/report.xml
files: ./build/reports/kover/report.xml
flags: unittests
verbose: true
- name: Upload reports
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
SIGNING_KEY_ID: ${{ secrets.SIGNING_KEY_ID }}
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
SIGNING_PASSWORD: ${{ secrets.SIGNING_PASSWORD }}
run: ./gradlew assembleRelease publishReleasePublicationToGitHubPackagesRepository -c settings.gradle
run: ./gradlew assembleRelease publishReleasePublicationToGitHubPackagesRepository -c settings.gradle.kts

# To publish to Sonatype
# ./gradlew publishReleasePublicationToSnapshotRepository
Expand Down
29 changes: 0 additions & 29 deletions build.gradle

This file was deleted.

29 changes: 29 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.android.library) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.kotlinx.kover) apply false
alias(libs.plugins.detekt) apply false
}

extra.apply {
// Android SDK and tools
set("min_sdk_version", 21)
set("target_sdk_version", 34)
set("compile_sdk_version", 34)
}

apply(from = "$rootDir/config/versioning.gradle")
apply(from = "$rootDir/config/maven.gradle")

allprojects {
group = "net.nicbell.emveeaye"
version = rootProject.extra.get("emveeaye_version").toString()
}

apply(from = "$rootDir/config/kover.gradle")

subprojects {
apply(from = "$rootDir/config/detekt.gradle")
}
25 changes: 25 additions & 0 deletions config/codecoverage-template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<html>
<head>
<title>Code Coverage</title>
<link rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu"
crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="page-header">
<h1>Code Coverage</h1>
</div>
<p class="lead">Code coverage reports for each module. <span class="glyphicon glyphicon glyphicon-remove text-danger" aria-hidden="true"></span> indicates no report available.</p>
<table class="table table-striped table-bordered">
<tr>
<th width="60%">Module</th>
<th>Coverage Report</th>
<th>Coverage</th>
</tr>
$codeQuality
</table>
</div>
</body>
</html>
148 changes: 79 additions & 69 deletions config/kover.gradle
Original file line number Diff line number Diff line change
@@ -1,103 +1,113 @@
import groovy.xml.XmlSlurper

apply plugin: 'org.jetbrains.kotlinx.kover'

def koverExcludes = ["*BuildConfig"]
def koverIgnoredProjects = []

koverMerged {
enable()
filters {
classes {
excludes.addAll(koverExcludes)
}
private static boolean isAndroidModule(Project project) {
boolean isAndroidLibrary = project.plugins.hasPlugin('com.android.library')
boolean isAndroidApp = project.plugins.hasPlugin('com.android.application')
return isAndroidLibrary || isAndroidApp
}

// Root / merged report
koverReport {
dependencies {
project.subprojects
.findAll { it.file("build.gradle").exists() && !koverIgnoredProjects.contains(it.name) }
.forEach { module -> kover(project(":${module.name}")) }
}
verify {
rule {
enabled = true
name = "Minimum coverage"
target = 'ALL'
bound {
minValue = 75
maxValue = 100
counter = 'LINE' // change coverage metric to evaluate (LINE, INSTRUCTION, BRANCH)
valueType = 'COVERED_PERCENTAGE'
}
}

filters {
excludes { classes(koverExcludes) }
}
}

subprojects {
apply plugin: "kover"
kover {
filters {
classes {
excludes.addAll(koverExcludes)
// Sub-project reports
subprojects { proj ->
if (koverIgnoredProjects.contains(proj.name)) return

apply plugin: 'org.jetbrains.kotlinx.kover'

afterEvaluate {
koverReport {
filters {
excludes { classes(koverExcludes) }
}
defaults {
if (isAndroidModule(proj)) {
mergeWith("debug")
}
}
}
instrumentation {
excludeTasks.add "testReleaseUnitTest"
// exclude testReleaseUnitTest from instrumentation
}
}
}


// Creates user friendly report per module
// ./gradlew koverXmlReport koverHtmlReport
// ./gradlew koverDump -q
def magenta = "\u001B[35m"
def normal = "\u001B[0m"

tasks.register("koverDump") {
dependsOn 'koverMergedReport'
doLast {
println "${magenta}Kover Console Dump${normal}"

def slurp = new groovy.xml.XmlSlurper()
slurp.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false)
slurp.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false)

def reportFile = file("${buildDir}/reports/kover/merged/xml/report.xml")
def reportParsed = slurp.parseText(reportFile.getText('UTF-8'))

reportParsed.'*'
.findAll { it.name() == 'counter' }
.collect { counter ->
int percentage = counter.@covered.toInteger() / (counter.@missed.toInteger() + counter.@covered.toInteger()) * 100
println "Coverage ${[email protected]()} $percentage%"
println "- Covered ${[email protected]()}/${[email protected]() + [email protected]()}"
}
println "\u001B[35mKover Console Dump\u001B[0m"

def codeQualityTemplate = new File(projectDir, "config/codecoverage-template.html").text
def reportHtml = ""
def metrics = ""
def coverageType = "INSTRUCTION"

// Modules
project.subprojects.findAll { it.file("build.gradle").exists() }.forEach { module ->
def moduleReportFile = file("${module.buildDir}/reports/kover/xml/report.xml")
int percentage = 0

if (moduleReportFile.exists()) {
def moduleReportParsed = slurp.parseText(moduleReportFile.getText('UTF-8'))

moduleReportParsed.'*'
.findAll { it.name() == 'counter' && it.@type.toString() == "INSTRUCTION" }
.collect { counter ->
percentage = counter.@covered.toInteger() / (counter.@missed.toInteger() + counter.@covered.toInteger()) * 100
}
metrics += "code-coverage${module.path} $percentage\n"
}
reportHtml += getModuleReportHtml(module, moduleReportFile.exists(), percentage)
def percentage = getPercentage(module, "/reports/kover/", coverageType)
reportHtml += getCoverageHtml(module, "/reports/kover/", percentage)
metrics += percentage != null ? "code-coverage${module.path} ${String.format("%.2f", percentage)}\n" : ""
}
// Merged report
def percentage = getPercentage(project, "/reports/kover/", coverageType)
reportHtml += getCoverageHtml(project, "/reports/kover/", percentage)

new File(projectDir, "build/reports").mkdirs() // in-case the directory doesn't exist.
new File(projectDir, "build/reports/metrics.txt").text = metrics
new File(projectDir, "build/reports/codecoverage.html").text = codeQualityTemplate.replace("\$codeQuality", reportHtml)
new File(projectDir, "build/reports/metrics.txt").text = metrics
}
}

private static String getModuleReportHtml(Project module, Boolean hasReport, int percentage) {
def modulePath = new File(module.rootDir, "build/reports/").relativePath(module.projectDir)
private static Double getPercentage(Project module, String reportPath, coverageType) {
def reportFile = new File(module.buildDir, reportPath + "report.xml")

if (reportFile.exists()) {
def slurp = new XmlSlurper()
slurp.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false)
slurp.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false)
def moduleReportParsed = slurp.parseText(reportFile.getText('UTF-8'))
double percentage = 0

moduleReportParsed.'*'.findAll { it.name() == 'counter' && it.@type.toString() == coverageType }.collect { counter ->
if (counter.@covered.toInteger() > 0) {
percentage = counter.@covered.toInteger() / (counter.@missed.toInteger() + counter.@covered.toInteger()) * 100
}
if (module.path != ":") {
println("${String.format("%.2f", percentage)}% \t - ${module.path} (${module.name})")
} else {
println("Total Coverage: ${String.format("%.2f", percentage)}%")
}
}
return percentage
} else {
return null
}
}

private static GString getCoverageHtml(Project module, String reportPath, Double percentage) {
if (percentage != null) {
def htmlPath = new File(module.rootProject.buildDir, "reports")
.relativePath(new File(module.buildDir, reportPath + "html/index.html"))

if (hasReport) {
return "<tr><td><code>${module.path}</code></td>" +
"<td><a href=\"$modulePath/build/reports/kover/html/index.html\">Report</a></td><td>$percentage%</td></tr>"
"<td><a href=\"${htmlPath}\">Report</a></td><td>${String.format("%.2f", percentage)}%</td></tr>"
} else {
return "<tr><td><code>${module.path}</code></td>" +
"<td><span class=\"glyphicon glyphicon glyphicon-remove text-danger\" aria-hidden=\"true\"></span></td>" +
"<td><span class=\"glyphicon glyphicon glyphicon-minus \" aria-hidden=\"true\"></span></td></tr>"
}
}
}
4 changes: 2 additions & 2 deletions emveeaye-test/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
alias libs.plugins.android.library
alias libs.plugins.kotlin.android
id 'maven-publish'
id 'signing'
}
Expand Down
4 changes: 2 additions & 2 deletions emveeaye/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
alias libs.plugins.android.library
alias libs.plugins.kotlin.android
id 'kotlin-parcelize'
id 'maven-publish'
id 'signing'
Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ android-application = { id = "com.android.application", version.ref = "agp" }
android-library = { id = "com.android.library", version.ref = "agp" }
detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlinx-kover = { id = "org.jetbrains.kotlinx.kover", version = "0.6.1" }
kotlinx-kover = { id = "org.jetbrains.kotlinx.kover", version = "0.7.3" }

[bundles]
4 changes: 2 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Tue Apr 18 20:23:05 CEST 2023
#Fri Nov 17 09:18:37 CET 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
4 changes: 2 additions & 2 deletions settings.gradle → settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ dependencyResolutionManagement {
}
}
rootProject.name = "EmVeeAye"
include ':emveeaye'
include ':emveeaye-test'
include(":emveeaye")
include(":emveeaye-test")

0 comments on commit 57c72f2

Please sign in to comment.