$ mvn sonar:sonarA few moments later you should have the metrics available at:
http://localhost:9000/Well, the past few days I was setting up a multi-module Gradle project for Sonar. Let me start by stating that Gradle is awesome. Having the ability to declare dependencies as one-liners and also being able to customize your scripts easily, yet having sensible defaults, is very nice. Kind of the best of both worlds.
Setting up Sonar for a multi module project, though, is unfortunately a bit more complicated, compared to what I am used to in the Maven world. It is not awfully complicated, but it took me a while to collect all the pieces of information.
Getting your Sonar plugin to just doing something is fairly simple. Just follow the basic steps outlined in the plugin documentation at:
One differentiator between the Sonar Plugin for Gradle and Maven is, that the Gradle version does not automatically run code coverage analysis. This needs to be manually setup. This is where the official doc just vaguely refers to Cobertura.
First, I tried using Cobertura for code coverage, but I seemed to run into difficulties for my multi-module projects. The Cobertura Plugin is here:
By chance I realized that the Sonar guys have a GitHub repository with samples on how to setup sonars for various build systems, including Gradle:
Some Gradle Sonar Plugin Limitations
The Gradle Sonar Plugin has an annoying limitation, where I can run it for the ROOT project OR for the sub-projects individually. See the following Gradle Jira ticket for details:
Furthermore, I hit the minor issue that I cannot set the links in the Sonar dashboard. This seems to be related to the following Sonar Jira issue:
The JaCoCo code coverage plugin is "slightly less" supported by the Gradle Sonar Plugin, e.g. the Gradle Plugin does not have an explicit setter for the JacocoReportPath and it assumes the "target" folder as the build directory by default. Therefore you must set explicitly:
props["sonar.jacoco.reportPath"] = "${buildDirName}/jacoco.exec"
Lastly, I deviated a bit from the SonarSource Gradle example, and instead of System properties, I wanted to use Gradle properties to allow for users to provide non-default Sonar configuration settings (databasem url, jdbc parameters etc.). Well, while setting that up I ran into yet another Gradle Jira issue:
But at the the end, I am happily able to run a multi-module Gradle project with Sonar and collecting Code Coverage statistics. Here is the relavant code from my build.gradle file:
apply plugin: 'sonar' sonar { if (rootProject.hasProperty('sonarHostUrl')) { server.url = rootProject.sonarHostUrl } database { if (rootProject.hasProperty('sonarJdbcUrl')) { url = rootProject.sonarJdbcUrl } if (rootProject.hasProperty('sonarJdbcDriver')) { driverClassName = rootProject.sonarJdbcDriver } if (rootProject.hasProperty('sonarJdbcUsername')) { username = rootProject.sonarJdbcUsername } if (rootProject.hasProperty('sonarJdbcPassword')) { password = rootProject.sonarJdbcPassword } } project { dynamicAnalysis = "reuseReports" withProjectProperties { props -> props["sonar.core.codeCoveragePlugin"] = "jacoco" props["sonar.jacoco.reportPath"] = "${buildDirName}/jacoco.exec" } } println("Sonar parameters used: server.url='${server.url}'; database.url='${database.url}'; database.driverClassName='${database.driverClassName}'; database.username='${database.username}'") } subprojects { subproject -> ... // See http://www.gradle.org/docs/current/userguide/dependency_management.html#sub:configurations // and http://www.gradle.org/docs/current/dsl/org.gradle.api.artifacts.ConfigurationContainer.html configurations { jacoco //Configuration Group used by Sonar to provide Code Coverage using JaCoCo } // dependencies that are common across all java projects dependencies { ... jacoco group: "org.jacoco", name: "org.jacoco.agent", version: "0.5.3.201107060350", classifier: "runtime" ... } test { jvmArgs "-javaagent:${configurations.jacoco.asPath}=destfile=${buildDir}/jacoco.exec,includes=org.your.project.*" } ... }I hope this is useful information for all Gradle users out there.
1 comment:
Keep in mind that Sonar was initially designed to work with Maven only. This still shines through here and there today. Though overall, Sonar works really well with Gradle by now.
Why is it that you externalize all those properties and pass them in from the command line? Except for the password, this goes a bit against Gradle's philosophy.
In the future, Gradle will likely provide a generic mechanism to set any property (e.g. sonar.database.username) from the command line.
Post a Comment