Journey to Integrate SonarQube Analysis on every pull request - Part 1

akansh09

Akansh Singhal

Posted on August 2, 2024

Journey to Integrate SonarQube Analysis on every pull request - Part 1

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)

Challenge with Community Edition of SonarQube

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.

Problem Statement

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
Enter fullscreen mode Exit fullscreen mode

More can be checked here

SonarQube Login

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

Possible Ways to Create Project
Using Github

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

How Page will be look like?

  • 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:

Projects imported after selection

Now our task is to select way of analysis
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:

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.
Repository 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'
Enter fullscreen mode Exit fullscreen mode

Let's raise a PR:
Once PR is raised it will be shown like

After raising PR, actions will start executing itself:
Actions State

If you see analysis got failed:
Failed Analysis Reason

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.

💖 💪 🙅 🚩
akansh09
Akansh Singhal

Posted on August 2, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related