Skip to content

dsf mirabaud jenkins sonarqube integration

jodacalc edited this page Jun 6, 2019 · 2 revisions

Jenkins - SonarQube integration

First thing is installing both tools by, for example, Docker or Docker Compose. Then, we have to think about how they should collaborate to create a more efficient Continuous Integration process.

Once our project’s pipeline is triggered (it could also be triggered in a fancy way, such as when a merge to the develop branch is done).

1. Jenkins SonarQube plugin

Typically in those integration cases, Jenkins plug-in installations become a must. Let’s look for some available SonarQube plug-in(s) for Jenkins:

jenkins sonarqube plugin

2. SonarQube token

Once installed let’s create a token in SonarQube so that Jenkins can communicate with it to trigger their Jobs. Once we install SonarQube in our CI/CD machine (ideally a remote machine) let’s login with admin/admin credentials:

sonarqube login

Afterwards, SonarQube itself asks you to create this token we talked about (the name is up to you):

sonarqube token name

Then a token is generated:

sonarqube token generation

You click in "continue" and the token’s generation is completed:

sonarqube token done

3. Jenkins SonarQube Server setup

Now we need to tell Jenkins where is SonarQube and how to communicate with it. In Manage Jenkins > Configure Settings. We add a name for the server (up to you), where it is located (URL), version and the Server authentication token created in point 2.

jenkins sonarqube server setup

4. Jenkins SonarQube Scanner

Install a SonarQube Scanner as a Global tool in Jenkins to be used in the project’s pipeline.

jenkins sonarqube scanner

5. Pipeline code

Last step is to add the SonarQube process in our project’s Jenkins pipeline. The following code will trigger a SonarQube process that will evaluate our code’s quality looking for bugs, duplications, and so on.

    stage 'SonarQube Analysis'
        def scannerHome = tool 'SonarQube scanner';
        sh "${scannerHome}/bin/sonar-scanner \
             -Dsonar.host.url=http://url-to-your-sq-server:9000/ \
             -Dsonar.login=[SONAR_USER] -Dsonar.password=[SONAR_PASS] \
             -Dsonar.projectKey=[PROJECT_KEY] \
             -Dsonar.projectName=[PROJECT_NAME] -Dsonar.projectVersion=[PROJECT_VERSION] \
             -Dsonar.sources=. -Dsonar.java.binaries=. \
             -Dsonar.java.source=1.8 -Dsonar.language=java"

6. Results

After all this, you should end up having something like this in Jenkins:

jenkins sonarqube feedback

And in SonarQube:

sonarqube project result

7. Changes in a devonfw project to execute SonarQube tests with Coverage

The plugin used to have Coverage reports in the SonarQube for devonfw projects is Jacoco. There are some changes in the project’s parent pom.xml that are mandatory to use it.

Inside of the <properties> tag:

<properties>

    (...)

    <sonar.jacoco.version>3.8</sonar.jacoco.version>
    <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
    <sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin>
    <sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
    <sonar.language>java</sonar.language>
    <sonar.java.source>1.7</sonar.java.source>
    <sonar.junit.reportPaths>target/surefire-reports</sonar.junit.reportPaths>
    <sonar.jacoco.reportPaths>target/jacoco.exec</sonar.jacoco.reportPaths>
    <sonar.sourceEncoding>UTF-8</sonar.sourceEncoding>
    <sonar.exclusions>
        **/generated-sources/**/*,
        **io/oasp/mirabaud/general/**/*,
        **/*Dao.java,
        **/*Entity.java,
        **/*Cto.java,
        **/*Eto.java,
        **/*SearchCriteriaTo.java,
        **/*management.java,
        **/*SpringBootApp.java,
        **/*SpringBootBatchApp.java,
        **/*.xml,
        **/*.jsp
    </sonar.exclusions>
    <sonar.coverage.exclusions>
        **io/oasp/mirabaud/general/**/*,
        **/*Dao.java,
        **/*Entity.java,
        **/*Cto.java,
        **/*Eto.java,
        **/*SearchCriteriaTo.java,
        **/*management.java,
        **/*SpringBootApp.java,
        **/*SpringBootBatchApp.java,
        **/*.xml,
        **/*.jsp
    </sonar.coverage.exclusions>
    <sonar.host.url>http://${YOUR_SONAR_SERVER_URL}/</sonar.host.url>
    <jacoco.version>0.7.9</jacoco.version>

    <war.plugin.version>3.2.0</war.plugin.version>
    <assembly.plugin.version>3.1.0</assembly.plugin.version>
