Thursday, February 11, 2016

Sonar + Jacoco + Maven multi module projects + Jenkins

I recently had to come up with a sonar set up for a multi maven project. I found several examples for stuff that came close to this, but it wasn't EXACTLY what I was looking for.

My set up:

sonarQube 5.3 set up on a server, running with an Oracle backend
Jenkins job running a build
Junit tests
Jenkins > Configure > Sonar Runner added



0. Set up the Jenkins job to build your code:

These details are out of scope here. This is just a normal Jenkins maven project that builds stuff into a workspace.

1. Set up the Jenkins job for sonar:

As recommended by sonarqube.org I created a separate job and in the Build section, chose to Invoke Standalone Solar Analysis

Note that under Advanced Project Options, I had to select Use custom workspace, and fill the workspace of the job that built my code in step 0.


My Build section looked like this:



For readability, my sonar properties were:



# Metadata
sonar.host.url=http://sonar.domain.com
sonar.projectKey=somekey-sonar-runner
sonar.projectName=SomeNameSonarQube Runner
sonar.projectVersion=dev

# Source info
sonar.forceAnalysis=true
sonar.sourceEncoding=ISO-8859-15
maven.test.failure.ignore=true
sonar.sources=.
sonar.exclusions=**/SomeJavaFile.java,**/target/**/*,**/resources/min/**/*.js,**/node_modules/**/*,**/generated-sources/**/*,**/generated_sources/**/*,**/resources/lib/**/*

# Tests
sonar.junit.reportsPath=**/target/surefire-reports
sonar.surefire.reportsPath=**/target/surefire-reports
sonar.jacoco.reportPath=${WORKSPACE}/target/jacoco.exec
sonar.jacoco.itReportPath=${WORKSPACE}/target/jacoco-it.exec
sonar.java.binaries=**/target/classes
sonar.java.coveragePlugin=jacoco

# Debug
sonar.verbose=true

Step 2: Maven pom.xml

Add the following properties:

<sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<sonar.jacoco.reportPath>${projectRoot}/target/jacoco.exec</sonar.jacoco.reportPath>
<sonar.jacoco.itReportPath>${projectRoot}/target/jacoco-it.exec</sonar.jacoco.itReportPath>
<sonar.language>java</sonar.language>

Add the jacoco-maven-plugin to your build
<build>
    <plugins>
        <plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.5.201505241946</version>
<executions>
<execution>
<id>agent-for-ut</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${sonar.jacoco.reportPath}</destFile>
<append>true</append>
</configuration>
</execution>
<execution>
<id>agent-for-it</id>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
<configuration>
<destFile>${sonar.jacoco.itReportPath}</destFile>
<append>true</append>
</configuration>
</execution>
</executions>
   </plugin>
</plugins>
</build>

Thats it! Build your jenkins job (from step 0) to build your code, and the jacoco-maven-plugin will automatically create one large jacoco.exec and jacoco-it.exec file in the jenkins workspace of the sonar job under
   workspace/target

Now when you run the sonar jenkins job (from step 1), sonar will grab the jacoco exec files and figure out the code coverage and create those beautiful graphs which you can see from your sonar server.