28 May 2019Comments are off for this post.

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!

7 May 2019Comments are off for this post.

SonarQube Tutorial – Part IV: Rules, Quality Profiles and Quality Gates

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 (you're here!)
  5. Gitlab integration tutorial

 

Quality profiles

Overview

The Quality Profiles service is central to SonarQube since this is where you define your requirements by defining sets of rules (ex: Methods should not have a Cognitive Complexity greater than 15).

Ideally, all projects will be measured with the same profile for any given language, but that's not always practical. For instance, you may find:

The technological implementation differs from one application to another (for example, different coding rules may apply when building threaded or non-threaded Java applications).

You want to ensure stronger requirements on some of your applications (internal frameworks for example).

Etc.

Sonarqube Quality Profiles official documentation.

 

Quality profiles practical example

Let's assume that our example .NET project from the previous tutorial requires the creation of  some rules customization due to used solutions for C# profile.

Firstly we should create a copy of the C# profile and name it SONAR_NET_PROJECT way to keep naming in our example solution in order under this URL http://localhost:9000/profiles.

creating new quality profile

Then associate a new quality profile with our project.

change quality profiles

In our example project, we want to be able to throw general exceptions and this is causing a lot of rule violations for us.

http://localhost:9000/project/issues?id=SONAR_NET_PROJECT_KEY&resolved=false&rules=csharpsquid%3AS112

In order to address this, let's use our new profile and select active rules.

select active rules

Then search for a rule that we want to address: General exceptions should never be thrown and deactivate it.

deactivate rule

In root directory of our .NET example project run docker build --network=host --no-cache . to analyse project using our new Quality profile SONAR_NET_PROJECT way.

The deactivated rule should no longer be taken into consideration for our project.

http://localhost:9000/project/issues?id=SONAR_NET_PROJECT_KEY&resolved=false&rules=csharpsquid%3AS112

In custom profiles, it is possible to change every rule Severity according to our needs and for some rules to set values for given options.

customize rule in quality profiles

 

Quality gates

Overview

A quality gate is the best way to enforce a quality policy in your organization. It's there to answer ONE question: can I deliver my project to production today or not?

In order to answer this question, you define a set of Boolean conditions based on measurement thresholds against which projects are measured. For example:

No new blocker issues

Code coverage on new code greater than 80%

Etc.

Ideally, all projects will be verified against the same quality gate, but that's not always practical. For instance, you may find:

Technological implementation differs from one application to another (you might not require the same code coverage on new code for Web or Java applications).

You want to ensure stronger requirements on some of your applications (internal frameworks for example).

Etc.

Which is why you can define as many quality gates as you wish. Quality Gates are defined and managed in the Quality Gates page found on the top menu.

Sonarqube Quality Gates official documentation

 

Quality gate practical example

Let's assume that the Default Quality gate "Sonar way" isn't strict enough for our project, so we should create a new quality gate.

Enter http://localhost:9000/quality_gates and press the copy button as shown below.

copy sonar way quality gates

Let's name it Strict way and assign it to our project as shown below.

strict way add project quality gates

We don't want to have any tests skipped, so we add the new condition Skipped Unit Tests and set its threshold value to 0 as shown below.

add condition

We don't want to have any test failures, so we add the new condition Unit Test Failures and set its threshold value to 0 as shown below.

 

add condition #2

Now execute analysis again and check the result in the server dashboard http://localhost:9000/dashboard?id=SONAR_NET_PROJECT_KEY. The quality gate is still passing, isn't it?

Let's seed out a project with some invalid tests then!

Edit  tests\UnitTests\ApplicationCore\Services\BasketServiceTests\DeleteBasket.cs file by adding following code to it:

 
        [Fact(Skip = "skipped!")]
        public void Should_Be_Skipped()
        {
            throw new System.Exception();
        }

        [Fact]
        public void Should_Throw_Exception_And_Fail()
        {
            throw new System.Exception();
        }

 

Save changes and edit Dockerfile by changing Run dotnet test … to RUN dotnet test --logger "trx;LogFileName=TestResults.trx" /p:CollectCoverage=true /p:CoverletOutputFormat=opencover; exit 0

Run an analysis. You should see a failed quality gate as in the screen below.

failed quality gate sonar project name

 

Branches - developer edition

[Obsolete since SonarQube 7.7]

It is also worth mentioning that in the current version of pull request and short branch analysis feature in SonarQube server it is always using hard-coded Quality gate instead of one that is chosen for the project. Quality gate of our choice is executed only during analysis of long living branches.

Release of SonarQube 7.7 adds support of full quality gates for pull requests and short living branches.

 

What next?

We will wrap things up with the Gitlab integration tutorial, which will show us how to integrate SonarQube with pull requests.

 

Cleaning up after tutorial

To stop a container with running SonarQube server instance run following command: (don’t do this if you want to continue with the next tutorial!)

docker container stop sonarqube

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

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

5 May 2019Comments are off for this post.

SonarQube Tutorial – Part III: SonarScanner for MSBuild

During this tutorial, I assume that you have finished the SonarScanner tutorial and you have your SonarQube server, sonar scanner and example projects set 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 (you're here!)
  4. Rules, quality profiles and quality gates
  5. Gitlab integration tutorial

The main differences between SonarScanner and SonarScanner for MSBuild

The biggest difference is the way of executing MSBuild scanner - you need to build a project. In order to make it work you need to explicitly tell the scanner to begin "listening" for the project building and after the build is finished you need to inform it about it being finished. A concept example is presented below together with a link to documentation.

SonarScanner.MSBuild.exe begin /k:"project-key"

MSBuild.exe <path to solution.sln> /t:Rebuild

SonarScanner.MSBuild.exe end

Analyzing with SonarQube Scanner for MSBuild official documentation

 

First MSBuild SonarQube analysis

  1. Run git clone https://github.com/SetappPL/eShopOnWeb.git
  2. Run cd eShopOnWeb
  3. Create Dockerfile
  4. Open created Dockerfile and paste the code below
FROM sonar-scanner-image:latest AS sonarqube_scan

WORKDIR /app

COPY . .

# We are restoring package here in order to make logs clearer for us to read in sonar-scanner
# analysis execution section
RUN dotnet restore

RUN ls -list

# First difference between this scanner and the previous one is a way that we execute it.
# We need to execute 3 commands in order to trigger an analysis. Firstly we need to begin Sonarqube
# analysis and pass analysis parameters. Then we need to build an application and then finally we need to
# to explicitly end analysis.
# What is more syntax of passing parameters varies from the previous scanner. We have predefined special
# prefixes for project key, project name and project versions instead of passing them as casual
# parameter. Also instead of adding prefix "/D" for this scanner, we need to ad "/d:" instead.
# The last, but not least difference is that we need to authorize on both begin and end step
# if Sonarqube project is private.
# Except for the above differences other parameters is mostly working the same.
RUN dotnet sonarscanner begin \
/k:"SONAR_NET_PROJECT_KEY" \
/n:"SONAR_NET_PROJECT_NAME" \
/v:"SONAR_NET_PROJECT_VERSION" \
/d:sonar.login="SONAR_LOGIN_TOKEN" \
/d:sonar.exclusions="**/wwwroot/**, **/obj/**, **/bin/**" \
/d:sonar.links.homepage="CI_LINK_URL"

RUN dotnet build --no-incremental

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

 

  1. Remember to use the value of SONAR_LOGIN_TOKEN generated in previous tutorials.
  2. Run docker build --network=host --no-cache . to execute code analysis. You will be running this command multiple time during the next examples. Remember to execute them in the project root directory!
  3. Enter http://localhost:9000/dashboard?id=SONAR_NET_PROJECT_KEY to see analysis result

 

Add code coverage

Adding new SonarQube parameters in order to improve analysis is almost the same as in SonarScanner, but since we have 3 test projects in the example solution we can play with supporting that scenario.

We need to add a new package to our solution to generate code coverage reports:

  1. Run dotnet add tests\FunctionalTests\FunctionalTests.csproj package coverlet.msbuild --version 2.3.2
  2. Run dotnet add tests\IntegrationTests\IntegrationTests.csproj package coverlet.msbuild --version 2.3.2
  3. Run dotnet add tests\UnitTests\UnitTests.csproj package coverlet.msbuild --version 2.3.2

If you don’t have dotnet core on your computer then add the above command to dockerfile as RUN .. commands after COPY . .. In that case, remember to change \ to / in paths to make it work!

Add RUN dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover after RUN dotnet restore in dockerfile to have code coverage generated

Using SonarC# official documentation try to make code coverage working.

 

 

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

WORKDIR /app

COPY . .

RUN dotnet restore
# Running tests with following parameters generate code coverage report
RUN dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover

RUN ls -list

# sonar.cs.opencover.reportsPaths - a similar case like for javascript code coverage parameter
# we need to pass paths to coverage reports.
RUN dotnet sonarscanner begin \
/k:"SONAR_NET_PROJECT_KEY" \
/n:"SONAR_NET_PROJECT_NAME" \
/v:"SONAR_NET_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"

# --no-incremental option marks the build as unsafe for incremental build. 
# This flag turns off incremental compilation and forces a clean rebuild of the project's dependency graph.
RUN dotnet build --no-incremental

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

 

 

Add unit test results to analysis

Generating unit test results in XML format isn’t too straightforward with the current .NET core framework, so instead, we will generate it with the Visual studio tests format (.trx). Creating xunit test in XML format would require adding new packages like xunit.testLogger which makes no sense since we have test results with an out of the box solution.

In order to achieve it add --logger "trx;LogFileName=TestResults.trx" to command executing tests, so it will be looking like this: RUN dotnet test --logger "trx;LogFileName=TestResults.trx" /p:CollectCoverage=true /p:CoverletOutputFormat=opencover

Using SonarC# official documentation on Unit Test Execution Results Import try to add unit tests result to the analysis.
 

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

WORKDIR /app

COPY . .

RUN dotnet restore
# Running tests with new option --logger presented below will generate test results in visual studio format
RUN dotnet test --logger "trx;LogFileName=TestResults.trx" /p:CollectCoverage=true /p:CoverletOutputFormat=opencover

RUN ls -list

# sonar.cs.vstest.reportsPaths - paths to visual studio test results format.
# In this example instead of providing the full path for all 3 reports I used pattern matching for it.
RUN dotnet sonarscanner begin \
/k:"SONAR_NET_PROJECT_KEY" \
/n:"SONAR_NET_PROJECT_NAME" \
/v:"SONAR_NET_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.vstest.reportsPaths="**/TestResults.trx"

RUN dotnet build --no-incremental

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

 

 

Add an advanced rule ignoring for patterns

Currently, MSBuild scanner doesn’t support defining multicriteria rules on the scanner side, so we need to define them on the server side which is harder to maintain in my opinion. It can be defined in the general settings section under Analysis Scope section at the bottom of the page.

To get there enter this link http://localhost:9000/project/settings?category=exclusions&id=SONAR_NET_PROJECT_KEY.

Configuration is even simpler than it is for SonarScanner since we need to configure only the Rule Key Pattern and File Path Pattern. For example, the following screen shows a configuration for ignoring rule General exceptions and should never be thrown in all controllers.

patterns

 

Add issues raised by Roslyn analyzers

SonarQube analysis works out of the box with Roslyn analyzers as mentioned in the SonarQube documentation.

Let’s add a new analyzer to our project to test this feature. In order to do this, we need to add the following new package - ClrHeapAllocationAnalyzer.

  1. Run dotnet add src\ApplicationCore\ApplicationCore.csproj package ClrHeapAllocationAnalyzer --version 1.0.0.9
  2. Run dotnet add src\Infrastructure\Infrastructure.csproj package ClrHeapAllocationAnalyzer --version 1.0.0.9
  3. Run dotnet add src\Web\Web.csproj package ClrHeapAllocationAnalyzer --version 1.0.0.9

 

If you don’t have dotnet core on your computer then add the above command to dockerfile as RUN .. commands after COPY . .. In that case, remember to change \ to / in paths to make it work!

Run docker build --network=host --no-cache . to execute analysis and see results

scm issues

 

Add SCM information to SonarQube

In the SonarQube project dashboard you may have noticed a warning about no SCM information found.

scm2

 

Without it, SonarQube cannot automatically assign issues to developers who have written problematic code and cannot determine who’s code it is.

In order to fix this, we need to provide SCM information to SonarQube. We can do this in two ways. The first way is to set SCM configuration in SonarQube options - http://localhost:9000/project/settings?category=scm&id=SONAR_NET_PROJECT_KEY, which isn’t recommended.

The second way is to provide local SCM files during SonarQube analysis - in order to do this we need to modify .dockerignore file and remove .git entry.

After the next analysis, SonarQube should be able to use SCM data.

 

Keeping SonarQube MSBuild scanner configuration in the configuration file

Similar to SonarScanner we can keep configuration in  SonarQube.Analysis.xml file:

<?xml version="1.0" encoding="utf-8" ?>
<SonarQubeAnalysisProperties  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.sonarsource.com/msbuild/integration/2015/1">
  <Property Name="sonar.exclusions">**/wwwroot/**, **/obj/**, **/bin/**</Property>
  <Property Name="sonar.verbose">true</Property>
</SonarQubeAnalysisProperties>

 

We may keep the configuration file anywhere in the project, but we need to pass a path to configuration to command like this: /s:"$(pwd)/SonarQube.Analysis.xml". What is more we can’t define all properties this way - for example, we can’t define sonar.projectBaseDir.

 

Changing the leak period

The leak period is used to define what is a new code for our project. By default, the leak period is set to the project version, but I found out that in practice quite often depending on the project version is problematic and makes no sense. It may make sense to change it to a number of days, for example to a sprint length (in calendar days).

We can change it either globally as a default value or per project. To change it globally go to http://localhost:9000/admin/settings and at the bottom of the page you can change New Code Period property to a different value for example to 14 as in the screen below.

new code period

What next?

In the next tutorial, we will play a little with customization of server rules and behaviors in analysis context in Rules, quality profiles and quality gates tutorial.

We will wrap things up with the Gitlab integration tutorial, which will show us how to integrate SonarQube with pull requests.

 

Cleaning up after a tutorial

To stop a container with running SonarQube server instance run following command: (don’t do this if you want to continue with the next tutorials!)

docker container stop sonarqube

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

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

23 April 2019Comments are off for this post.

SonarQube Tutorial – Part II: How to Use SonarScanner?

In the previous tutorial we set up our environment and ran our first analysis, but what is this tutorial about? While SonarQube is a server that keeps our process analysis and project data, it also requires something that will provide its necessary data. That's why we need SonarScanner and in this article you will get to know what it is and how to use it!

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

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

 

What is SonarScanner and why do we need it?

SonarScanner is a separate client type application that in connection with the SonarQube server will run project analysis and then send the results to the SonarQube server to process it. SonarScanner can handle most programming languages supported by SonarQube except C# and VB. It is usually located on continuous integration agents (workers) or in separate docker images depending on your project flow.

 

Requirements

During this tutorial, I assume that you have finished the SonarQube introduction and you have your SonarQube server, sonar scanner and example projects set and ready to play with. If not please check the tutorial for "SonarScanner tutorial" for instructions.

 

Add project name

Let's begin our tutorial by editing our dockerfile by adding a project name property.

FROM sonar-scanner-image:latest AS sonarqube_scan

WORKDIR /app

COPY . .

RUN ls -list

# sonar.projectName property used for providing human-friendly project name in addition 
# for projectKey
RUN sonar-scanner \
    -Dsonar.host.url="http://localhost:9000" \
    -Dsonar.projectKey="SONAR_PROJECT_KEY" \
    -Dsonar.sources="src" \
    -Dsonar.projectName="SONAR_PROJECT_NAME"

 

Run docker build --network=host --no-cache. to execute code analysis. You will be running this command multiple times during the next examples. Remember to execute them in the project root directory!

Enter http://localhost:9000/dashboard?id=SONAR_PROJECT_KEY

It looks better, doesn't it?

 

Add duplication exclusion

Let's assume that our current duplication metric is false and we need to add some exclusion for duplications. Let's exclude the passport.js file using official analysis parameters documentation and using this document (example patterns are at the bottom).

 

 

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

WORKDIR /app

COPY . .

RUN ls -list

# sonar.cpd is group of settings for duplication area
# sonar.cpd.exclusions adding exclusions setting to area name is common pattern
# in Sonarqube.
RUN sonar-scanner \
    -Dsonar.host.url="http://localhost:9000" \
    -Dsonar.projectKey="SONAR_PROJECT_KEY" \
    -Dsonar.sources="src" \
    -Dsonar.projectName="SONAR_PROJECT_NAME" \
    -Dsonar.cpd.exclusions="**passport.js"

 

 

 

Add exclusion from analysis

For this example, let's assume that we don't want to analyse any login files in the src/routes/login data and routes folder.

http://localhost:9000/code?id=SONAR_PROJECT_KEY&selected=SONAR_PROJECT_KEY%3Asrc%2Froutes%2Flogin

Using official analysis parameters documentation and using this document (example patterns are at the bottom) try to achieve it.

 

 

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

WORKDIR /app

COPY . .

RUN ls -list

# sonar.exclusions it is global exclusion from the whole analysis.
RUN sonar-scanner \
    -Dsonar.host.url="http://localhost:9000" \
    -Dsonar.projectKey="SONAR_PROJECT_KEY" \
    -Dsonar.sources="src" \
    -Dsonar.projectName="SONAR_PROJECT_NAME" \
    -Dsonar.cpd.exclusions="**passport.js" \
    -Dsonar.exclusions="**/login/Login.*"

 

 

 

Add code coverage to analysis

We are still missing some pieces in our analysis to be as efficient as possible - code coverage is the key missing part. Firstly modify our dockerfile to look like this:

FROM sonar-scanner-image:latest AS sonarqube_scan

WORKDIR /app

COPY . .

# In order to run tests we need to install dependencies
RUN npm install
# To have nicely generated code coverage report lets run test with the following parameters.
RUN npm run test -- --ci --coverage

RUN ls -list

RUN sonar-scanner \
    -Dsonar.host.url="http://localhost:9000" \
    ...

 

Then using official SonarJS documentation try to achieve it.

 

 

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

WORKDIR /app

COPY . .

RUN npm install
RUN npm run test -- --ci --coverage

RUN ls -list

# In Sonarqube support multiple formats of test coverage.
# For this case we will use javascript since its default 
# format generated by the testing framework in the example project. 
# sonar.javascript.lcov.reportPaths path to lcov.info file with code coverage
RUN sonar-scanner \
    -Dsonar.host.url="http://localhost:9000" \
    -Dsonar.projectKey="SONAR_PROJECT_KEY" \
    -Dsonar.sources="src" \
    -Dsonar.projectName="SONAR_PROJECT_NAME" \
    -Dsonar.cpd.exclusions="**passport.js" \
    -Dsonar.exclusions="**/login/Login.*" \
    -Dsonar.javascript.lcov.reportPaths="coverage/lcov.info"

 

 

 

Add code coverage file exclusions from the analysis

It looks better now, but it makes no sense for us to count coverage for everything. Let's assume that we don't want to calculate coverage for data and routes folders and files containing the word Utils.

Using the official SonarJS documentation try to achieve it.

 

 

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

WORKDIR /app

COPY . .

RUN npm install
RUN npm run test -- --ci --coverage

RUN ls -list

# sonar.coverage.exclusions is another example of how exclusions work.
RUN sonar-scanner \
    -Dsonar.host.url="http://localhost:9000" \
    -Dsonar.projectKey="SONAR_PROJECT_KEY" \
    -Dsonar.sources="src" \
    -Dsonar.projectName="SONAR_PROJECT_NAME" \
    -Dsonar.cpd.exclusions="**passport.js" \
    -Dsonar.exclusions="**/login/Login.*" \
    -Dsonar.javascript.lcov.reportPaths="coverage/lcov.info" \
    -Dsonar.coverage.exclusions="src/data/**,src/routes/**,**/*Utils*"

 

 

 

Add unit test results to analysis

Firstly we need to add a new package to our project. Run npm i -D jest-sonar-reporter. If you don’t have npm on your computer then add this to dockerfile as RUN npm i -D jest-sonar-reporter after COPY . . command.

Then we need to add some configuration to jest.config.js:

testResultsProcessor: "jest-sonar-reporter",

 

Using the above tips, official analysis parameters documentation and official "narrowing the focus" documentation try to achieve it.

 

 

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

WORKDIR /app

COPY . .

RUN npm install
RUN npm run test -- --ci --coverage

RUN ls -list

# Adding tests to an analysis isn't as straightforward as another thins in previous examples.
# In addition to providing Sonarqube with a path to generated report we need also to specify
# test directory which in our example is the same as sources, so we need to add also
# distinction between source files and test files by adding "inclusions" to test area
# sonar.testExecutionReportPaths - path to test execution report
# sonar.tests - test directory
# sonar.test.inclusions - pattern to recognize files as tests files.
RUN sonar-scanner \
    -Dsonar.host.url="http://localhost:9000" \
    -Dsonar.projectKey="SONAR_PROJECT_KEY" \
    -Dsonar.sources="src" \
    -Dsonar.projectName="SONAR_PROJECT_NAME" \
    -Dsonar.cpd.exclusions="**passport.js" \
    -Dsonar.exclusions="**/login/Login.*" \
    -Dsonar.javascript.lcov.reportPaths="coverage/lcov.info" \
    -Dsonar.coverage.exclusions="src/data/**,src/routes/**,**/*Utils*" \
    -Dsonar.testExecutionReportPaths="test-report.xml" \
    -Dsonar.tests="src" \
    -Dsonar.test.inclusions="**test.js"

 

 

 

Add an advanced rule ignoring for patterns

Some rules are very useful and give us a lot of value, but they don’t make sense everywhere and we want to either exclude some files from it or restrict the rule only to some files.

Things like this can be done using either sonar.issue.ignore.multicriteria for ignoring the rule for certain patterns or with sonar.issue.enforce.multicriteria when we enforce usage of rules only to a certain pattern. The above properties aren’t well documented in the official documentation and the best example with a description that I could find was this bug about outdated documentation.

Let’s assume that in our project rule Default export names and file names should match and shouldn't be applied for server.js file. What is more rule Properties of variables with "null" or "undefined" values should not be accessed as well and shouldn’t be applied to any files ending with port.js.

Try to achieve it using the above example.

Rule names can be retrieved by entering http://localhost:9000/project/issues?id=SONAR_PROJECT_KEY&resolved=false and pressing on the issues like on screens below.

Sonar - project name

sonar project name 2

 

 

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

WORKDIR /app

COPY . .

RUN npm install
RUN npm run test -- --ci --coverage

RUN ls -list

# sonar.issue.ignore.multicriteria - defines multicriteria names, comma separated like X1,js1 for which rule will be ignored
# sonar.issue.ignore.multicriteria.X1.ruleKey - used to choose on which rule this multicriteria will work like javascript:S3317
# sonar.issue.ignore.multicriteria.X1.resourceKey - pattern for which multicriteria will be applied
RUN sonar-scanner \
    -Dsonar.host.url="http://localhost:9000" \
    -Dsonar.projectKey="SONAR_PROJECT_KEY" \
    -Dsonar.sources="src" \
    -Dsonar.projectName="SONAR_PROJECT_NAME" \
    -Dsonar.cpd.exclusions="**passport.js" \
    -Dsonar.exclusions="**/login/Login.*" \
    -Dsonar.javascript.lcov.reportPaths="coverage/lcov.info" \
    -Dsonar.coverage.exclusions="src/data/**,src/routes/**,**/*Utils*" \
    -Dsonar.testExecutionReportPaths="test-report.xml" \
    -Dsonar.tests="src" \
    -Dsonar.test.inclusions="**test.js" \
    -Dsonar.issue.ignore.multicriteria="js1,js2" \
    -Dsonar.issue.ignore.multicriteria.js1.ruleKey="javascript:S3317" \
    -Dsonar.issue.ignore.multicriteria.js1.resourceKey="src/server.js" \
    -Dsonar.issue.ignore.multicriteria.js2.ruleKey="javascript:S2259" \
    -Dsonar.issue.ignore.multicriteria.js2.resourceKey="**/*port.js"

 

 

 

Finishing touches

Add links to a project

To improve our workflow and to make navigation more comfortable it is useful to add quick links to the project's website and continuous integration executions.

Using official analysis parameters documentation try to achieve it.

 

 

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

WORKDIR /app

COPY . .

RUN npm install
RUN npm run test -- --ci --coverage

RUN ls -list

# Sonarqube can also show links to another application that are connected
# with the development process. In this example, we are filling 2 links
# sonar.links.ci - link for continuous integration server
# sonar.links.homepage - link for project homepage - usually project repository URL
RUN sonar-scanner \
    -Dsonar.host.url="http://localhost:9000" \
    -Dsonar.projectKey="SONAR_PROJECT_KEY" \
    -Dsonar.sources="src" \
    -Dsonar.projectName="SONAR_PROJECT_NAME" \
    -Dsonar.cpd.exclusions="**passport.js" \
    -Dsonar.exclusions="**/login/Login.*" \
    -Dsonar.javascript.lcov.reportPaths="coverage/lcov.info" \
    -Dsonar.coverage.exclusions="src/data/**,src/routes/**,**/*Utils*" \
    -Dsonar.testExecutionReportPaths="test-report.xml" \
    -Dsonar.tests="src" \
    -Dsonar.test.inclusions="**test.js" \
    -Dsonar.issue.ignore.multicriteria="js1,js2" \
    -Dsonar.issue.ignore.multicriteria.js1.ruleKey="javascript:S3317" \
    -Dsonar.issue.ignore.multicriteria.js1.resourceKey="src/server.js" \
    -Dsonar.issue.ignore.multicriteria.js2.ruleKey="javascript:S2259" \
    -Dsonar.issue.ignore.multicriteria.js2.resourceKey="**/*port.js" \
    -Dsonar.links.ci="CI_LINK_URL" \
    -Dsonar.links.homepage="PROJECT_URL"

 

 

 

Make the project private

The last, but not least thing to do is to make the project private.

Firstly let's allow the sonar-administrators group to execute analysis and revoke permissions from group Anyone in http://localhost:9000/admin/permissions.

permissions

Secondly, we need to change the project type to Private and allow sonar-administrators group to execute analysis since the project was created with old permission matrix in http://localhost:9000/project_roles?id=SONAR_PROJECT_KEY.

Lastly we should force authentication in the whole of SonarQube - we can achieve it by entering and following the link http://localhost:9000/admin/settings?category=security and switching Force user authentication setting to On like on the screen below.

admin

Currently you can only reach our server when you log in. Anonymous analysis will also not work anymore. Try to make it work again using official analysis parameters documentation.

 

 

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

WORKDIR /app

COPY . .

RUN npm install
RUN npm run test -- --ci --coverage

RUN ls -list

# sonar.login - a place for a token that will be used to authorise analysis in Sonarqube server
RUN sonar-scanner \
    -Dsonar.host.url="http://localhost:9000" \
    -Dsonar.projectKey="SONAR_PROJECT_KEY" \
    -Dsonar.sources="src" \
    -Dsonar.projectName="SONAR_PROJECT_NAME" \
    -Dsonar.cpd.exclusions="**passport.js" \
    -Dsonar.exclusions="**/login/Login.*" \
    -Dsonar.javascript.lcov.reportPaths="coverage/lcov.info" \
    -Dsonar.coverage.exclusions="src/data/**,src/routes/**,**/*Utils*" \
    -Dsonar.testExecutionReportPaths="test-report.xml" \
    -Dsonar.tests="src" \
    -Dsonar.test.inclusions="**test.js" \
    -Dsonar.issue.ignore.multicriteria="js1,js2" \
    -Dsonar.issue.ignore.multicriteria.js1.ruleKey="javascript:S3317" \
    -Dsonar.issue.ignore.multicriteria.js1.resourceKey="src/server.js" \
    -Dsonar.issue.ignore.multicriteria.js2.ruleKey="javascript:S2259" \
    -Dsonar.issue.ignore.multicriteria.js2.resourceKey="**/*port.js" \
    -Dsonar.links.ci="CI_LINK_URL" \
    -Dsonar.links.homepage="PROJECT_URL" \
    -Dsonar.login="SONAR_LOGIN_TOKEN"

 

 

 

Keeping SonarQube scanner configuration in a configuration file

Instead of keeping configuration as command line parameters we may also define them in the sonar-project.properties file that must be located in the project root directory. We can move all or some settings there:

sonar.host.url=http://localhost:9000
sonar.projectKey=SONAR_PROJECT_KEY 
sonar.sources=src 
sonar.projectName=SONAR_PROJECT_NAME 
sonar.cpd.exclusions=**passport.js 
sonar.exclusions=**/login/Login.* 
sonar.javascript.lcov.reportPaths=coverage/lcov.info 
sonar.coverage.exclusions=src/data/**,src/routes/**,**/*Utils* 
sonar.testExecutionReportPaths=test-report.xml 
sonar.tests=src 
sonar.test.inclusions=**test.js 
sonar.issue.ignore.multicriteria=js1,js2 
sonar.issue.ignore.multicriteria.js1.ruleKey=javascript:S3317 
sonar.issue.ignore.multicriteria.js1.resourceKey=src/server.js 
sonar.issue.ignore.multicriteria.js2.ruleKey=javascript:S2259 
sonar.issue.ignore.multicriteria.js2.resourceKey=**/*port.js
sonar.links.ci=CI_LINK_URL
sonar.links.homepage=PROJECT_URL
sonar.login=SONAR_LOGIN_TOKEN

Our new dockerfile:

FROM sonar-scanner-image:latest AS sonarqube_scan

WORKDIR /app

COPY . .

RUN npm install
RUN npm run test -- --ci --coverage

RUN ls -list

RUN sonar-scanner

 

What next?

In the next tutorial, we will take a look into SonarScanner for MSBuild and check what are the differences between it and SonarScanner and work with its unique features.

Then we will play a little with customization of server rules and behaviors in analysis context in Rules, quality profiles and quality gates tutorial.

We will wrap things up with a Gitlab integration tutorial, which will show us how to integrate SonarQube with pull requests.

 

Cleaning up after tutorial

To stop a container running SonarQube server instance run the following command: (don’t do this if you want to continue with the next tutorials!)

docker container stop sonarqube

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

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

15 April 2019Comments are off for this post.

SonarQube tutorial – Part I: How to Get Started?

Have you heard about SonarQube before? Do you want to know how to use it and what kind of value it can bring to the software development process?

You’re in a right place! We’ve prepared a series of 5 articles which will make dealing with SonarQube much easier.

  1. SonarQube - introduction (you're here!)
  2. SonarScanner tutorial 
  3. SonarScanner for MSBuild tutorial 
  4. Rules, quality profiles and quality gates 
  5. Gitlab integration tutorial

 

So let’s get started! First of all – what is SonarQube?

SonarQube is an open source platform to perform automatic reviews with static analysis of code to detect bugs, code smells and security vulnerabilities on 25+ programming languages

SonarQube.org

SonarQube is a very universal tool for static code analysis that has become more or less the industry standard. Because it is covering the most popular programming languages, it’s the most complex solution that covers most use cases using a single application. This allows you to not use a separate app for every programming language that has to be analyzed.

 

What kind of value SonarQube brings

It helps to catch a lot of problems in code and thanks to its philosophy to focus on the new code it helps to fix issues as soon as they appear.

Keeping code clean, simple and easy to read is also a lot easier with SonarQube since a lot of rules also focus on those aspects which starts to pay off a lot after some time.

A lot more detailed feature descriptions that are widely used are described on the official SonarQube page and there is no point in duplicating them here.

 

What is this series of tutorials about?

The main goal of this tutorial is to show how to configure SonarQube scanners for both .NET example projects and JS example projects. SonarQube is used here as a Docker Image for demonstration purposes and should not be used in this configuration in production.

The reason for creating a custom image that is used to execute SonarQube analysis is to make sonar scanner syntax easier to read and modify during this tutorial than running it as the console commands.

 

Technical requirements

Docker - https://www.docker.com/get-started

Git - https://git-scm.com/downloads

 

First steps

Setup SonarQube

1. Run SonarQube server

docker run -d --name sonarqube -p 9000:9000 sonarqube:7.5-community

 

2. Run docker ps and check if a server is up and running

docker image

 

3. Wait for the server to start and log in to SonarQube server on http://localhost:9000 using default credentials: login: admin password: admin

4. Go to: http://localhost:9000/account/security/ and generate a token.

tokens image

 

5. Copy token value and save it somewhere, since you won't be able to see it again! You will need it later in the tutorial.

6. Create a new folder for SonarQube scanner image dockerfile. Run mkdir sonarqube-scanner

7. Run cd sonarqube-scanner

8. Create dockerfile

9. Open created Dockerfile and paste the code below:

sonarqube-scanner dockerfile (click here to open)
# This is docker file for our sonarqube-scanner. You don't need to read it since
# the goal of this tutorial isn't about teaching docker or about presenting the best 
# way for creating Sonarqube scanner image. Of course feel free to check on it if you like.
# Get dotnetcore SDK
FROM microsoft/dotnet:2.2.104-sdk AS sonarqube

# Install OpenJDK-8
RUN apt-get update && \
    apt-get install -y openjdk-8-jdk && \
    apt-get install -y ant && \
    apt-get clean;

# Fix certificate issues
RUN apt-get update && \
    apt-get install ca-certificates-java && \
    apt-get clean && \
    update-ca-certificates -f;

# Setup JAVA_HOME
ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64/
RUN export JAVA_HOM

# Env variables
ENV NODE_VERSION 10.13.0
ENV NODE_DOWNLOAD_SHA b4b5d8f73148dcf277df413bb16827be476f4fa117cbbec2aaabc8cc0a8588e1

# Install node.js
RUN curl -SL "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.gz" --output nodejs.tar.gz \
    && echo "$NODE_DOWNLOAD_SHA nodejs.tar.gz" | sha256sum -c - \
    && tar -xzf "nodejs.tar.gz" -C /usr/local --strip-components=1 \
    && rm nodejs.tar.gz \
    && ln -s /usr/local/bin/node /usr/local/bin/nodejs

# Install global tools
RUN dotnet tool install -g dotnetsay
RUN dotnet tool install --global dotnet-sonarscanner --version 4.5.0

# Add global tools folder to PATH
ENV PATH="${PATH}:/root/.dotnet/tools"

# Get required packages for sonar scanner
RUN apt-get update && apt-get -y install curl bash unzip yarn bzip2

WORKDIR /root

ENV LATEST='sonar-scanner-cli-3.3.0.1492-linux.zip'

# Get & install sonar scanner
RUN env && \
curl -OL 'https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/'$LATEST && \
mkdir sonar_scanner && unzip -d sonar_scanner $LATEST && mv sonar_scanner/* sonar_home && \
rm -rf sonar_scanner $LATEST

# Add sonar scanner to PATH
ENV SONAR_RUNNER_HOME=/root/sonar_home
ENV PATH ${SONAR_RUNNER_HOME}/bin:$PATH

ARG SONAR_HOST
ARG SONAR_LOGIN_TOKEN

# make temporary folder for seed analysis for javascript scanner
WORKDIR /root/temp1
RUN mkdir src
RUN touch src/test.js
# Init sonarscanner cache with plugins
RUN sonar-scanner -Dsonar.host.url=$SONAR_HOST -Dsonar.login=$SONAR_LOGIN_TOKEN -Dsonar.analysis.mode=preview -Dsonar.projectKey="pluginsSeedJS" -Dsonar.sources="src"

WORKDIR /root

# Remove temporary folder
RUN rm /root/temp1 -rf

# make temporary folder for seed analysis
WORKDIR /root/temp2
# Init sonarscanner cache with plugins for .NET scanner
RUN dotnet sonarscanner begin /k:"pluginsSeedNET" /d:sonar.host.url=$SONAR_HOST /d:sonar.login=$SONAR_LOGIN_TOKEN /d:sonar.analysis.mode=preview
RUN dotnet new sln --name FooBar
RUN dotnet new mvc --name Foo --output Foo
RUN dotnet new console --name Bar --output Bar
RUN dotnet sln add ./Foo/Foo.csproj
RUN dotnet sln add ./Bar/Bar.csproj
RUN dotnet restore
RUN dotnet build FooBar.sln
RUN dotnet sonarscanner end /d:sonar.login=$SONAR_LOGIN_TOKEN ; exit 0

WORKDIR /root

# Remove temporary folder
RUN rm /root/temp2 -rf

 

10. Build sonarqube-scanner image by executing following command in a console in sonarqube-scanner directory:

docker build --network=host --tag sonar-scanner-image:latest --build-arg SONAR_HOST="http://localhost:9000" --build-arg SONAR_LOGIN_TOKEN="TOKEN_VALUE" .

Remember to replace “TOKEN_VALUE” with your token from point 4.

Setup example project
  1. Run cd ..
  2. Run git clone https://github.com/SetappPL/react-starter-kit.git
  3. Run cd react-starter-kit
  4. Add following .dockerignore file to the root directory:
.dockerignore
.vs
node_modules

5. Open Dockerfile and replace it with the following code:

# It is our freshly build sonar-scanner-image from previous steps that
# is used here as a base image in docker file that we will be working on
FROM sonar-scanner-image:latest AS sonarqube_scan

# Here we are setting up a working directory to /app. It is like using `cd app` command
WORKDIR /app

# Copying all files from the project directory to our current location (/app) in image
# except patterns mention in .dockerignore
COPY . .

# Execution of example command. Here it is used to show a list of files and directories.
# It will be useful in later exercises in this tutorial. 
RUN ls -list

# To execute sonar-scanner we just need to run "sonar-scanner" in the image. 
# To pass Sonarqube parameter we need to add "-D"prefix to each as in the example below
# sonar.host.url is property used to define URL of Sonarqube server
# sonar.projectKey is used to define project key that will be used to distinguish it in 
# sonarqube server from other projects
# sonar.sources directory for sources of project
RUN sonar-scanner \
    -Dsonar.host.url="http://localhost:9000" \
    -Dsonar.projectKey="SONAR_PROJECT_KEY" \
    -Dsonar.sources="src"

 

First analysis

  1. Run docker build --network=host --no-cache . in react-starter-kit directory
  2. Enter http://localhost:9000/dashboard?id=SONAR_PROJECT_KEY to see analysis results

 

A few words about SonarQube administration

SonarQube settings administration

SonarQube have three levels of settings:

  1. Server level administration under http://localhost:9000/admin/settings
  2. Project level under http://localhost:9000/project/settings?id=SONAR_PROJECT_KEY
  3. Settings passed as parameters during an analysis

Since settings at both server and project levels location aren't versioned I usually prefer to pass settings as parameters during analysis to version them together with the code of a living project.

 

Projects management

In Projects management tab http://localhost:9000/admin/projects_management you can add new projects and edit permissions to them.

 

What next?

In the next tutorial, you are going to learn about how to configure SonarScanner to work with your projects and to suit your needs - SonarScanner tutorial.

After this, we will take a look into SonarScanner for MSBuild and check the differences between it and SonarScanner and work with its unique features - SonarScanner for MSBuild tutorial.

Then we will play a little with customization of the server rules and behaviors in analysis context in Rules, quality profiles and quality gates tutorial.

We will wrap things up with Gitlab integration tutorial, which will show us how to integrate SonarQube with pull requests.

 

Cleaning up after a tutorial

To stop a container running SonarQube server instance run the following command: (don’t do this if you want to continue with the next tutorials!)

docker container stop sonarqube

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

Want to learn more about SonarQube?
Check our next article on how to use SonarScanner!

OUR OFFICE

Wojskowa 6, 60-792 Poznań, Poland
+48 506 798 998
office@setapp.pl

OUR OFFICES

POL: Wojskowa 6, 60-792 Poznań, Poland
+48 506 798 998
office@setapp.pl

ISR: 220 Hertzel Street, 7630003 Israel

COMPANY DATA

Setapp Sp. z o.o.
VAT ID: PL7781465185
REGON: 301183743
KRS: 0000334616

PRIVACY POLICY

OUR OFFICES

PL: Wojskowa 6, 60-792 Poznań, Poland
+48 506 798 998
office@setapp.pl

ISR: 220 Hertzel Street, 7630003 Israel

COMPANY DATA

Setapp Sp. z o.o.

VAT ID: PL7781465185
REGON: 301183743
KRS: 0000334616

PRIVACY POLICY

OUR OFFICE

Wojskowa 6, 60-792 Poznań, Poland
+48 506 798 998
office@setapp.pl

COMPANY DATA

Setapp Sp. z o.o.

VAT ID: PL7781465185
REGON: 301183743
KRS: 0000334616

PRIVACY POLICY

 COMPANY DATA

Setapp Sp. z o.o.
VAT ID: PL7781465185
REGON: 301183743
KRS: 0000334616

PRIVACY POLICY

OUR OFFICES

POL: Wojskowa 6, 60-792 Poznań, Poland
+48 506 798 998
office@setapp.pl

ISR: 220 Hertzel Street, 7630003 Israel

COMPANY DATA

Setapp Sp. z o.o.
VAT ID: PL7781465185
REGON: 301183743
KRS: 0000334616

PRIVACY POLICY

OUR OFFICES

PL: Wojskowa 6, 60-792 Poznań, Poland
+48 506 798 998
office@setapp.pl

ISR: 220 Hertzel Street, 7630003 Israel

COMPANY DATA

Setapp Sp. z o.o.

VAT ID: PL7781465185
REGON: 301183743
KRS: 0000334616

PRIVACY POLICY

OUR OFFICE

Wojskowa 6, 60-792 Poznań, Poland
+48 506 798 998
office@setapp.pl

COMPANY DATA

Setapp Sp. z o.o.

VAT ID: PL7781465185
REGON: 301183743
KRS: 0000334616

PRIVACY POLICY

klacz
Clutch award badge
topdizajn
svg-image
svg-image
svg-image
svg-image
Instagram Icon
svg-image
svg-image
smart-growth
european-union

©2020 Setapp. All rights reserved.