</properties>

Of course, those sonar amd sonar.coverage can/must be changed to fit with other projects.

Now add the Jacoco Listener as a dependency:

<dependencies>
    <dependency>
        <groupId>org.sonarsource.java</groupId>
        <artifactId>sonar-jacoco-listeners</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

Plugin Management declarations:

<pluginManagement>
    <plugins>
        <plugin>
            <groupId>org.sonarsource.scanner.maven</groupId>
            <artifactId>sonar-maven-plugin</artifactId>
            <version>3.2</version>
        </plugin>
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>${jacoco.version}</version>
        </plugin>
    </plugins>
<pluginManagement>

Plugins:

<plugins>

    (...)

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.20.1</version>
        <configuration>
            <argLine>-XX:-UseSplitVerifier -Xmx2048m ${surefireArgLine}</argLine>
            <testFailureIgnore>false</testFailureIgnore>
            <useFile>false</useFile>
            <reportsDirectory>${project.basedir}/${sonar.junit.reportPaths}</reportsDirectory>
            <argLine>${jacoco.agent.argLine}</argLine>
            <excludedGroups>${oasp.test.excluded.groups}</excludedGroups>
            <alwaysGenerateSurefireReport>true</alwaysGenerateSurefireReport>
            <aggregate>true</aggregate>
            <properties>
                <property>
                    <name>listener</name>
                    <value>org.sonar.java.jacoco.JUnitListener</value>
                </property>
            </properties>
        </configuration>
    </plugin>
    <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <configuration>
            <argLine>-Xmx128m</argLine>
            <append>true</append>
            <propertyName>jacoco.agent.argLine</propertyName>
            <destFile>${sonar.jacoco.reportPath}</destFile>
            <excludes>
                <exclude>**/generated-sources/**/*,</exclude>
                <exclude>**io/oasp/${PROJECT_NAME}/general/**/*</exclude>
                <exclude>**/*Dao.java</exclude>
                <exclude>**/*Entity.java</exclude>
                <exclude>**/*Cto.java</exclude>
                <exclude>**/*Eto.java</exclude>
                <exclude>**/*SearchCriteriaTo.java</exclude>
                <exclude>**/*management.java</exclude>
                <exclude>**/*SpringBootApp.java</exclude>
                <exclude>**/*SpringBootBatchApp.java</exclude>
                <exclude>**/*.class</exclude>
            </excludes>
        </configuration>
        <executions>
            <execution>
                <id>prepare-agent</id>
                <phase>initialize</phase>
                <goals>
                    <goal>prepare-agent</goal>
                </goals>
                <configuration>
                    <destFile>${sonar.jacoco.reportPath}</destFile>
                    <append>true</append>
                </configuration>
            </execution>
            <execution>
                <id>report-aggregate</id>
                <phase>verify</phase>
                <goals>
                    <goal>report-aggregate</goal>
                </goals>
            </execution>
            <execution>
                <id>jacoco-site</id>
                <phase>verify</phase>
                <goals>
                    <goal>report</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
</plugins>

Jenkins SonarQube execution

If the previous configuration is already setup, once Jenkins execute the sonar maven plugin, it will automatically execute coverage as well.

This is an example of a block of code from a devonfw project’s Jenkinsfile:

    withMaven(globalMavenSettingsConfig: 'YOUR_GLOBAL_MAVEN_SETTINGS', jdk: 'OpenJDK 1.8', maven: 'Maven_3.3.9') {
        sh "mvn sonar:sonar -Dsonar.login=[USERNAME] -Dsonar.password=[PASSWORD]"
    }
Clone this wiki locally