We am working on splitting out our gradle build for a multi module gradle project. Previously we used to build the whole repo together using a build.gradle at the top level and sonarqube works fine but now we want to build submodules in the repo with their own build.gradle files. The issue we are hitting is with integrating sonarqube for submodules.
When I am keeping sonarqube property in top level and nested level build.gradle, I am hitting this error:
File abc/src/main/java/abc.java can’t be indexed twice. Please check that inclusion/exclusion patterns produce disjoint sets for main and test files
When I removed sonarqube property from the top level and only having it at the nested level, I am getting this error:
sonarqubeSonarQube server [http://localhost:9000] can not be reached
even though sonar.host.url is specified in nested level build.gradle
I am trying to build my submodule with this command:
gradle build sonarqube -Dsonar.login=USERNAME -Dsonar.password=PASSWORD -Dsonar.branch.name=​test -Dsonar.projectVersion=test -Dsonar.sources=abc/src/main/java
Yes, multi-module Gradle projects can be a bit painful to set up. I’m assuming you’re using a Gradle multi-project build? I experimented with this a few months ago; here’s what worked for me.
In the top-level build.gradle I have two blocks:
sonarqube {
properties {
property "sonar.host.url", "http://<hostname>:<port>"
property "sonar.sourceEncoding", "UTF-8"
property "sonar.projectName", "Example Gradle multi-project"
property "sonar.projectKey", "my-example-gradle-multi-project"
}
}
...
subprojects {
version = '1.0'
sonarqube {
properties {
property "sonar.sources", "src/main"
property "sonar.tests", "src/test"
// I was testing with JaCoCo, so the next line is not needed if you're using some other tool
property "sonar.coverage.jacoco.xmlReportPaths", "../build/reports/jacoco/codeCoverageReport/codeCoverageReport.xml"
property "sonar.host.url", "http://<hostname>:<port>"
}
}
}
Then in the top-level settings.gradle file I have:
rootProject.name = 'example_gradle_multi_project'
include 'abc'
include 'xyz'
Nothing needed at the abc/build.gradle or xyz/build.gradle level
I’ve also been looking for a best practice way to set-up a multi-module gradle project, but found that I end up with one project per module in the sonar interface. This is a problem when some projects contain API modules (with no tests, and therefore no test coverage), and implementation modules (with tests, and therefore test coverage).
When I say I want 90% coverage, and I want it to mean “across the multi-module project as a whole”.
how do I do that?
SonarQube coverage is per project. So in your situation you need to either analyze the multi-module project as a single SonarQube project, or if you’re a commercial customer use an Application to aggregate the individual projects, which will also calculate overall coverage.
Hi Cameron
I have multi-module Gradle projects similar to the example. I can analyze every module with Sonarqube, but not exactly the way I want.
sonarqube.gradle :
apply plugin: "org.sonarqube"
sonarqube {
properties {
property "sonar.host.url", "http://<hostname>:<port>"
property "sonar.sourceEncoding", "UTF-8"
property "sonar.projectName", "Example Gradle multi-project"
// property "sonar.projectKey", "my-example-gradle-multi-project" // Removed key for every module can be run
}
}
abc/build.gradle :
apply from: "$rootDir/sonarqube.gradle"
xyz/build.gradle :
apply from: "$rootDir/sonarqube.gradle"
When I want to analyze the modules in the project, I write to the terminal : ./gradlew sonarqube
This way , I am able to run and analyze each module as a different project. This is ok.
But My problem :
I want to run only 1 module among the modules. But I cant.Can I run a single module I want ?
Thanks. It seems to be working with jacoco and detekt, but doesn’t work with owasp dependency check (org.owasp.dependencycheck)
My config is
subprojects {
apply {
plugin("org.jetbrains.kotlin.jvm")
plugin("io.gitlab.arturbosch.detekt")
plugin("org.sonarqube")
plugin("org.owasp.dependencycheck")
plugin("jacoco")
}
dependencies {
detektPlugins("io.gitlab.arturbosch.detekt:detekt-formatting:" + System.getenv("GRADLE_DETEKT_VER") ?: "1.22.0")
}
jacoco {
toolVersion = System.getenv("GRADLE_JACOCO_VER") ?: "0.8.8"
}
tasks.jacocoTestReport {
reports {
xml.required.set(true)
}
}
tasks.withType<Test> {
useJUnitPlatform()
finalizedBy("jacocoTestReport")
}
dependencyCheck {
format = "ALL"
}
sonarqube {
properties {
property ("sonar.host.url", System.getenv("SONARQUBE_URL") ?: "")
property ("sonar.token", System.getenv("SONARQUBE_TOKEN") ?: "")
property ("sonar.coverage.jacoco.xmlReportPaths", "build/reports/jacoco/jacocoTestReport/jacocoTestReport.xml,build/reports/jacoco/test/jacocoTestReport.xml")
property ("sonar.dependencyCheck.jsonReportPath", "build/reports/dependency-check-report.json")
property ("sonar.dependencyCheck.htmlReportPath", "build/reports/dependency-check-report.html")
property ("sonar.kotlin.detekt.reportPaths", "build/reports/detekt/detekt.xml")
}
}
detekt {
// Version of Detekt that will be used. When unspecified the latest detekt
// version found will be used. Override to stay on the same version.
toolVersion = System.getenv("GRADLE_DETEKT_VER") ?: "1.22.0"
// If set to `true` the build does not fail when the
// maxIssues count was reached. Defaults to `false`.
ignoreFailures = true
}
}