Journey to Integrate SonarQube Analysis on every pull request - Part 1
Akansh Singhal
Posted on August 2, 2024
What is SonarQube?
SonarQube is an open-source platform for inspecting code quality. It performs static code analysis and reports vulnerabilities, code smells, and duplications in the code under analysis.
Problem Statement:
With the increase in code velocity and the shift-left approach, it is beneficial to execute linting at multiple phases of the development cycle:
During development: Use SonarLint.
On raising a PR: Run SonarQube on new code changes.
On merging a PR: Execute SonarQube on the develop branch.
If you want to know difference between SonarQube and SonarLint, you can refer this link.
If you are using SonarQube Community version, It only supports
- A Single Branch
- No PR level segregation.
- Segregation between Overall Code Issues and New Code Issues (Last commit on which analysis was done)
However, if you are using the Developer Edition of SonarQube, you can utilize its built-in features to keep your code clean. This edition does come at a cost.
To address the limitations of the Community Edition, we need to implement a custom solution. This involves writing a wrapper and creating a multi-branch Jenkins pipeline.
We will use some public APIs from GitHub and SonarQube to make this fully functional. In this blog, I will share my approach to solving this problem.
Installation & Setup
You can run sonarqube using docker command
$ docker run -d --name sonarqube -e SONAR_ES_BOOTSTRAP_CHECKS_DISABLE=true -p 9000:9000 sonarqube:latest
More can be checked here
Login with default username and password. Now you will see a page to create new project. There are two options:
- Either use any source code management tool like Github, BitBucket
- Other one is to Create New Project
If we are setting up with direct source code tool then we should be able to create communication channel between Github <> SonarQube. If Sonar is under some firewall or VPN. Please don't go ahead with this approach.
Now for this we need to perform following steps:
- Create App in Github :
- Go to Settings
- Move to Developer's Setting
- Create on New Github app button
- Add App Name & other mandatory details
- Now Save App
- You will get option to generate private key and client secret
- Add redirection and callback url as http://localhost:9000/ If you do not have any valid page.
- Add permission for Pull Request, Webhook, Projects for read & write access.
- Save the application and install it by moving to instal menu.
Once this is done move to SonarQube and Enter github app details like AppId, Client Id, Client Secret & Private Key and Save it. Once that is done, It will ask for authorization, Give permission.
Now you will get the option to select all those projects which you want to import in sonarqube from github.
After selection you will get projects like below image:
Now our task is to select way of analysis
Going with the Github Actions only in this approach, because I want to get most of the benefit from Github. You will get screen like below on selecting Github Actions:
Now go to repository which you want to integrate and enter generated token there in Secrets field and sonar url in other secret.
Now we want to execute every pull request raised to develop
, we can use below YAML file to do so.
name: Build
on:
pull_request:
branches: [develop]
jobs:
build:
name: Build and analyze
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Set up JDK 17
uses: actions/setup-java@v1
with:
java-version: 17
- name: Cache SonarQube packages
uses: actions/cache@v1
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache Maven packages
uses: actions/cache@v1
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Build and analyze
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
run: mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.projectKey=${{Project key generated}} -Dsonar.projectName='card'
After raising PR, actions will start executing itself:
If you see analysis got failed:
The initial attempt failed because the SonarQube server is not reachable from GitHub's public IP. For the integration to work, our SonarQube instance must be publicly accessible, which is often challenging in organizational settings. In my case, SonarQube is set up on my local machine (127.0.0.1:9000), which is not accessible to GitHub.
Above PR and actions can be checked on https://github.com/Akansh09/card/actions
Thank you for reading this. In the next part, we will discuss the second approach: integrating GitHub, Jenkins, and SonarQube.
If you have any questions or need further information, feel free to contact me at akanshsinghal7@gmail.com.
Posted on August 2, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.