Skip to content

DNAlchemist/gitlab-code-quality-gradle-plugin

 
 

Repository files navigation

gitlab-code-quality-gradle-plugin

This Gradle plugin transforms XML reports produced by tools such as SpotBugs and Checkstyle into JSON in the format expected by GitLab, so that findings can be shown in the merge request code quality widget.

gitlab merge request widget

Usage

Step 1: Configure SpotBugs and/or Checkstyle

The plugin only reads XML produced by other tools. Configure the SpotBugs and/or Checkstyle Gradle plugins (or any setup that writes compatible XML) so reports exist before check runs.

Default input locations match the layout used by the official Gradle plugins: build/reports/spotbugs/main.xml and build/reports/checkstyle/main.xml. The SpotBugs Gradle plugin only emits XML when the XML report is explicitly enabled, so make sure your build does that:

spotbugs {
    // ...
}

tasks.named<com.github.spotbugs.snom.SpotBugsTask>("spotbugsMain") {
    reports.create("xml") { required.set(true) }
}

If your reports live elsewhere, override the generateGitLabCodeQualityReport task properties (see Advanced configuration).

Step 2: Apply this plugin

The plugin attaches to any project that has a JVM toolchain plugin applied — java, java-library, application, org.jetbrains.kotlin.jvm, etc. Add this plugin to your build.gradle.kts (or build.gradle):

plugins {
    java
    id("io.github.dnalchemist.gitlab-code-quality") version "1.1.0"
}

By default the plugin reads:

  • build/reports/spotbugs/main.xml

  • build/reports/checkstyle/main.xml

and writes:

  • build/gl-code-quality-report.json

when the check lifecycle runs (the generateGitLabCodeQualityReport task is attached to check).

If the XML files are missing or empty, the task still completes and logs that no report was found.

Note
build/gl-code-quality-report.json is always written, including when no findings are detected. In that case its content is an empty JSON array []. This keeps GitLab CI’s reports:codequality artifact pattern stable across runs — it does not fail an MR with "artifact not found" just because the build was clean. If you prefer "no file = no findings" semantics, delete the file in a CI step when the array is empty.

If you do not want the report task wired into check — for example when spotbugsMain runs with ignoreFailures = false and you want the GitLab JSON to be produced even when SpotBugs reports a failure — disable the auto-wiring and run the task explicitly:

gitlabCodeQuality {
    wireIntoCheck.set(false)
}

Then call ./gradlew check generateGitLabCodeQualityReport (or run the task in your CI step that always executes, regardless of check outcome).

Step 3: Publish the report to GitLab CI

Point GitLab at the generated JSON, for example:

build:
  stage: build
  image: ...
  script:
    - ./gradlew check
  artifacts:
    reports:
      codequality:
        - build/gl-code-quality-report.json

Advanced configuration

All options are properties on the generateGitLabCodeQualityReport task. Example:

import io.github.dnalchemist.gitlab.codequality.GenerateGitLabCodeQualityReportTask

tasks.named<GenerateGitLabCodeQualityReportTask>("generateGitLabCodeQualityReport") {
    spotbugsEnabled.set(true)
    spotbugsInputFile.set(layout.buildDirectory.file("reports/spotbugs/main.xml"))
    checkstyleEnabled.set(true)
    checkstyleInputFile.set(layout.buildDirectory.file("reports/checkstyle/main.xml"))
    outputFile.set(layout.buildDirectory.file("gl-code-quality-report.json"))
}

Android and Kotlin Multiplatform projects

The plugin looks up source directories for SpotBugs path resolution from sourceSets.main.java.srcDirs. That works on plain java / java-library / org.jetbrains.kotlin.jvm setups, but Android (com.android.application, com.android.library) and Kotlin Multiplatform projects do not register a main source set on JavaPluginExtension. In that case set sourceRoots explicitly so SpotBugs paths can still be resolved relative to the git root:

tasks.named<GenerateGitLabCodeQualityReportTask>("generateGitLabCodeQualityReport") {
    // Android
    sourceRoots.setFrom(file("src/main/java"), file("src/main/kotlin"))

    // Or Kotlin Multiplatform — pick the source sets whose findings you want resolved
    // sourceRoots.setFrom(
    //     kotlin.sourceSets.getByName("commonMain").kotlin.srcDirs,
    //     kotlin.sourceSets.getByName("jvmMain").kotlin.srcDirs,
    // )
}

Use setFrom(...) to replace the auto-detected default; from(...) would just append.

If sourceRoots resolves to an empty list, the SpotBugs portion of the report falls back to the raw sourcepath from the XML — fingerprints stay valid, but file paths in the GitLab widget will not be relative to the repo root.

Multi-project builds

Apply the plugin in subprojects that run SpotBugs/Checkstyle. Each project produces its own JSON file under its build/ directory.

GitLab accepts one code quality file per job (see this issue). Merge reports with jq, for example:

build:
  stage: build
  image: ...
  before_script:
    - apt-get update && apt-get install -y jq
  script:
    - ./gradlew check
  after_script:
    - find . -name gl-code-quality-report.json -print0 | xargs -0 cat | jq -s "add" > merged-gl-code-quality-report.json
  artifacts:
    reports:
      codequality:
        - merged-gl-code-quality-report.json

Using snapshots

Snapshots are published to the Sonatype Central Portal snapshots repository. Add that repository for plugin resolution in settings.gradle.kts, then apply the snapshot version in your build script:

// settings.gradle.kts
pluginManagement {
    repositories {
        gradlePluginPortal()
        maven {
            url = uri("https://central.sonatype.com/repository/maven-snapshots/")
            mavenContent { snapshotsOnly() }
        }
    }
}
// build.gradle.kts
plugins {
    java
    id("io.github.dnalchemist.gitlab-code-quality") version "1.2.0-SNAPSHOT"
}

About

Maven plugin to transform SpotBugs and Checkstyle XML reports to GitLab's JSON report format

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • Java 100.0%