SonarQube Tutorial – Part V: Gitlab integration tutorial

We finally came to the last part of our SonarQube series! Hopefully these 5 articles made dealing with SonarQube much easier for all of you.

During this tutorial, I assume that you have finished the “SonarScanner for MSBuild tutorial” and you have your SonarQube server, sonar scanner and example project sets and ready to play with. If not please check the previous tutorials for instructions.

Keep in mind this article is part of our series on SonarQube!

  1. SonarQube tutorial – how to get started?
  2. SonarScanner tutorial
  3. SonarScanner for MSBuild tutorial
  4. Rules, quality profiles and quality gates
  5. Gitlab integration tutorial (you’re here!)

 

Overview

During this tutorial, I will show an example integration of SonarQube with Gitlab service. Our pull requests/merge requests will be decorated with inline SonarQube comments with issues that should be fixed. From our experience in Setapp it is the most efficient way of improving overall application code – doing it little by little as new code emerges or an old one needs to be updated.

Setting up Gitlab in docker is only for the purpose of creating a nice sandbox for this tutorial and should not be used in any other way – there are better ways to set up it.

 

Preparation

Enter SonarQube marketplace: http://localhost:9000/admin/marketplace?search=gitlab and install Gitlab plugin.

Marketplace Administration

After installation finish restart SonarQube

restart sq

 

Run docker run -d --name gitlab --publish 9008:443 --publish 9009:80 --publish 9010:22 gitlab/gitlab-ce:11.8.1-ce.0 to get our local Gitlab instance.

It may take about 2 minutes for it to start.

Enter http://localhost:9009 to create a password for our root user. Let it be for the sake of this tutorial very secure one: root1234

pass for root

Now we need to generate a Personal Access Token.

Enter http://localhost:9009/profile/personal_access_tokens and generate token with API permissions.

personal access tokens

Copy and save token value – we will need it later!

Create a project on http://localhost:9009

 

create project

Let’s name it SONAR_NET_PROJECT_NAME

 

create project 2

 

Assuming that we are in eShopOnWeb project root directory, then to migrate the repository run the following commands:

  1. Run git remote rename origin old-origin
  2. Run git remote add origin http://localhost:9009/root/SONAR_NET_PROJECT_NAME.git
  3. Run git push -u origin --all
  4. Run git push -u origin --tags

 

Create a new branch

  1. Run git branch test_pr_with_sonarqube
  2. Run git checkout test_pr_with_sonarqube
  3. Run git add .
  4. Run git commit -a -m "Some commit message"
  5. Run git push --set-upstream origin test_pr_with_sonarqube

 

Create Merge request

Enter http://localhost:9009/root/sonar_net_project_name/merge_requests

Press Create merge request as in the image below

Merge Request

In the new window, press Submit merge request

new merge request

Pipeline for out pull request will be waiting because we don’t have any runner configured to run it.

 

First analysis that decorates pull request with comments

Let’s edit our project DockerFile by adding a new section in a file:

Whole new Dockerfile:

FROM sonar-scanner-image:latest AS sonarqube_scan

WORKDIR /app

COPY . .

RUN ls -list

RUN dotnet restore

RUN dotnet test --logger:"xunit;LogFilePath=test-result.xml" /p:CollectCoverage=true /p:CoverletOutputFormat=opencover; exit 0

# this analysis will save data to server and we will be able to results of our changes.
RUN dotnet sonarscanner begin \
/k:"SONAR_NET_PROJECT_KEY" \
/n:"SONAR_NET_PROJECT_NAME" \
/v:"SONAR_PROJECT_VERSION" \
/d:sonar.login="SONAR_LOGIN_TOKEN" \
/d:sonar.exclusions="**/wwwroot/**, **/obj/**, **/bin/**" \
/d:sonar.links.homepage="CI_LINK_URL" \
/d:sonar.cs.opencover.reportsPaths="tests/FunctionalTests/coverage.opencover.xml,tests/IntegrationTests/coverage.opencover.xml,tests/UnitTests/coverage.opencover.xml" \
/d:sonar.cs.xunit.reportsPaths="**/test-result.xml"

