Jenkins Pipelines
Code Quality and Testing
SonarQube Quality Gate Step and Refactoring
In this lesson, we explain how to configure a SonarQube quality gate to control whether your Jenkins pipeline continues or stops, and how to refactor your pipeline for enhanced security and clarity. The solution leverages the SonarQube plugin in Jenkins, which provides a webhook URL to receive quality status updates.
The integration process is illustrated in the following diagram:
The complete process follows these steps:
- Jenkins triggers the pipeline.
- The pipeline runs the SonarScanner to analyze the application.
- SonarScanner uploads analysis results to the SonarQube server.
- SonarQube computes the quality gate for the project and determines if it passes or fails.
- The server sends the quality gate status back to Jenkins via the configured webhook.
- Depending on the quality gate status, the pipeline either continues (if passed) or aborts (if failed).
Note
Ensure that your Jenkins and SonarQube instances are properly integrated before proceeding with these configurations.
Configuring the SonarQube Webhook
Before integrating quality gate status notifications, verify that Jenkins exposes a webhook URL. Open a new browser tab, navigate to Jenkins on port 8080, and access the SonarQube-webhook
endpoint exposed by the SonarQube plugin.
Next, configure the webhook in SonarQube with these steps:
- Navigate to Administration > Configure Webhook.
- Note that no webhook is defined by default.
- Create a new webhook named "Jenkins webhook" and paste the Jenkins webhook URL copied in the previous step.
Once the webhook is created, SonarQube will send the quality gate status back to Jenkins. To confirm the settings, check the webhook management page in SonarQube:
Refactoring the Jenkins Pipeline
Initially, the Jenkinsfile exposed the authentication token directly in the script, which is not secure. To improve security, you should configure the SonarQube installation within Jenkins and update the Jenkinsfile accordingly.
Adding a SonarQube Server in Jenkins
- Navigate to Jenkins configuration.
- Add a new SonarQube server by providing:
- A unique name (e.g., "sonar-qube-server")
- The SonarQube endpoint (e.g., running on port 9000)
- The authentication token
- Create a new credential of type "Secret Text" using the token. For example, assign a credential ID like "SonarQube server token."
Updating the Jenkinsfile
Modify your Jenkinsfile so that SonarScanner commands are executed within the context of the SonarQube installation. For instance, replace the insecure stage that exposed the token:
stage('SAST - SonarQube') {
steps {
sh 'echo $SONAR_SCANNER_HOME'
sh '''
$SONAR_SCANNER_HOME/bin/sonar-scanner \
-Dsonar.projectKey=Solar-System-Project \
-Dsonar.sources=app.js \
-Dsonar.host.url=http://64.227.187.25:9000 \
-Dsonar.javascript.lcov.reportPaths=/coverage/lcov.info \
-Dsonar.login=sqp_54484dbbbe3a5b3b3088c734cf5e4c3bbe3f6d6
'''
}
}
to a more secure version:
stage('SAST - SonarQube') {
steps {
withSonarQubeEnv('sonar-qube-server') {
sh 'echo $SONAR_SCANNER_HOME'
sh '''
$SONAR_SCANNER_HOME/bin/sonar-scanner \
-Dsonar.projectKey=Solar-System-Project \
-Dsonar.sources=app.js \
-Dsonar.javascript.lcov.reportPaths=./coverage/lcov.info \
-Dsonar.login=sqp_544848dbbbe3a53b3088c734cfe34cbeba3fd6
'''
}
}
}
This refactoring ensures that the host URL and token are managed by the SonarQube installation configuration within Jenkins.
Waiting for the Quality Gate Status
To prevent the pipeline from proceeding before the SonarQube analysis is complete, incorporate the "waitForQualityGate" step. This step waits for the quality gate status and can be wrapped in a timeout to avoid indefinite blocking.
Declarative Pipeline Example
pipeline {
agent none
stages {
stage("build & SonarQube analysis") {
agent any
steps {
withSonarQubeEnv('My SonarQube Server') {
sh 'mvn clean package sonar:sonar'
}
}
}
stage("Quality Gate") {
steps {
timeout(time: 1, unit: 'HOURS') {
waitForQualityGate abortPipeline: true
}
}
}
}
}
Scripted Pipeline Example
stage('SAST - SonarQube') {
steps {
timeout(time: 60, unit: 'SECONDS') {
withSonarQubeEnv('sonar-qube-server') {
sh 'echo $SONAR_SCANNER_HOME'
sh '''
$SONAR_SCANNER_HOME/bin/sonar-scanner \
-Dsonar.projectKey=Solar-System-Project \
-Dsonar.sources=app.js \
-Dsonar.javascript.lcov.reportPaths=./coverage/lcov.info
'''
}
}
waitForQualityGate abortPipeline: true
}
}
Using the timeout directive ensures that if SonarQube does not return a quality gate status within the specified time (e.g., 60 seconds), the build will be aborted to prevent hanging.
Disabling the OWASP Yarn Audit Analyzer
If your dependency check stage takes too long due to the initialization of the Yarn audit analyzer—and you are already using the Node.js or NPM audit analyzer—you can disable the Yarn audit analyzer to avoid unnecessary delays or errors. Simply add an argument in your dependency scanning configuration to disable Yarn audit.
Below is an example Jenkinsfile with several stages, including Dependency Scanning, Unit Testing, Code Coverage, and a refactored SAST stage:
stage('Dependency Scanning') {
// dependency scanning steps
}
stage('Unit Testing') {
// unit testing steps
}
stage('Code Coverage') {
// code coverage steps
}
stage('SAST - SonarQube') {
steps {
timeout(time: 60, unit: 'SECONDS') {
withSonarQubeEnv('sonar-qube-server') {
sh 'echo $SONAR_SCANNER_HOME'
sh '''
$SONAR_SCANNER_HOME/bin/sonar-scanner \
-Dsonar.projectKey=Solar-System-Project \
-Dsonar.sources=app.js \
-Dsonar.javascript.lcov.reportPaths=./coverage/lcov.info
'''
}
}
waitForQualityGate abortPipeline: true
}
}
Include the necessary argument to disable the Yarn audit analyzer in your dependency scanning configuration to prevent related errors.
After committing and pushing these changes, observe the pipeline execution:
- The SonarQube stage executes.
- The quality gate step waits and aborts the pipeline if the quality gate fails.
- The SonarQube webhook reports the quality gate status back to Jenkins.
For example, if the SonarQube analysis fails due to code coverage issues, you may find logs like this:
19:04:34.691 INFO The project is analyzed
...
SonarQube task "AtgKZXBMuU4i1nHuM" - Quality gate is "ERROR"
Pipeline aborted due to quality gate failure: ERROR
You can also verify the failed status on the SonarQube dashboard:
Review the SonarQube project details:
The webhook delivers a JSON payload similar to the following:
{
"serverUrl": "http://localhost:9000",
"taskId": "Ai7jRybMUtl41hUM",
"status": "SUCCESS",
"analysedAt": "2024-09-23T19:04:20+00:00",
"revision": "241b54d305c462f8c326f32d4cbfc330f8",
"changedAt": "2024-09-23T19:04:20+00:00",
"project": {
"key": "Solar-System-Project",
"name": "Solar-System-Project",
"url": "http://localhost:9000/dashboard?id=Solar-System-Project"
},
"branch": {
"name": "main",
"type": "BRANCH",
"isMain": true,
"url": "http://localhost:9000/dashboard?id=Solar-System-Project"
},
"qualityGate": {
"name": "Dasher-Quality-Gate",
"status": "ERROR"
}
}
In this scenario, the pipeline aborts when the quality gate fails (for example, due to insufficient code coverage).
Managing and Updating Quality Gate Settings
For subsequent demos or builds, update the quality gate configuration in SonarQube (for example, lower the coverage threshold) to pass the analysis. You can retrigger the pipeline or restart only the SonarQube stage. Once the quality gate status is successful, the build continues and completes successfully.
When reviewing the detailed quality gate conditions in SonarQube, you might see output like this:
[
{
"metric": "new_coverage",
"operator": "LESS_THAN",
"status": "NO_VALUE",
"errorThreshold": "80"
},
{
"metric": "coverage",
"operator": "LESS_THAN",
"value": "73.5",
"status": "OK",
"errorThreshold": "70"
},
{
"metric": "new_duplicated_lines_density",
"operator": "GREATER_THAN",
"status": "NO_VALUE",
"errorThreshold": "3"
},
{
"metric": "new_security_hotspots_reviewed",
"operator": "LESS_THAN",
"status": "NO_VALUE",
"errorThreshold": "100"
}
]
Check the SonarQube dashboard for final confirmation:
Further inspection of build details:
Through this integration, SonarQube helps identify quality issues and enforces quality gates to control the build process. Addressing the quality issues—such as increasing code coverage—ensures that the pipeline will eventually succeed.
Thank you for following this lesson on integrating SonarQube with Jenkins and refactoring your pipeline configuration.
Watch Video
Watch video content
Practice Lab
Practice lab