Setting up automatic code quality gates

Patrik Malý
5 min readJan 15, 2023

--

Fighting the technical debt is one of the most challenging parts of software development. We all know the famous quotes like:

We are going to refactor it later!

The reality is that the developers usually forget or simply do not have time to do that (that’s why deadlines are hell!), which leads to increasing the technical debt, defect ratio, higher costs of maintenance and it can prolong the time it takes for new features to reach the production (Time to market). Looking for a solution? Well, automatic code quality gate is just a piece of puzzle, but might have a significant impact, because you can monitor whether you are going into the right direction. I am going to demonstrate a quite simple solution with Gitlab CI/CD pipelines & SonarQube (at least the TLS version 8.9 — enables pull request analysis).

So, let’s jump into the technical part :)

Sonarqube Quality Gate

Sonarqube is one of the best tools for the static code analysis. Sonarqube empowers all developers to write cleaner and safer code.

It provides two types of quality gates, which can determine whether the analysis will PASS or FAIL :

  • Overall code — used for all branches
  • New code — used for pull / merge requests & branches

Sonarqube provides a really sophisticated way of setting up the metrics. You can setup conditions for vulnerabilities, code coverage, duplications, or bugs. I have setup a quality gate for our demo with the following conditions:

Conditions definition for Demo quality gate
Quality Gate for overall & new code for this demo

Usually, it is not trivial to setup the quality gates, especially on the already running projects with existing issues within the code. However, there is a quite common approach to that — use the Clean as You Code strategy.

Clean as You Code is an approach to Code Quality that eliminates a lot of the challenges that come with traditional approaches. As a developer, you focus on maintaining high standards and taking responsibility specifically in the New Code you’re working on.

So, in case you have an existing project, I recommend you to focus on the new code at first.

Touch point

When you are considering an implementation of automatic quality gates, you need to find the right step within your software development lifecycle to receive feedback about the implemented code, ideally as soon as possible. The majority of the software engineering family uses an approach with pull / merge request within different kind of branching models like gitflow or github flow.

Gitlab CI provides a useful feature to run pipelines for merge requests which should be very helpful in scenarios when you would like to run specific job for merge request (i.e., verify the code quality). You need to create a gitlab-ci.yml file that will contain the job of checking the code quality with SonarQube and determining if the quality gate has been passed.

Here is an example of gitlab-ci.yml file for checking the code quality:

# The pipeline is used to verify the quality of the code during the merge
# requests. In case of the quality gate fail, the whole pipeline will fail
# and you will not be able to merge the merge request.

stages:
- verify

variables:
SONAR_PROJECT_NAME: "YOUR_SONAR_PROJECT_NAME"
SONAR_PROJECT_KEY: "YOUR_SONAR_PROJECT_KEY"
#if needed you can provide additional Maven options
MAVEN_OPTS: "-Dhttps.protocols=TLSv1.2"

workflow:
rules:
#run only for merge requests
- if: $CI_PIPELINE_SOURCE == "merge_request_event"

Verify code quality:
stage: verify
image:
name: maven:3.6.3-jdk-11

#used for cancel the previous Running / Pending job
interruptible: true

variables:
# Defines the location of the analysis task cache
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
# Tells git to fetch all the branches of the project, required by the analysis task
GIT_DEPTH: "0"
MAVEN_OPTS: "-Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository"
cache:
key: "${CI_JOB_NAME}"
paths:
- .sonar/cache
- .m2/repository
script:
- mvn sonar:sonar -Dsonar.qualitygate.wait=true -Dsonar.projectName=${SONAR_PROJECT_NAME} -Dsonar.projectKey=${SONAR_PROJECT_KEY}
# The value false is by default - it will force to fail the pipeline
allow_failure: false

There are some important parts of the code to mention. The workflow section allows you to define the condition for running the pipeline. You can adjust it with specific branches or other events. I also found very useful to set the interruptible option to true, which saves the resources of your gitlab executor in case of your merge request has been updated during the running analysis. It will cancel the job because there is an update on your merge request. Last but not least, the -Dsonar.qualitygate.wait=true flag forces the sonar analysis to wait until the quality gate is evaluated.

The only missing part is to setup a rule that will prevent the merge of merge requests in case of the pipeline fails. This can be achieved within the configuration of your project in the Merge Requests section with Pipeline must succeed option.

Merge requests configuration

Let’s put it all together

The general idea of the whole workflow is to verify the quality of the code in the earliest stage of software development lifecycle. Thanks to the parts described in the above sections we can achieve that using the merge requests.

The general workflow can be described with this simple diagram:

A simple workflow example of code quality verification

Now I would like to demonstrate the whole workflow on the following example. When I create a merge request, the merge request pipeline will be displayed on the merge request overview page and in case the quality gate fails, there will be no possibility to merge the code.

Merge request with failed pipeline

In this case, you are able to check what went wrong by checking the logs within your pipeline. There will be a message at the end with a similar content like this:

[ERROR] Failed to execute goal org.sonarsource.scanner.maven:sonar-maven-plugin:3.9.1.2184:sonar (default-cli) on project code-with-quarkus: QUALITY GATE STATUS: FAILED - View details on https://sonarqube-demo.com/quality/dashboard?id=demo.project&pullRequest=11 -> [Help 1]

The provided URL will redirect you to the results of the analysis, where you can see the failed conditions:

Merge request analysis provided by SonarQube

Pro Tip

If you are annoyed about searching the link to the analysis result within the logs of your pipeline, the SonarQube provides a solution with the so called Merge request Decorator. This allows you to display the results of the analysis within the comments section in the merge request.

Merge request decorator

Hope you enjoyed my first post, stay tuned and follow me! :)

--

--

Patrik Malý

Java Professional & Software Engineering Chapter Lead