RUN dotnet build --no-incremental

RUN dotnet sonarscanner end /d:sonar.login="SONAR_LOGIN_TOKEN"

# sonar.analysis.mode=preview - analyst mode that need to be choosen in order to make pull request decoration feature working in free SonarQube tier. Basically it will not save results to server.
# sonar.gitlab.api_version - gitlab api version to be used by gitlab plugin. We will use v4 value here
# sonar.gitlab.commit_sha - SHA of commit that we are analyzing. Usually set by variable provided by CI. Instruction how to get it will be provide further in this tutorial
# sonar.gitlab.ref_name - name of branch that we want to analyse. Usually set by variable provided by CI. For us it will be test_pr_with_sonarqube
# sonar.gitlab.project_id - our project ID. Usually set by variable provided by CI. Most likely for us it will be just 1. Can be checked in http://localhost:9009/root/sonar_net_project_name/edit under General project section.
# sonar.gitlab.url - URL to our gitlab instance. In this tutorial it should be http://localhost:9009
# sonar.gitlab.user_token - access token of user that will be used to make comments in our pull request. We generated it some time ago.
# Remember to replace SONAR_LOGIN_TOKEN with your token value.
RUN dotnet sonarscanner begin \
/k:"SONAR_NET_PROJECT_KEY" \
/n:"SONAR_NET_PROJECT_NAME" \
/v:"SONAR_PROJECT_VERSION" \
/d:sonar.login="SONAR_LOGIN_TOKEN" \
/d:sonar.exclusions="**/wwwroot/**, **/obj/**, **/bin/**" \
/d:sonar.links.homepage="CI_LINK_URL" \
/d:sonar.cs.opencover.reportsPaths="tests/FunctionalTests/coverage.opencover.xml,tests/IntegrationTests/coverage.opencover.xml,tests/UnitTests/coverage.opencover.xml" \
/d:sonar.cs.xunit.reportsPaths="**/test-result.xml" \
/d:sonar.analysis.mode=preview \
/d:sonar.gitlab.api_version="v4" \
/d:sonar.gitlab.commit_sha="CI_COMMIT_REF" \
/d:sonar.gitlab.ref_name="CI_COMMIT_REF_NAME" \
/d:sonar.gitlab.project_id="CI_PROJECT_ID" \
/d:sonar.gitlab.url="GITLAB_URL" \
/d:sonar.gitlab.user_token="SONAR_GITLAB_USER_TOKEN"

RUN dotnet build --no-incremental

RUN dotnet sonarscanner end /d:sonar.login="SONAR_LOGIN_TOKEN"

 

Replace CI_COMMIT_REF with commit SHA, that can be copied from http://localhost:9009/root/sonar_net_project_name/merge_requests/1/commits like in this screen:

test pr with sonarqube

In Dockerfile comments, you can find instructions about how to set required values.

Gitlab plugin documentation.

To run analysis execute the following command in the project root directory: docker build --network=host --no-cache .

 

Follow up

Playing with plugin quality gates

We have some options mentioned in the plugin documentation to use and play with. I found the most useful options related to issues types of quality gates. Currently, our pull request will be failed by the SonarQube plugin, because we have some critical issues found. http://localhost:9009/root/sonar_net_project_name/pipelines

sonarqube

Try to change this behavior using the  plugin documentation.

sonarqube

 

Show example solution (click here to open)
FROM sonar-scanner-image:latest AS sonarqube_scan

WORKDIR /app

COPY . .

RUN ls -list

RUN dotnet restore

RUN dotnet test --logger:"xunit;LogFilePath=test-result.xml" /p:CollectCoverage=true /p:CoverletOutputFormat=opencover; exit 0

