= 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: image::./images/others/jenkins-sonarqube/jenkins-sonarqube-plugin.png[] == 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: image::./images/others/jenkins-sonarqube/sonarqube-login.png[] Afterwards, SonarQube itself asks you to create this token we talked about (the name is up to you): image::./images/others/jenkins-sonarqube/sonarqube-token-name.png[] Then a token is generated: image::./images/others/jenkins-sonarqube/sonarqube-token-generation.png[] You click in "continue" and the token's generation is completed: image::./images/others/jenkins-sonarqube/sonarqube-token-done.png[] == 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. image::./images/others/jenkins-sonarqube/jenkins-sonarqube-server-setup.png[] == 4. Jenkins SonarQube Scanner Install a SonarQube Scanner as a Global tool in Jenkins to be used in the project's pipeline. image::./images/others/jenkins-sonarqube/jenkins-sonarqube-scanner.png[] == 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. [source,groovy] ---- 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: image::./images/others/jenkins-sonarqube/jenkins-sonarqube-feedback.png[] And in SonarQube: image::./images/others/jenkins-sonarqube/sonarqube-project-result.png[] == 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 `` tag: [source,xml] ---- (...) 3.8 jacoco jacoco reuseReports java 1.7 target/surefire-reports target/jacoco.exec UTF-8 **/generated-sources/**/*, **io/oasp/mirabaud/general/**/*, **/*Dao.java, **/*Entity.java, **/*Cto.java, **/*Eto.java, **/*SearchCriteriaTo.java, **/*management.java, **/*SpringBootApp.java, **/*SpringBootBatchApp.java, **/*.xml, **/*.jsp **io/oasp/mirabaud/general/**/*, **/*Dao.java, **/*Entity.java, **/*Cto.java, **/*Eto.java, **/*SearchCriteriaTo.java, **/*management.java, **/*SpringBootApp.java, **/*SpringBootBatchApp.java, **/*.xml, **/*.jsp http://${YOUR_SONAR_SERVER_URL}/ 0.7.9 3.2.0 3.1.0 ---- Of course, those `sonar` amd `sonar.coverage` can/must be changed to fit with other projects. Now add the *Jacoco Listener* as a dependency: [source,xml] ---- org.sonarsource.java sonar-jacoco-listeners test ---- Plugin Management declarations: [source,xml] ---- org.sonarsource.scanner.maven sonar-maven-plugin 3.2 org.jacoco jacoco-maven-plugin ${jacoco.version} ---- Plugins: [source,xml] ---- (...) org.apache.maven.plugins maven-surefire-plugin 2.20.1 -XX:-UseSplitVerifier -Xmx2048m ${surefireArgLine} false false ${project.basedir}/${sonar.junit.reportPaths} ${jacoco.agent.argLine} ${oasp.test.excluded.groups} true true listener org.sonar.java.jacoco.JUnitListener org.jacoco jacoco-maven-plugin -Xmx128m true jacoco.agent.argLine ${sonar.jacoco.reportPath} **/generated-sources/**/*, **io/oasp/${PROJECT_NAME}/general/**/* **/*Dao.java **/*Entity.java **/*Cto.java **/*Eto.java **/*SearchCriteriaTo.java **/*management.java **/*SpringBootApp.java **/*SpringBootBatchApp.java **/*.class prepare-agent initialize prepare-agent ${sonar.jacoco.reportPath} true report-aggregate verify report-aggregate jacoco-site verify report ---- == 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`: [source,groovy] ---- 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]" } ----