Analysis of merge requests in GitLab using PVS-Studio for C#

Analysis of merge requests in GitLab using PVS-Studio for C#
Love GitLab and hate bugs? Want to improve the quality of your source code? Then you have come to the right place. Today we will tell you how to configure the PVS-Studio C# analyzer to check merge requests. Cheers to all and happy reading.

PVS Studio is a tool for detecting errors and potential vulnerabilities in the source code of programs written in C, C++, C# and Java. Works on 64-bit systems on Windows, Linux and macOS. Can analyze code designed for 32-bit, 64-bit and embedded ARM platforms.

By the way, we have released PVS-Studio 7.08, in which we have done a lot of things interesting. For example:

  • C# analyzer for Linux and macOS;
  • plugin for Rider;
  • new file list check mode.

File list check mode

Previously, in order to check certain files, it was necessary to pass an .xml file with a list of files to the parser. But since this is not very convenient, we have added the ability to transfer .txt, which greatly simplifies life.

In order to check certain files, you must specify the flag --sourceFiles (-f) and pass .txt with a list of files. It looks like this:

pvs-studio-dotnet -t path/to/solution.sln -f fileList.txt -o project.json

If you're interested in setting up commit checks or pull requests, you can also do so using this mode. The difference will be in obtaining a list of files for analysis and will depend on which systems you are using.

Principle of merge request check

The main essence of the check is to ensure that the problems detected by the analyzer do not fall into the merge master branch. Also, we do not want to analyze the entire project each time. Moreover, when merging branches, we have a list of changed files. Therefore, I propose to add a merge request check.

This is what the merge request looks like before the introduction of the static analyzer:

Analysis of merge requests in GitLab using PVS-Studio for C#
That is, all the errors that were in the branch changes, will move to the master branch. Since we don't want this, we add the analysis, and now the circuit looks like this:

Analysis of merge requests in GitLab using PVS-Studio for C#
Analyzing changes2 and, if there are no errors, we accept the merge request, otherwise we reject it.

By the way, if you are interested in analyzing commits and pull requests for C/C++, then you can read about it. here.

GitLab

GitLab is an open source DevOps lifecycle web tool that provides a code repository management system for Git with its own wiki, bug tracking system, CI/CD pipeline and other features.

Before proceeding with the implementation of the analysis of merge requests, you need to register and upload your project. If you do not know how to do this, then I suggest Article my colleague.

Note. The way to set up the environment described below is one of the possible ones. The goal is to show the steps for setting up the environment necessary for analysis and launching the analyzer. Perhaps, in your case, it would be more optimal to separate the stages of environment preparation (adding repositories, installing the analyzer) and analysis: for example, preparing Docker images with the necessary environment and using them, or some other way.

To better understand what will happen now, I suggest taking a look at the following diagram:

Analysis of merge requests in GitLab using PVS-Studio for C#
The analyzer requires the .NET Core SDK 3 to work, so before installing the analyzer, you need to add the Microsoft repositories, from which the dependencies necessary for the analyzer will be installed. Adding Microsoft repositories for various Linux distributions described in the relevant document.

To install PVS-Studio via the package manager, you will also need to add the PVS-Studio repositories. Adding repositories for various distributions is described in more detail in corresponding section of the documentation.

The analyzer needs a license key to work. You can get a trial license at analyzer download page.

Note. Please note that the described mode of operation (analysis of merge requests) requires an Enterprise license. Therefore, if you want to try this mode of operation, in the "Message" field, do not forget to indicate that you need an Enterprise license.

If a merge request occurs, then we need to analyze only the list of changed files, otherwise we analyze all files. After analysis, we need to convert the logs to the format we need.

Now, having the algorithm of work before our eyes, we can proceed to writing the script. To do this, you need to change the file .gitlab-ci.yml or, if it doesn't exist, create it. To create it, you need to click on the name of your project -> Set up CI/CD.

Analysis of merge requests in GitLab using PVS-Studio for C#
Now we are ready to write the script. Let's first write the code that will install the analyzer and enter the license:

before_script:
  - apt-get update && apt-get -y install wget gnupg 

  - apt-get -y install git
  - wget https://packages.microsoft.com/config/debian/10/
packages-microsoft-prod.deb -O packages-microsoft-prod.deb
  - dpkg -i packages-microsoft-prod.deb
  - apt-get update
  - apt-get install apt-transport-https
  - apt-get update
  
  - wget -q -O - https://files.viva64.com/etc/pubkey.txt | apt-key add -
  - wget -O /etc/apt/sources.list.d/viva64.list
