From 4e91e0712177d915ed16e1208810a39682534cf9 Mon Sep 17 00:00:00 2001 From: Nico Piel Date: Wed, 28 Oct 2026 23:19:23 +0100 Subject: [PATCH 1/3] Merge unit and smoke-test coverage in CI CI already ran the unit tests with JaCoCo but left the data inside the builder image. Export it, record coverage of the server under the smoke tests too, and merge both into one report. - Bump JaCoCo to 0.8.14: the smoke-test images run Java 21, which 0.8.8 predates. stageCoverage collects the unit-test data plus the agent and CLI into build/coverage, which the Dockerfile now exports. - ci/coverage.compose.yml attaches the agent when JACOCO_AGENT is set. configure-from-env splits VMOPTIONS on commas, so the agent gets only destfile. run-configuration.sh stops the server with a long timeout so the agent can write its data on shutdown. - ci/coverage-report.sh merges everything against the distribution jars the smoke tests ran, limited to our own jars. Signed-off-by: Nico Piel --- .dockerignore | 8 +++ .github/workflows/build.yaml | 52 ++++++++++++++++ .gitignore | 1 + Dockerfile | 5 +- build.gradle | 32 +++++++++- ci/README.md | 14 +++++ ci/coverage-report.sh | 52 ++++++++++++++++ ci/coverage.compose.yml | 12 ++++ ci/run-configuration.sh | 14 ++++- gradle/libs.versions.toml | 3 + gradle/verification-metadata.xml | 102 +++++++++++++++++-------------- 11 files changed, 245 insertions(+), 50 deletions(-) create mode 100755 ci/coverage-report.sh create mode 100644 ci/coverage.compose.yml diff --git a/.dockerignore b/.dockerignore index 47119def9..d028c2a4c 100644 --- a/.dockerignore +++ b/.dockerignore @@ -40,6 +40,11 @@ **/gradle-app.setting !**/gradle-wrapper.jar +############################## +## install4j +############################## +**/*.install4j~ + ############################## ## IntelliJ ############################## @@ -118,6 +123,9 @@ exports MapUtilTestDB testconf +ci/test-results +ci/coverage + client/logs client/classes client/dist diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index cc3954b35..609b90039 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -12,6 +12,7 @@ on: # miss each other's build cache. env: GRADLE_BUILD_ARGS: ${{ github.ref != 'refs/heads/main' && '-PdisableSigning=true -Pcoverage=true' || '' }} + COVERAGE: ${{ github.ref != 'refs/heads/main' }} jobs: build: @@ -56,6 +57,13 @@ jobs: name: oie-build path: openintegrationengine.tar.gz + - name: Upload unit coverage + if: env.COVERAGE == 'true' + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: coverage-unit + path: docker-build-output/app/build/coverage + - name: Stage Test Results if: (!cancelled()) run: | @@ -91,13 +99,28 @@ jobs: - name: Expose GitHub Actions runtime for buildx cache uses: crazy-max/ghaction-github-runtime@04d248b84655b509d8c44dc1d6f990c879747487 # v4.0.0 + - name: Download JaCoCo agent + if: env.COVERAGE == 'true' + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + name: coverage-unit + path: coverage-unit + # Read-only: the build job populates this cache, and concurrent writers # from the matrix would just fight over the same scope. - name: Run integration tests env: EXTRA_BUILDX_ARGS: --cache-from type=gha,scope=oie-build + JACOCO_AGENT: ${{ env.COVERAGE == 'true' && 'coverage-unit/jacocoagent.jar' || '' }} run: ci/runtests.sh ${{ matrix.configuration }} + - name: Upload smoke-test coverage + if: (!cancelled()) && env.COVERAGE == 'true' + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: coverage-smoke-${{ matrix.configuration }} + path: ci/coverage/*.exec + - name: Upload Test Results if: (!cancelled()) uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 @@ -123,3 +146,32 @@ jobs: name: Test Results pattern: Test Results (*) delete-merged: true + + coverage: + needs: [build, integration-test] + if: (!cancelled()) && github.ref != 'refs/heads/main' + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Download build + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + name: oie-build + path: artifacts + + - name: Download coverage data + uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 + with: + pattern: coverage-* + path: artifacts + + - name: Merge unit and smoke-test coverage + run: ci/coverage-report.sh artifacts coverage-report + + - name: Upload coverage report + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: Coverage Report + path: coverage-report diff --git a/.gitignore b/.gitignore index 17542916c..8c90af1e5 100644 --- a/.gitignore +++ b/.gitignore @@ -122,6 +122,7 @@ donkey/donkey-test # /ci /ci/test-results/ +/ci/coverage/ # /client/ /client/logs diff --git a/Dockerfile b/Dockerfile index a59672f5e..ab46dfbe2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -42,7 +42,8 @@ RUN mkdir -p /home/ubuntu/.gradle RUN --mount=type=cache,target=/home/ubuntu/.gradle/caches,sharing=locked,uid=1000,gid=1000 \ --mount=type=cache,target=/home/ubuntu/.gradle/wrapper,sharing=locked,uid=1000,gid=1000 \ source "$HOME/.sdkman/bin/sdkman-init.sh" \ - && ./gradlew --no-daemon build :smoketest:installHarnessDist ${GRADLE_BUILD_ARGS} + && ./gradlew --no-daemon build :smoketest:installHarnessDist stageCoverage ${GRADLE_BUILD_ARGS} \ + && mkdir -p build/coverage # Stage 1c: Present artifacts for export if not running within docker FROM scratch AS build-output-export @@ -51,6 +52,8 @@ COPY --from=builder /app/client/build/test-results /app/client/build/test-result COPY --from=builder /app/command/build/test-results /app/command/build/test-results/ COPY --from=builder /app/donkey/build/test-results /app/donkey/build/test-results/ COPY --from=builder /app/server/build/test-results /app/server/build/test-results/ +# empty unless built with -Pcoverage=true +COPY --from=builder /app/build/coverage /app/build/coverage/ # Stage 1d: Smoke Test Harness FROM eclipse-temurin:21.0.9_10-jre-noble AS smoketest-harness diff --git a/build.gradle b/build.gradle index d35520992..2d4c52930 100644 --- a/build.gradle +++ b/build.gradle @@ -263,7 +263,7 @@ subprojects { if (rootProject.coverageEnabled) { apply plugin: 'jacoco' - jacoco { toolVersion = '0.8.8' } + jacoco { toolVersion = libs.versions.jacoco.get() } tasks.withType(Test).configureEach { finalizedBy tasks.named('jacocoTestReport') } tasks.named('jacocoTestReport') { reports.xml.required = true @@ -318,6 +318,36 @@ tasks.register('test') { dependsOn ':donkey:test', ':server:test', ':client:test', ':command:test' } +// Collects what CI needs to merge unit and smoke-test coverage: the unit +// test execution data, the agent for the smoke-test server and the CLI +// that merges and reports. See ci/README.md. +def coverageTools = configurations.create('coverageTools') { transitive = false } +dependencies { + add('coverageTools', variantOf(libs.jacoco.agent) { classifier('runtime') }) + add('coverageTools', variantOf(libs.jacoco.cli) { classifier('nodeps') }) +} +repositories { + mavenCentral() +} + +tasks.register('stageCoverage', Sync) { + group = 'verification' + description = 'Stages unit-test JaCoCo data and the JaCoCo agent and CLI into build/coverage.' + onlyIf { rootProject.coverageEnabled } + mustRunAfter ':donkey:test', ':server:test', ':client:test', ':command:test' + into layout.buildDirectory.dir('coverage') + from(coverageTools) { + rename { it.startsWith('org.jacoco.agent') ? 'jacocoagent.jar' : 'jacococli.jar' } + } + ['donkey', 'server', 'client', 'command'].each { name -> + from(project(":${name}").layout.buildDirectory.dir('jacoco')) { + include '*.exec' + into 'unit' + rename { "${name}-${it}" } + } + } +} + tasks.register('clean') { group = 'build' description = 'Cleans every module.' diff --git a/ci/README.md b/ci/README.md index 1fd3f24e9..088f30dc1 100644 --- a/ci/README.md +++ b/ci/README.md @@ -140,3 +140,17 @@ started yourself logged a generated password on its first boot: JUnit XML results are written to `ci/test-results//` when using `ci/runtests.sh`. + +## Coverage + +CI merges the unit-test and smoke-test coverage into one JaCoCo report (the +`Coverage Report` artifact). To record smoke-test coverage locally, build with +coverage and point `JACOCO_AGENT` at the staged agent: + +```sh +./gradlew build stageCoverage -Pcoverage=true +JACOCO_AGENT=build/coverage/jacocoagent.jar ci/runtests.sh alpine-temurin21-derby +``` + +Each configuration writes `ci/coverage/.exec` when its server stops. +In CI, `ci/coverage-report.sh` then merges them with the unit-test data. diff --git a/ci/coverage-report.sh b/ci/coverage-report.sh new file mode 100755 index 000000000..391c7a48a --- /dev/null +++ b/ci/coverage-report.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# Merges unit-test and smoke-test JaCoCo data into one report. +# +# holds what the CI build uploads: openintegrationengine.tar.gz +# (the distribution the smoke tests ran), coverage-unit/ (unit-test data, +# jacococli.jar) and coverage-smoke-*/ (one data file per configuration). +set -euo pipefail + +if [[ $# -ne 2 ]]; then + echo "Usage: $0 " >&2 + exit 2 +fi + +artifacts="$(realpath "$1")" +mkdir -p "$2" +output="$(realpath "$2")" +cd "$(dirname "${BASH_SOURCE[0]}")/.." +cli="$artifacts/coverage-unit/jacococli.jar" + +tmp="$(mktemp -d)" +trap 'rm -rf "$tmp"' EXIT +tar xzf "$artifacts/openintegrationengine.tar.gz" -C "$tmp" +dist="$tmp/openintegrationengine" + +shopt -s nullglob +java -jar "$cli" merge \ + "$artifacts"/coverage-unit/unit/*.exec \ + "$artifacts"/coverage-smoke-*/*.exec \ + --destfile "$output/merged.exec" + +# Only our own jars: third-party jars would add their classes to the report, +# and some of them hold originals of classes we patch in mirth-server.jar. +classfiles=() +for jar in "$dist"/mirth-*-launcher.jar \ + "$dist"/server-lib/mirth-*.jar \ + "$dist"/server-lib/donkey/donkey-*.jar \ + "$dist"/client-lib/mirth-client.jar \ + "$dist"/cli-lib/mirth-cli.jar \ + "$dist"/extensions/*/*.jar; do + classfiles+=(--classfiles "$jar") +done + +sourcefiles=() +for dir in donkey server client command; do + sourcefiles+=(--sourcefiles "$dir/src/main/java") +done + +java -jar "$cli" report "$output/merged.exec" \ + "${classfiles[@]}" "${sourcefiles[@]}" \ + --name "Open Integration Engine (unit + smoke tests)" \ + --xml "$output/coverage.xml" \ + --html "$output/html" diff --git a/ci/coverage.compose.yml b/ci/coverage.compose.yml new file mode 100644 index 000000000..5e81da0d3 --- /dev/null +++ b/ci/coverage.compose.yml @@ -0,0 +1,12 @@ +# Overlay that records JaCoCo coverage of the server under test. Added by +# ci/run-configuration.sh when JACOCO_AGENT points at a jacocoagent.jar. +services: + oie: + environment: + # configure-from-env splits VMOPTIONS on commas, so the agent gets a + # single option and records every class; ci/coverage-report.sh only + # reports our own. The data file is written when the JVM exits. + VMOPTIONS: -javaagent:/jacoco/jacocoagent.jar=destfile=/coverage/${OIE_CONFIGURATION}.exec + volumes: + - ${JACOCO_AGENT}:/jacoco/jacocoagent.jar:ro + - ${WORKSPACE}/ci/coverage:/coverage diff --git a/ci/run-configuration.sh b/ci/run-configuration.sh index 7881f57bb..915f73dcb 100755 --- a/ci/run-configuration.sh +++ b/ci/run-configuration.sh @@ -23,9 +23,21 @@ export HOST_UID="$(id -u)" export HOST_GID="$(id -g)" mkdir -p "$WORKSPACE/ci/test-results" -compose=(docker compose -f "$1" -f ci/harness.compose.yml -p "oie-ci-${OIE_CONFIGURATION//[^a-z0-9-]/-}-$$") +compose=(docker compose -f "$1" -f ci/harness.compose.yml) +if [[ -n "${JACOCO_AGENT:-}" ]]; then + export JACOCO_AGENT="$(realpath "$JACOCO_AGENT")" + mkdir -p "$WORKSPACE/ci/coverage" + # The server runs as its own user, whose UID differs between the images. + chmod 777 "$WORKSPACE/ci/coverage" + compose+=(-f ci/coverage.compose.yml) +fi +compose+=(-p "oie-ci-${OIE_CONFIGURATION//[^a-z0-9-]/-}-$$") cleanup() { + if [[ -n "${JACOCO_AGENT:-}" ]]; then + # Give the server time to shut down cleanly so JaCoCo writes its data file. + "${compose[@]}" stop -t 120 oie || true + fi "${compose[@]}" down -v --remove-orphans || true } trap cleanup EXIT diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bb6dc1f29..d8b33ef1d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,6 +22,7 @@ hk2 = "2.4.0-b31" httpclient = "4.5.13" itext = "2.1.7" jackson = "2.18.11" +jacoco = "0.8.14" jasper = "8.5.70" jaxb-ri = "2.4.0-b180725.0644" jaxws-ri = "2.3.0.2" @@ -146,6 +147,8 @@ jackson-databind = { module = "com.fasterxml.jackson.core:jackson-databind", ver jackson-dataformat-cbor = { module = "com.fasterxml.jackson.dataformat:jackson-dataformat-cbor", version.ref = "jackson" } jackson-dataformat-yaml = { module = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml", version.ref = "jackson" } jackson-datatype-jsr310 = { module = "com.fasterxml.jackson.datatype:jackson-datatype-jsr310", version.ref = "jackson" } +jacoco-agent = { module = "org.jacoco:org.jacoco.agent", version.ref = "jacoco" } +jacoco-cli = { module = "org.jacoco:org.jacoco.cli", version.ref = "jacoco" } jakarta-activation = { module = "com.sun.activation:jakarta.activation", version = "1.2.1" } jakarta-mail = { module = "com.sun.mail:jakarta.mail", version = "1.6.8" } jasper-apache-el = { module = "org.mortbay.jasper:apache-el", version.ref = "jasper" } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 9895ca7af..01d9ef198 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2510,41 +2510,52 @@ - - - + + + - - + + + + + - - - + + + + + + - - + + + + - - - + + + + + + - - - + + + - - + + - - - + + + - - + + @@ -2851,14 +2862,6 @@ - - - - - - - - @@ -2867,12 +2870,12 @@ - - - + + + - - + + @@ -2883,12 +2886,9 @@ - - - - - - + + + @@ -2899,12 +2899,12 @@ - - - + + + - - + + @@ -2915,6 +2915,14 @@ + + + + + + + + From b470e38026dcf7fa245a3500a42f2c03e0466d2c Mon Sep 17 00:00:00 2001 From: Nico Piel Date: Wed, 28 Oct 2026 23:37:11 +0100 Subject: [PATCH 2/3] Harden the coverage merge against missing data - coverage-report.sh fails when the unit-test or smoke-test data or the distribution jars are missing, instead of publishing a partial report. - The coverage job no longer runs after a failed build. - run-configuration.sh removes an earlier run's data file, since the agent appends to it. Signed-off-by: Nico Piel --- .github/workflows/build.yaml | 2 +- ci/coverage-report.sh | 16 ++++++++++++---- ci/run-configuration.sh | 2 ++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 609b90039..d2a459ea5 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -149,7 +149,7 @@ jobs: coverage: needs: [build, integration-test] - if: (!cancelled()) && github.ref != 'refs/heads/main' + if: (!cancelled()) && needs.build.result == 'success' && github.ref != 'refs/heads/main' runs-on: ubuntu-latest steps: diff --git a/ci/coverage-report.sh b/ci/coverage-report.sh index 391c7a48a..e37ad046a 100755 --- a/ci/coverage-report.sh +++ b/ci/coverage-report.sh @@ -23,10 +23,14 @@ tar xzf "$artifacts/openintegrationengine.tar.gz" -C "$tmp" dist="$tmp/openintegrationengine" shopt -s nullglob -java -jar "$cli" merge \ - "$artifacts"/coverage-unit/unit/*.exec \ - "$artifacts"/coverage-smoke-*/*.exec \ - --destfile "$output/merged.exec" +unit=("$artifacts"/coverage-unit/unit/*.exec) +smoke=("$artifacts"/coverage-smoke-*/*.exec) +echo "Merging ${#unit[@]} unit-test and ${#smoke[@]} smoke-test data files" +if [[ ${#unit[@]} -eq 0 || ${#smoke[@]} -eq 0 ]]; then + echo "Missing unit-test or smoke-test coverage data" >&2 + exit 1 +fi +java -jar "$cli" merge "${unit[@]}" "${smoke[@]}" --destfile "$output/merged.exec" # Only our own jars: third-party jars would add their classes to the report, # and some of them hold originals of classes we patch in mirth-server.jar. @@ -39,6 +43,10 @@ for jar in "$dist"/mirth-*-launcher.jar \ "$dist"/extensions/*/*.jar; do classfiles+=(--classfiles "$jar") done +if [[ ${#classfiles[@]} -eq 0 ]]; then + echo "No jars found in the distribution" >&2 + exit 1 +fi sourcefiles=() for dir in donkey server client command; do diff --git a/ci/run-configuration.sh b/ci/run-configuration.sh index 915f73dcb..ee01e39cb 100755 --- a/ci/run-configuration.sh +++ b/ci/run-configuration.sh @@ -29,6 +29,8 @@ if [[ -n "${JACOCO_AGENT:-}" ]]; then mkdir -p "$WORKSPACE/ci/coverage" # The server runs as its own user, whose UID differs between the images. chmod 777 "$WORKSPACE/ci/coverage" + # The agent appends, so start from a clean file. + rm -f "$WORKSPACE/ci/coverage/$OIE_CONFIGURATION.exec" compose+=(-f ci/coverage.compose.yml) fi compose+=(-p "oie-ci-${OIE_CONFIGURATION//[^a-z0-9-]/-}-$$") From 3bd606d15ad06deffb34de38afcdbab27edc054e Mon Sep 17 00:00:00 2001 From: Nico Piel Date: Thu, 29 Oct 2026 14:09:49 +0100 Subject: [PATCH 3/3] Analyze the merged coverage with Sonar Add the SonarQube Gradle plugin and point every module at the merged report, so `./gradlew sonar -Dsonar.host.url=... -Dsonar.token=...` picks up unit and smoke-test coverage. The property is set per module because JaCoCo's per-module default would otherwise override it. ci/coverage-report.sh now works on the local build layout (server/setup, build/coverage, ci/coverage), so anyone can produce the report; the CI job lays its artifacts out the same way. Signed-off-by: Nico Piel --- .github/workflows/build.yaml | 10 ++++++-- build.gradle | 19 ++++++++++++++++ ci/README.md | 14 +++++++++--- ci/coverage-report.sh | 32 +++++++++----------------- gradle/libs.versions.toml | 1 + gradle/verification-metadata.xml | 39 ++++++++++++++++++++++++++++++++ 6 files changed, 89 insertions(+), 26 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index d2a459ea5..c586d1da4 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -167,11 +167,17 @@ jobs: pattern: coverage-* path: artifacts + # Lay the artifacts out as a local build would leave them. - name: Merge unit and smoke-test coverage - run: ci/coverage-report.sh artifacts coverage-report + run: | + mkdir -p server build ci/coverage + tar xzf artifacts/openintegrationengine.tar.gz -C server --transform 's|^openintegrationengine/|setup/|' + cp -r artifacts/coverage-unit build/coverage + cp artifacts/coverage-smoke-*/*.exec ci/coverage/ + ci/coverage-report.sh - name: Upload coverage report uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 with: name: Coverage Report - path: coverage-report + path: build/coverage/report diff --git a/build.gradle b/build.gradle index 2d4c52930..1f87954ef 100644 --- a/build.gradle +++ b/build.gradle @@ -45,6 +45,25 @@ plugins { // vulnerability scanning: ./gradlew dependencyCheckAggregate // (replaces the old standalone dependency-check.xml Ant entry point) alias(libs.plugins.owasp.dependencycheck) + // static analysis: ./gradlew sonar -Dsonar.host.url=... -Dsonar.token=... + alias(libs.plugins.sonarqube) +} + +sonar { + properties { + property 'sonar.projectKey', 'oie' + property 'sonar.projectName', 'Open Integration Engine' + } +} + +allprojects { + sonar { + properties { + // unit and smoke-test coverage merged by ci/coverage-report.sh; + // set on every module, or JaCoCo's per-module default wins + property 'sonar.coverage.jacoco.xmlReportPaths', rootProject.file('build/coverage/report/coverage.xml').path + } + } } dependencyCheck { diff --git a/ci/README.md b/ci/README.md index 088f30dc1..e6851f31c 100644 --- a/ci/README.md +++ b/ci/README.md @@ -144,13 +144,21 @@ JUnit XML results are written to `ci/test-results//` when using ## Coverage CI merges the unit-test and smoke-test coverage into one JaCoCo report (the -`Coverage Report` artifact). To record smoke-test coverage locally, build with -coverage and point `JACOCO_AGENT` at the staged agent: +`Coverage Report` artifact). To produce the same report locally, build with +coverage, run the smoke tests with the staged agent, then merge: ```sh ./gradlew build stageCoverage -Pcoverage=true JACOCO_AGENT=build/coverage/jacocoagent.jar ci/runtests.sh alpine-temurin21-derby +ci/coverage-report.sh ``` Each configuration writes `ci/coverage/.exec` when its server stops. -In CI, `ci/coverage-report.sh` then merges them with the unit-test data. +The merged report lands in `build/coverage/report`, where `./gradlew sonar` reads it: + +```sh +./gradlew sonar -Dsonar.host.url=... -Dsonar.token=... +``` + +Override the project key with `-Dsonar.projectKey=...`; SonarCloud also needs +`-Dsonar.organization=...`. diff --git a/ci/coverage-report.sh b/ci/coverage-report.sh index e37ad046a..413687bd5 100755 --- a/ci/coverage-report.sh +++ b/ci/coverage-report.sh @@ -1,30 +1,20 @@ #!/usr/bin/env bash -# Merges unit-test and smoke-test JaCoCo data into one report. -# -# holds what the CI build uploads: openintegrationengine.tar.gz -# (the distribution the smoke tests ran), coverage-unit/ (unit-test data, -# jacococli.jar) and coverage-smoke-*/ (one data file per configuration). +# Merges unit-test and smoke-test JaCoCo data into build/coverage/report, +# which `./gradlew sonar` picks up. Expects, from the same commit: +# ./gradlew build stageCoverage -Pcoverage=true (server/setup, build/coverage) +# JACOCO_AGENT=build/coverage/jacocoagent.jar ci/runtests.sh +# (ci/coverage/*.exec) set -euo pipefail -if [[ $# -ne 2 ]]; then - echo "Usage: $0 " >&2 - exit 2 -fi - -artifacts="$(realpath "$1")" -mkdir -p "$2" -output="$(realpath "$2")" cd "$(dirname "${BASH_SOURCE[0]}")/.." -cli="$artifacts/coverage-unit/jacococli.jar" - -tmp="$(mktemp -d)" -trap 'rm -rf "$tmp"' EXIT -tar xzf "$artifacts/openintegrationengine.tar.gz" -C "$tmp" -dist="$tmp/openintegrationengine" +cli=build/coverage/jacococli.jar +dist=server/setup +output=build/coverage/report +mkdir -p "$output" shopt -s nullglob -unit=("$artifacts"/coverage-unit/unit/*.exec) -smoke=("$artifacts"/coverage-smoke-*/*.exec) +unit=(build/coverage/unit/*.exec) +smoke=(ci/coverage/*.exec) echo "Merging ${#unit[@]} unit-test and ${#smoke[@]} smoke-test data files" if [[ ${#unit[@]} -eq 0 || ${#smoke[@]} -eq 0 ]]; then echo "Missing unit-test or smoke-test coverage data" >&2 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d8b33ef1d..7d8c9b5df 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -673,3 +673,4 @@ server-test = [ [plugins] owasp-dependencycheck = { id = "org.owasp.dependencycheck", version = "12.2.2" } +sonarqube = { id = "org.sonarqube", version = "7.5.0.8588" } diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 01d9ef198..ddf7dedfc 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -2739,6 +2739,14 @@ + + + + + + + + @@ -3065,6 +3073,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +