DEV Community

Amalia Hajarani
Amalia Hajarani

Posted on

How to: SonarQube Code Coverage in Jenkins with Maven Project

Hallo dear everyone whoever read this post. Today I'd love to share my learning journey with Jenkins. In today's post I will be using this code as my use case and I'll be cooking from scratch which is installing Jenkins until we have the final dish of seeing the code coverage of our maven project in SonarQube.

Prerequisite

  1. Installed Java version of 17 and have it configured in environment variable
  2. Installed Maven version of 3.9.5 and have it configured in environment variable

Installing Jenkins

  1. Since I'm on Windows 10, I downloaded Jenkins lts version (mine is 2.426.1 LTS) from this official link.
  2. Open the installer and click Next. Image description
  3. I'm going to use the default path so I just click Next. Image description
  4. Since I cannot remember my own credential, I choose the Run service as LocalSystem. Then, click Next. Image description
  5. I choose the default port which is 8085. Click Test Port then proceed to Next. Image description
  6. Choose your java version. Mine is 17. If the path is correct, just click Next. Image description
  7. I don't understand what is happening here, so I assume it is safe to just click Next. Image description
  8. And now Jenkins is ready to be installed! Don't forget to click the Install button. After that you might have to wait for a few times until installation is finish. Image description
  9. Now that installation is finished already, we can move on by clicking Finish button. Image description

Installing and Prepare SonarQube

  1. I downloaded the latest version of SonarQube from this official link. The version is now at Version 10.3.
  2. Unzip the file in your dedicated folder. Mine is on D: drive.
  3. We might cannot start the SonarQube just now because we have to do thing to make sure the configuration is working.
  4. To make things easier, open sonar.properties in code editor. You can find the file by entering the unzip directory result, go to conf directory, and there laying the sonar.properties. Now I uncomment few things in that file such as below lines: sonar.web.host=0.0.0.0 sonar.web.port=9000 sonar.search.port=0 // For this line you might want to change the port as well. Mine is from `9001` to `0`
  5. Don't forget to save after making those changes.
  6. Now let's try to run SonarQube server by going to bin directory, it is at the same level as conf directory. Choose the directory that match your operating system. For me, I choose windows-x86-64.
  7. Open command prompt from that directory.
  8. Run this command: StartSonar.bat
  9. If it's working properly this is what will you see at the bottom of command line: Image description

Updating POM.xml

You can find the original resource at here for this step. But it wasn't working at the first try since some of the versions are not compatible with my java version. But the final POM.xml looks like:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.tujuhsembilan</groupId>
<artifactId>scheduler</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>scheduler</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
<jacoco.version>0.8.8</jacoco.version>
<sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
<sonar.dynamicAnalysis>reuseReports</sonar.dynamicAnalysis>
<sonar.jacoco.reportPath>${project.basedir}/../target/jacoco.exec</sonar.jacoco.reportPath>
<sonar.language>java</sonar.language>
</properties>
<dependencies>
    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-data-jpa&lt;/artifactId&gt;
    &lt;/dependency&gt;

    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-hateoas&lt;/artifactId&gt;
    &lt;/dependency&gt;

    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-quartz&lt;/artifactId&gt;
    &lt;/dependency&gt;

    &lt;dependency&gt;
        &lt;groupId&gt;com.h2database&lt;/groupId&gt;
        &lt;artifactId&gt;h2&lt;/artifactId&gt;
        &lt;scope&gt;runtime&lt;/scope&gt;
    &lt;/dependency&gt;

    &lt;dependency&gt;
        &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
        &lt;artifactId&gt;lombok&lt;/artifactId&gt;
        &lt;optional&gt;true&lt;/optional&gt;
    &lt;/dependency&gt;

    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-test&lt;/artifactId&gt;
        &lt;scope&gt;test&lt;/scope&gt;
    &lt;/dependency&gt;

    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-data-mongodb&lt;/artifactId&gt;
    &lt;/dependency&gt;

    &lt;dependency&gt;
        &lt;groupId&gt;org.modelmapper&lt;/groupId&gt;
        &lt;artifactId&gt;modelmapper&lt;/artifactId&gt;
        &lt;version&gt;3.0.0&lt;/version&gt;
    &lt;/dependency&gt;

    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-web&lt;/artifactId&gt;
    &lt;/dependency&gt;

    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-data-rest&lt;/artifactId&gt;
    &lt;/dependency&gt;

    &lt;dependency&gt;
        &lt;groupId&gt;org.postgresql&lt;/groupId&gt;
        &lt;artifactId&gt;postgresql&lt;/artifactId&gt;
        &lt;scope&gt;runtime&lt;/scope&gt;
    &lt;/dependency&gt;

    &lt;dependency&gt;
        &lt;groupId&gt;org.telegram&lt;/groupId&gt;
        &lt;artifactId&gt;telegrambots-spring-boot-starter&lt;/artifactId&gt;
        &lt;version&gt;6.1.0&lt;/version&gt;
    &lt;/dependency&gt;
    &lt;dependency&gt;
        &lt;groupId&gt;org.telegram&lt;/groupId&gt;
        &lt;artifactId&gt;telegrambots-abilities&lt;/artifactId&gt;
        &lt;version&gt;6.7.0&lt;/version&gt;
    &lt;/dependency&gt;

    &lt;dependency&gt;
        &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
        &lt;artifactId&gt;spring-boot-starter-security&lt;/artifactId&gt;
    &lt;/dependency&gt;

    &lt;dependency&gt;
        &lt;groupId&gt;org.jacoco&lt;/groupId&gt; 
        &lt;artifactId&gt;jacoco-maven-plugin&lt;/artifactId&gt;
        &lt;version&gt;0.8.6&lt;/version&gt;
    &lt;/dependency&gt;