https://files.viva64.com/etc/viva64.list
  - apt-get update
  - apt-get -y install pvs-studio-dotnet

  - pvs-studio-analyzer credentials $PVS_NAME $PVS_KEY
  - dotnet restore "$CI_PROJECT_DIR"/Test/Test.sln

Since installation and activation must occur before all other scripts, we use a special label before_script. Let me explain this part a bit.

Preparing to install the analyzer:

  - wget https://packages.microsoft.com/config/debian/10/
packages-microsoft-prod.deb -O packages-microsoft-prod.deb
  - dpkg -i packages-microsoft-prod.deb
  - apt-get update
  - apt-get install apt-transport-https
  - apt-get update

Adding PVS-Studio and analyzer repositories:

  - wget -q -O - https://files.viva64.com/etc/pubkey.txt | apt-key add -
  - wget -O /etc/apt/sources.list.d/viva64.list
https://files.viva64.com/etc/viva64.list
  - apt-get update
  - apt-get -y install pvs-studio-dotnet

License activation:

  - pvs-studio-analyzer credentials $PVS_NAME $PVS_KEY

$PVS_NAME - Username.

$PVS_KEY - product key.

Restore project dependencies where $CI_PROJECT_DIR – full path to the project directory:

  - dotnet restore "$CI_PROJECT_DIR"/Path/To/Solution.sln

For correct analysis, the project must be successfully built, and its dependencies must be restored (for example, the necessary NuGet packages must be downloaded).

You can set environment variables containing license information by clicking on Setting, and after - on CI/CD.

Analysis of merge requests in GitLab using PVS-Studio for C#
In the window that opens, find the item Variables, right click on the button Expand and add variables. The result should be the following:

Analysis of merge requests in GitLab using PVS-Studio for C#
Now we can move on to the analysis. First, let's add a script for a complete analysis. To the flag -t pass the path to solution to the flag -o write the path to the file where the analysis results will be written. We are also interested in the return code. In this case, we are interested in stopping the work when the return code contains information that warnings were issued during the analysis. Here's what the snippet looks like:

job:
  script:
  - exit_code=0
  - pvs-studio-dotnet -t "$CI_PROJECT_DIR"/Test/Test.sln -o 
PVS-Studio.json || exit_code=$?
  - exit_code=$((($exit_code & 8)/8))
  - if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi

Return codes work on the principle of a bit mask. For example, if warnings were issued as a result of the analysis, then the return code will be 8. If the license expires within a month, then the return code will be 4. If errors were found during the analysis, and the license also expires within a month, the code return, both values ​​will be written: add the numbers together and get the final return code - 8 + 4 = 12. Thus, by checking the corresponding bits, it is possible to obtain information about various states during analysis. Return codes are described in more detail in the pvs-studio-dotnet (Linux / macOS) Return Codes section of the document.Checking Visual Studio / MSBuild / .NET Core projects from the command line using PVS-Studio".

In this case, we are interested in all return codes where 8 appears.

  - exit_code=$((($exit_code & 8)/8))

We will get 1 when the return code contains the bit of the number we are interested in, otherwise we will get 0.

It's time to add the merge request analysis. Before doing this, let's prepare a place for the script. We need it to be executed only when a merge request occurs. It looks like this:

merge:
  script:
  only:
  - merge_requests

Let's move on to the script itself. I encountered the fact that the virtual machine does not know anything about origin/master. So let's help her a little:

  - git fetch origin

Now we get the difference of the branches and save the result in txt file:

  - git diff --name-only origin/master $CI_COMMIT_SHA > pvs-fl.txt

Where $CI_COMMIT_SHA – hash of the last commit.

Next, we start the analysis of the list of files using the flag -f. We transfer the previously received .txt file to it. Well, by analogy with the full analysis, we look at the return codes:

  - exit_code=0
  - pvs-studio-dotnet -t "$CI_PROJECT_DIR"/Test/Test.sln -f 
pvs-fl.txt -o PVS-Studio.json || exit_code=$?
  - exit_code=$((($exit_code & 8)/8))
  - if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi

The complete script for checking the merge request will look like this:

merge:
  script:
  - git fetch origin
  - git diff --name-only origin/master $CI_COMMIT_SHA > pvs-fl.txt
  - exit_code=0
  - pvs-studio-dotnet -t "$CI_PROJECT_DIR"/Test/Test.sln -f 