# this analysis will save data to server and we will be able to results of our changes.
RUN dotnet sonarscanner begin \
/k:"SONAR_NET_PROJECT_KEY" \
/n:"SONAR_NET_PROJECT_NAME" \
/v:"SONAR_NET_PROJECT_VERSION" \
/d:sonar.login="SONAR_GITLAB_USER_TOKEN" \
/d:sonar.exclusions="**/wwwroot/**, **/obj/**, **/bin/**" \
/d:sonar.links.homepage="CI_LINK_URL" \
/d:sonar.cs.opencover.reportsPaths="tests/FunctionalTests/coverage.opencover.xml,tests/IntegrationTests/coverage.opencover.xml,tests/UnitTests/coverage.opencover.xml" \
/d:sonar.cs.xunit.reportsPaths="**/test-result.xml"

RUN dotnet build --no-incremental

RUN dotnet sonarscanner end /d:sonar.login="SONAR_GITLAB_USER_TOKEN"

RUN dotnet sonarscanner begin \
/k:"SONAR_NET_PROJECT_KEY" \
/n:"SONAR_NET_PROJECT_NAME" \
/v:"SONAR_NET_PROJECT_VERSION" \
/d:sonar.login="SONAR_GITLAB_USER_TOKEN" \
/d:sonar.exclusions="**/wwwroot/**, **/obj/**, **/bin/**" \
/d:sonar.links.homepage="CI_LINK_URL" \
/d:sonar.cs.opencover.reportsPaths="tests/FunctionalTests/coverage.opencover.xml,tests/IntegrationTests/coverage.opencover.xml,tests/UnitTests/coverage.opencover.xml" \
/d:sonar.cs.xunit.reportsPaths="**/test-result.xml" \
/d:sonar.analysis.mode=preview \
/d:sonar.gitlab.api_version="v4" \
/d:sonar.gitlab.commit_sha="CI_COMMIT_SHA" \
/d:sonar.gitlab.ref_name="CI_COMMIT_REF_NAME" \
/d:sonar.gitlab.project_id="CI_PROJECT_ID" \
/d:sonar.gitlab.url="GITLAB_URL" \
/d:sonar.gitlab.user_token="SONAR_GITLAB_USER_TOKEN" \
/d:sonar.gitlab.max_critical_issues_gate="-1"

RUN dotnet build --no-incremental

RUN dotnet sonarscanner end /d:sonar.login="SONAR_GITLAB_USER_TOKEN"

 

Other useful properties

sonar.gitlab.prefix_directory – may be used to fix the problem with Gitlab link to issue in branch code.

sonar.gitlab.json_mode – can be set to enable code quality report or SAST json generation that can be consumed as artifacts by Gitlab.

sonar.gitlab.failure_notification_mode – may be set to exit code in a scenario where we have multiple SonarScanner executions in a single repository – for example when we have .NET backend API and JS frontend application in a single repository and not in common solution.

 

Developer Edition/Branch plugin

Plugin integration works differently for the Developer edition. First of all, you don’t need to use sonar.analysis.mode=preview anymore and instead you can use sonar.branch.name="$CI_COMMIT_REF_NAME" parameter. Thanks to this branch analysis may also  be saved on the server side and reviewed there holding some extra useful information like new code coverage if provided.

Also, quality gate settings won’t be working anymore since short living branches/pull requests use hardcoded small Quality gates. Check the Rules, quality profiles and quality gates tutorial for more information.

 

Other code management services

Bitbucket, Azure DevOps, Github are also supported by either SonarQube out of the box integration provided in the Developer edition or by other 3rd party plugins that work on the same principle as the Gitlab one.

 

Cleaning up after a tutorial

To stop a container with running SonarQube server instance run following command:

docker container stop sonarqube

docker container stop gitlab

To remove also all docker containers run

docker container prune --force

Finally to remove all images used in this tutorial run

docker image remove sonarqube:7.5-community sonar-scanner-image gitlab/gitlab-ce:11.8.1-ce.0

Is Code Quality important to you?
Our experts can take care of that!

Let's create
something meaningful together!

Company data
  • Setapp Sp. z o.o.
  • VAT ID: PL7781465185
  • REGON: 301183743
  • KRS: 0000334616
Address
  • ul. Wojskowa 4
  • 60-792 Poznań, Poland
Contact us
Stay connected