&lt;/dependencies&gt;

&lt;build&gt;
    &lt;plugins&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
            &lt;artifactId&gt;spring-boot-maven-plugin&lt;/artifactId&gt;
        &lt;/plugin&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.jacoco&lt;/groupId&gt;
            &lt;artifactId&gt;jacoco-maven-plugin&lt;/artifactId&gt;
            &lt;version&gt;${jacoco.version}&lt;/version&gt;
            &lt;executions&gt;
                &lt;execution&gt;
                    &lt;id&gt;jacoco-initialize&lt;/id&gt;
                    &lt;goals&gt;
                        &lt;goal&gt;prepare-agent&lt;/goal&gt;
                    &lt;/goals&gt;
                &lt;/execution&gt;
                &lt;execution&gt;
                    &lt;id&gt;jacoco-site&lt;/id&gt;
                    &lt;phase&gt;package&lt;/phase&gt;
                    &lt;goals&gt;
                        &lt;goal&gt;report&lt;/goal&gt;
                    &lt;/goals&gt;
                &lt;/execution&gt;
            &lt;/executions&gt;
        &lt;/plugin&gt;
    &lt;/plugins&gt;
&lt;/build&gt;
&lt;repositories&gt;
    &lt;repository&gt;
        &lt;id&gt;spring-releases&lt;/id&gt;
        &lt;name&gt;Spring Releases&lt;/name&gt;
        &lt;url&gt;https://repo.spring.io/libs-release&lt;/url&gt;
    &lt;/repository&gt;
&lt;/repositories&gt;
&lt;pluginRepositories&gt;
    &lt;pluginRepository&gt;
        &lt;id&gt;spring-releases&lt;/id&gt;
        &lt;name&gt;Spring Releases&lt;/name&gt;
        &lt;url&gt;https://repo.spring.io/libs-release&lt;/url&gt;
    &lt;/pluginRepository&gt;
&lt;/pluginRepositories&gt;
Enter fullscreen mode Exit fullscreen mode

</project>

Enter fullscreen mode Exit fullscreen mode




Running SonarQube in Local Environment

Now that I have the SonarQube and the project ready, I tried to run it, but some problem happened related to my maven settings. I hope you're not going to have the problem, but this is how I update my maven settings (you can find the settings at MAVEN_HOME/conf):

  1. Adding sonarscanner plugin group.

    <pluginGroup>org.sonarsource.scanner.maven</pluginGroup>
    
    
  2. Adding sonar profile.

        <profile>
            <id>sonar</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <!-- Optional URL to server. Default value is http://localhost:9000 -->
                <sonar.host.url>
                  http://localhost:9000
                </sonar.host.url>
            </properties>
        </profile>
    

