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!
- SonarQube tutorial – how to get started?
- SonarScanner tutorial
- SonarScanner for MSBuild tutorial
- Rules, quality profiles and quality gates
- 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.
After installation finish restart SonarQube
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
Now we need to generate a Personal Access Token.
Enter http://localhost:9009/profile/personal_access_tokens and generate token with API permissions.
Copy and save token value – we will need it later!
Create a project on http://localhost:9009
Let’s name it SONAR_NET_PROJECT_NAME
Assuming that we are in eShopOnWeb
project root directory, then to migrate the repository run the following commands:
- Run
git remote rename origin old-origin
- Run
git remote add origin http://localhost:9009/root/SONAR_NET_PROJECT_NAME.git
- Run
git push -u origin --all
- Run
git push -u origin --tags
Create a new branch
- Run
git branch test_pr_with_sonarqube
- Run
git checkout test_pr_with_sonarqube
- Run
git add .
- Run
git commit -a -m "Some commit message"
- 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
In the new window, press Submit 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:
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
Try to change this behavior using the plugin documentation.
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