pvs-fl.txt -o PVS-Studio.json || exit_code=$?
  - exit_code=$((($exit_code & 8)/8))
  - if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi
  only:
  - merge_requests

It remains only to add the log conversion after all the scripts have worked. Using the label after_script and utility plog-converter:

after_script:
  - plog-converter -t html -o eLog ./PVS-Studio.json

Utility plog-converter is an open source project that is used to convert the parser error report into various forms such as HTML. For a more detailed description of the utility, see the "Plog Converter Utility" subsection. corresponding section of the documentation.

By the way, if you want to conveniently work with a .json report locally from the IDE, then I suggest our Plugin for IDE Rider. Its use is described in more detail in relevant document.

For convenience here .gitlab-ci.yml whole:

image: debian

before_script:
  - apt-get update && apt-get -y install wget gnupg 

  - apt-get -y install git
  - wget https://packages.microsoft.com/config/debian/10/
packages-microsoft-prod.deb -O packages-microsoft-prod.deb
  - dpkg -i packages-microsoft-prod.deb
  - apt-get update
  - apt-get install apt-transport-https
  - apt-get update
  
  - wget -q -O - https://files.viva64.com/etc/pubkey.txt | apt-key add -
  - wget -O /etc/apt/sources.list.d/viva64.list
https://files.viva64.com/etc/viva64.list
  - apt-get update
  - apt-get -y install pvs-studio-dotnet

  - pvs-studio-analyzer credentials $PVS_NAME $PVS_KEY
  - dotnet restore "$CI_PROJECT_DIR"/Test/Test.sln

merge:
  script:
  - git fetch origin
  - git diff --name-only origin/master $CI_COMMIT_SHA > pvs-fl.txt
  - exit_code=0
  - pvs-studio-dotnet -t "$CI_PROJECT_DIR"/Test/Test.sln -f 
pvs-fl.txt -o PVS-Studio.json || exit_code=$?
  - exit_code=$((($exit_code & 8)/8))
  - if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi
  only:
  - merge_requests

job:
  script:
  - exit_code=0
  - pvs-studio-dotnet -t "$CI_PROJECT_DIR"/Test/Test.sln -o 
PVS-Studio.json || exit_code=$?
  - exit_code=$((($exit_code & 8)/8))
  - if [[ $exit_code == 1 ]]; then exit 1; else exit 0; fi
  
after_script:
  - plog-converter -t html -o eLog ./PVS-Studio.json

Once everything has been added to the file, click on commit changes. To see if everything is correct, go to CI / CD -> Pipelines -> Running. The virtual machine window will open, at the end of which should be the following:

Analysis of merge requests in GitLab using PVS-Studio for C#
saw Job succeeded - success, everything is fine. Now you can test what you've done.

Examples of work

For an example of work, let's create a simple project (in master) which will contain several files. After that, in another branch, we will change only one file and try to make a merge request.

Let's consider two cases: when the modified file contains an error and when it doesn't. First, an example with an error.

Let's say there is a file in the master branch program.cs, which does not contain errors, and in another branch, the developer added erroneous code and wants to make a merge request. What kind of mistake he made is not so important, the main thing is that it exists. For example, I forgot the operator throw (Yes, so wrong):

void MyAwesomeMethod(String name)
{
  if (name == null)
    new ArgumentNullException(....);
  // do something
  ....
}

Let's look at the result of the analysis of an example with an error. Also to make sure only one file was parsed I added the flag -r to the pvs-studio-dotnet start line:

Analysis of merge requests in GitLab using PVS-Studio for C#
We see that the analyzer found an error and did not allow the branches to be merged.

Let's check the example without error. Fixing the code:

void MyAwesomeMethod(String name)
{
  if (name == null)
    throw new ArgumentNullException(....);
  // do something
  ....
}

Results of merge request analysis:

Analysis of merge requests in GitLab using PVS-Studio for C#
As we can see, no errors were found, and the execution of the task was successful, which is what we wanted to check.

Conclusion

Weeding out bad code before merging branches is very convenient and pleasant. Therefore, if you use CI/CD, try to embed a static analyzer to check it. Moreover, this is done quite simply.

Thank you for attention.

Analysis of merge requests in GitLab using PVS-Studio for C#
If you want to share this article with an English-speaking audience, please use the translation link: Nikolay Mironov. Analysis of merge requests in GitLab using PVS-Studio for C#.

Source: habr.com

Add a comment