Now, let's try to run SonarQube locally using command prompt

  1. Open command prompt from the root of the project and run: mvn clean install If the build success you will have this on your command prompt: Image description
  2. Start the SonarQube server
  3. Get back to the project command line and run:

    mvn sonar:sonar -Dsonar.login=admin -Dsonar.password=admin
    

    I did not change any credential, so by default the credential should be as what written above.

    Image description

  4. If the build succeed, you might wanna see some previous line to know where you can open the coverage result. Mine is at http://localhost:9000/dashboard?id=com.tujuhsembilan%3Ascheduler. Disclaimer: you might need to login for the first time using the default credentials and have to change your password, but after that you should be good to go.
    Image description

Creating Jenkins Maven Project and Implementing SonarQube

Configuring Jenkins for the first time

  1. Open localhost:8085. Jenkins is automatically start by default. From here, I will use the picture from the official site since mine is already unlcoked. You will have to unlock jenkins by inputing the password provided in red block. Then click continue. Image description
  2. You will be asked to install some plugins. I choose the Install suggested plugins.
  3. Now you will be redirected to creating admin user. Just fill it as you wish and then click Save and Continue.
  4. After that put http://localhost:8085/ as Jenkins URL and click Save and Finish.
  5. You are now supposed to be at the dashboard.

Configuring SonarQube Scanner Plugin in Jenkins

  1. In the Dashboard, click Manage Jenkins.
  2. Choose Plugins. Image description
  3. Choose Available Plugin and search SonarQube Scanner for Jenkins. Tick the checkbox and click Install.

Configuring Tools

  1. In the Dashboard, click Manage Jenkins.
  2. Choose Tools. Image description
  3. Add JDK installations and fill it with your JAVA_HOME. Image description
  4. Add Maven installations and fill it with your MAVEN_HOME. Image description

Getting SonarQube Token

  1. Make sure that SonarQube server is still running.
  2. Go to http://localhost:9000/.
  3. On the right corner, click on your initial and choose My Account
    Image description

  4. Go to Security tab.
    Image description

  5. Fill the field and click Generate.
    Image description

  6. Copy the token to somewhere save because we are not able to see it again.

Configuring System

  1. In the Dashboard, click Manage Jenkins.
  2. Choose System. Image description
  3. Go to SonarQube servers. Tick the check box for Environment variables.
  4. Add SonarQube installations.
  5. Fill the name and Server URL Image description
  6. In Server authentication token field, click Add.
  7. Choose Jenkins.
  8. Add Kind dropdown, choose Secret text.
  9. Leave the scope.
  10. Enter the SonarQube secret token that you copy before.
  11. Fill the ID with some name that make it easier to know what credential is that for. Image description
  12. Click Add.
  13. Back to Server authentication token field, click the dropdown and choose the newly generated credential. Image description
  14. Click Save.

Creating Maven Project

  1. In the dashboard, click New Item.
  2. Enter the project name and choose Maven Project. Then Click OK. Image description
  3. Now we are going to configure build settings.
  4. In Source Code Management section, choose Git. Make sure you alredy push the latest change especially the POM.xml change to your repository.
  5. Enter your repository URL that you usually use to clone the project.
  6. In credential fields, click Add, choose Jenkins. Image description
  7. In Kind dropdown, choose Username with password.
  8. Leave the Scope.
  9. Enter your github username.
  10. Enter your github password.
  11. Again, fill the ID with some name that make it easier to know what credential is that for. Image description
  12. click Add.
  13. Back to credential field dropdown, choose your github credential.
  14. Moving to Build Environment section, tick the Prepare SonarQube Scanner environment, and again in the dropdown, choose the SonarQube token credential. Image description
  15. Moving to the Build section you want to add this to the Goals and options. clean install $SONAR_MAVEN_GOAL Image description
  16. Click Save.

Building Maven Project

  1. From Dashboard, you can see your new project. Click on the project.
  2. In the sidebar you can see Build Now button. Click that. Image description
  3. Wait for the build.
  4. When the build is success, you can click SonarQube button in sidebar. Image description
  5. Now you have your code coverage running from Jenkins! Image description

The working repository can be seen here.

Top comments (0)