diff --git a/.github/workflows/jacoco_report.yml b/.github/workflows/jacoco_report.yml index e4679364..c6974136 100644 --- a/.github/workflows/jacoco_report.yml +++ b/.github/workflows/jacoco_report.yml @@ -14,24 +14,65 @@ # limitations under the License. # -name: JaCoCo Report +name: CI JaCoCo Report on: pull_request: branches: [ master ] - types: [ opened, edited, synchronize, reopened ] + +permissions: + contents: read + +concurrency: + group: jacoco-report-${{ github.ref }} + cancel-in-progress: true env: - scalaLong: 2.13.11 - scalaShort: 2.13 - coverage-overall: 57.0 - coverage-changed-files: 80.0 - check-overall-coverages: true + # hint: "group thresholds" are in format: 'overall*changed-files-average*per-changed-file' + REPORT_GROUPS: | + - name: faDbCore + paths: + - '**/core/target/**/jacoco-report/jacoco.xml' + thresholds: '61*80*0' + - name: faDBDoobie + paths: + - '**/doobie/target/**/jacoco-report/jacoco.xml' + thresholds: '67*80*0' + - name: faDBSlick + paths: + - '**/slick/target/**/jacoco-report/jacoco.xml' + thresholds: '39*80*0' jobs: - build-test-and-measure: - name: Build, Test and Measure + detect: + name: Detect Changed Files + runs-on: ubuntu-latest + timeout-minutes: 2 + outputs: + scala_changed: ${{ steps.filter.outputs.scala }} + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 + with: + persist-credentials: false + fetch-depth: 0 + - uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d + id: filter + with: + token: "" + filters: | + scala: + - '**/*.scala' + - '!project/**' + + jacoco-report: + name: JaCoCo Report + needs: detect + if: needs.detect.outputs.scala_changed == 'true' runs-on: ubuntu-latest + permissions: + contents: read + issues: write + pull-requests: write services: postgres: @@ -52,6 +93,7 @@ jobs: uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 with: persist-credentials: false + fetch-depth: 0 - name: Setup Scala uses: olafurpg/setup-scala@32ffa16635ff8f19cc21ea253a987f0fdf29844c @@ -63,107 +105,27 @@ jobs: - name: Build and run tests continue-on-error: true - id: jacocorun - run: sbt ++${{env.scalaLong}} jacoco - - - name: Add coverage to PR (core) - if: steps.jacocorun.outcome == 'success' - id: jacoco-core - uses: madrapps/jacoco-report@50d3aff4548aa991e6753342d9ba291084e63848 - with: - paths: ${{ github.workspace }}/core/target/scala-${{ env.scalaShort }}/jacoco/report/jacoco.xml - token: ${{ secrets.GITHUB_TOKEN }} - min-coverage-overall: ${{ env.coverage-overall }} - min-coverage-changed-files: ${{ env.coverage-changed-files }} - title: JaCoCo `core` module code coverage report - scala ${{ env.scalaLong }} - update-comment: true + run: sbt jacoco - - name: Add coverage to PR (doobie) - if: steps.jacocorun.outcome == 'success' - id: jacoco-doobie - uses: madrapps/jacoco-report@50d3aff4548aa991e6753342d9ba291084e63848 + - name: Setup Python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 with: - paths: ${{ github.workspace }}/doobie/target/scala-${{ env.scalaShort }}/jacoco/report/jacoco.xml - token: ${{ secrets.GITHUB_TOKEN }} - min-coverage-overall: ${{ env.coverage-overall }} - min-coverage-changed-files: ${{ env.coverage-changed-files }} - title: JaCoCo `doobie` module code coverage report - scala ${{ env.scalaLong }} - update-comment: true + python-version: '3.14' - - name: Add coverage to PR (slick) - if: steps.jacocorun.outcome == 'success' - id: jacoco-slick - uses: madrapps/jacoco-report@50d3aff4548aa991e6753342d9ba291084e63848 + - name: Add JaCoCo Report in PR comments + uses: MoranaApps/jacoco-report@5b6495430e6bb5fde0a6b7dd348fc8afc3aa86db with: - paths: ${{ github.workspace }}/slick/target/scala-${{ env.scalaShort }}/jacoco/report/jacoco.xml token: ${{ secrets.GITHUB_TOKEN }} - min-coverage-overall: ${{env.coverage-overall }} - min-coverage-changed-files: ${{ env.coverage-changed-files }} - title: JaCoCo `slick` module code coverage report - scala ${{ env.scalaLong }} - update-comment: true - - - name: Get the Coverage info - if: steps.jacocorun.outcome == 'success' - run: | - echo "Total `core` module coverage ${{ steps.jacoco-core.outputs.coverage-overall }}" - echo "Changed Files coverage ${{ steps.jacoco-core.outputs.coverage-changed-files }}" - echo "Total `doobie` module coverage ${{ steps.jacoco-doobie.outputs.coverage-overall }}" - echo "Changed Files coverage ${{ steps.jacoco-doobie.outputs.coverage-changed-files }}" - echo "Total `slick` module coverage ${{ steps.jacoco-slick.outputs.coverage-overall }}" - echo "Changed Files coverage ${{ steps.jacoco-slick.outputs.coverage-changed-files }}" - - - name: Fail PR if changed files coverage is less than ${{ env.coverage-changed-files }}% - if: steps.jacocorun.outcome == 'success' - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 - with: - script: | - const coverageCheckFailed = - Number('${{ steps.jacoco-core.outputs.coverage-changed-files }}') < Number('${{ env.coverage-changed-files }}') || - Number('${{ steps.jacoco-doobie.outputs.coverage-changed-files }}') < Number('${{ env.coverage-changed-files }}') || - Number('${{ steps.jacoco-slick.outputs.coverage-changed-files }}') < Number('${{ env.coverage-changed-files }}'); - if (coverageCheckFailed) { - core.setFailed('Changed files coverage is less than ${{ env.coverage-changed-files }}%!'); - } - - - name: Fail PR if overall files coverage is less than ${{ env.coverage-overall }}% - if: ${{ (steps.jacocorun.outcome == 'success') && (env.check-overall-coverages == 'true') }} - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 - with: - script: | - const coverageCheckFailed = - Number('${{ steps.jacoco-core.outputs.coverage-overall }}') < Number('${{ env.coverage-overall }}') || - Number('${{ steps.jacoco-doobie.outputs.coverage-overall }}') < Number('${{ env.coverage-overall }}') || - Number('${{ steps.jacoco-slick.outputs.coverage-overall }}') < Number('${{ env.coverage-overall }}'); - if (coverageCheckFailed) { - core.setFailed('Overall coverage is less than ${{ env.coverage-overall }}%!'); - } - - - name: Edit JaCoCo comments on build failure - if: steps.jacocorun.outcome != 'success' - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 - with: - script: | - const issue_number = context.issue.number; - const owner = context.repo.owner; - const repo = context.repo.repo; - const jacocoReportRegExp = /^### JaCoCo .* code coverage report .*/; - - const comments = await github.rest.issues.listComments({ - owner, - repo, - issue_number, - }); - - for (const comment of comments.data) { - const lines = comment.body.split('\n'); - if (lines.length > 0 && jacocoReportRegExp.test(lines[0])) { - await github.rest.issues.updateComment({ - owner, - repo, - comment_id: comment.id, - body: lines[0] + "\n\n### Build Failed", - }); - } - } - - core.setFailed('JaCoCo test coverage report generation failed, and related PR comments were updated.'); + global-thresholds: '0*80' + report-thresholds-default: '0*0*0' + skip-unchanged: 'true' + evaluate-unchanged: 'false' + report-groups: ${{ env.REPORT_GROUPS }} + + noop: + name: No Operation + needs: detect + if: needs.detect.outputs.scala_changed != 'true' + runs-on: ubuntu-latest + steps: + - run: echo "No changes in Scala related files — passing." diff --git a/.sbtrc b/.sbtrc index 952a4147..771ad3e1 100644 --- a/.sbtrc +++ b/.sbtrc @@ -25,5 +25,12 @@ alias test=; testOnly *UnitTests # * Integration tests alias testIT=; testOnly *IntegrationTests -# Project specific aliases +# JaCoCo aliases +alias jacoco=; jacocoOn; jacocoCore; jacocoDoobie; jacocoSlick; jacocoOff +alias jacocoOn=; set every jacocoPluginEnabled := true +alias jacocoOff=; set every jacocoPluginEnabled := false + +alias jacocoCore=; project faDbCore; clean; testOnly *UnitTests *IntegrationTests; jacocoReportAll +alias jacocoDoobie=; project faDBDoobie; clean; testOnly *UnitTests *IntegrationTests; jacocoReportAll +alias jacocoSlick=; project faDBSlick; clean; testOnly *UnitTests *IntegrationTests; jacocoReportAll diff --git a/build.sbt b/build.sbt index e75bc408..15e9cf4e 100644 --- a/build.sbt +++ b/build.sbt @@ -15,7 +15,6 @@ */ import Dependencies._ -import com.github.sbt.jacoco.report.JacocoReportSettings lazy val scala212 = "2.12.17" lazy val scala213 = "2.13.12" @@ -35,23 +34,12 @@ ThisBuild / printScalaVersion := { log.info(s"Local maven ${Resolver.mavenLocal}") } -lazy val commonJacocoReportSettings: JacocoReportSettings = JacocoReportSettings( - formats = Seq(JacocoReportFormats.HTML, JacocoReportFormats.XML) -) - -/** - * add `za.co.absa.db.fadb.naming.NamingConvention` to filter a class - * or `za.co.absa.db.fadb.naming.NamingConvention*` to filter the class and all related objects - */ -lazy val commonJacocoExcludes: Seq[String] = Seq( -) lazy val commonSettings = Seq( javacOptions ++= commonJavacOptions, scalacOptions ++= commonScalacOptions, Test / parallelExecution := false, (Compile / compile) := ((Compile / compile) dependsOn printScalaVersion).value, // printScalaVersion is run with compile - jacocoExcludes := commonJacocoExcludes, // to mitigate CVE-2022-31183 dependencyOverrides += "co.fs2" %% "fs2-core" % "3.2.11", dependencyOverrides += "co.fs2" %% "fs2-io" % "3.2.11", @@ -72,26 +60,26 @@ lazy val faDbCore = (project in file("core")) .settings( name := "core", libraryDependencies ++= coreDependencies(scalaVersion.value), - jacocoReportSettings := commonJacocoReportSettings.withTitle(s"fa-db:core Jacoco Report - scala:${scalaVersion.value}"), ) + .enablePlugins(JacocoFilterPlugin) lazy val faDBSlick = (project in file("slick")) .settings(commonSettings: _*) .settings( name := "slick", libraryDependencies ++= slickDependencies(scalaVersion.value), - jacocoReportSettings := commonJacocoReportSettings.withTitle(s"fa-db:slick Jacoco Report - scala:${scalaVersion.value}"), ) .dependsOn(faDbCore) + .enablePlugins(JacocoFilterPlugin) lazy val faDBDoobie = (project in file("doobie")) .settings(commonSettings: _*) .settings( name := "doobie", libraryDependencies ++= doobieDependencies(scalaVersion.value), - jacocoReportSettings := commonJacocoReportSettings.withTitle(s"fa-db:doobie Jacoco Report - scala:${scalaVersion.value}"), ) .dependsOn(faDbCore) + .enablePlugins(JacocoFilterPlugin) lazy val flywaySettings = project .enablePlugins(FlywayPlugin) diff --git a/jmf-rules.txt b/jmf-rules.txt new file mode 100644 index 00000000..e2a67f2e --- /dev/null +++ b/jmf-rules.txt @@ -0,0 +1,126 @@ +# jacoco-method-filter — Rules Template (Scala / sbt) +# [jmf:1.0.0] +# +# Syntax reference, pitfalls, examples, and workflows: docs/rules-reference.md +# +# ───────────────────────────────────────────────────────────────────────────── +# HOW TO USE +# ───────────────────────────────────────────────────────────────────────────── +# +# 1) Review the GLOBAL RULES below — they cover compiler-generated boilerplate. +# 2) Add project-specific patterns in the PROJECT RULES section. +# 3) Keep rules narrow; add id: labels so logs are readable. +# Every rule must have an id: