使用PVS-Studio for C#分析GitLab中的合并请求

image1.png


喜欢GitLab,不喜欢bug?是否想提高源代码的质量?然后您来对地方了。今天,我们将告诉您如何设置PVS-Studio C#分析器以检查合并请求。所有独角兽的心情和愉快的阅读。



PVS-Studio是用于检测用C,C ++,C#和Java编写的程序的源代码中的错误和潜在漏洞的工具。在Windows,Linux和macOS上的64位系统上运行。可以分析32位,64位和嵌入式ARM平台的代码。



顺便说一句,我们发布了PVS-Studio 7.08,其中做了很多有趣的事情例如:



  • 用于Linux和macOS的C#分析器;
  • Rider插件;
  • 用于检查文件列表的新模式。


文件列表检查模式



以前,为了检查某些文件,必须将带有文件列表的.xml传递给解析器。但是由于它不是很方便,所以我们增加了传输.txt的功能,这使生活变得非常轻松。



为了检查特定文件,您需要指定--sourceFiles-f标志,并将文件列表传递给.txt。看起来像这样:



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


如果您对配置检查提交或拉取请求感兴趣,也可以使用此模式进行。区别在于获取要分析的文件列表,这取决于您使用的系统。



合并请求验证原理



检查的重点是合并期间分析器检测到的问题不会最终出现在master分支另外,我们不想每次都分析整个项目。此外,合并分支时,我们具有已更改文件的列表。因此,我建议为合并请求添加检查。



这是在实现静态分析器之前合并请求的外观:



image2.png


也就是说,所有在change分支中的错误都将转到master分支。由于我们不愿意这样做,因此我们添加了分析,现在该图如下所示:



image3.png


我们分析changes2,如果没有错误,我们接受合并请求,否则我们拒绝它。



顺便说一句,如果您有兴趣分析C / C ++的提交和提取请求,那么可以在此处阅读有关内容



Gitlab



GitLab是一个基于Web的开源DevOps生命周期工具,它为Git提供了一个代码仓库管理系统,它具有自己的Wiki,错误跟踪器,CI / CD管道等。



在开始执行合并请求的分析之前,需要注册并上传项目。如果您不知道该怎么做,那么我建议我的同事写一篇文章



注意...下述环境设置方法是其中一种。目的是显示设置分析和运行分析仪所需的环境的步骤。在您的情况下,也许最好将准备环境(添加存储库,安装分析器)和分析的阶段分开:例如,使用必要的环境准备Docker映像并使用它们,或使用其他方法。



为了更好地了解现在将要发生的事情,我建议看一下下图:



image4.png


分析器需要.NET Core SDK 3才能工作,因此,在安装分析器之前,您需要添加Microsoft存储库,将从中安装分析器所需的依赖项。在相应的文档中介绍了为各种Linux发行版添加Microsoft存储库



要通过程序包管理器安装PVS-Studio,您还需要添加PVS-Studio存储库。在文档相应部分中详细介绍了为不同发行版添加存储库



分析仪需要许可证密钥才能操作。您可以在分析仪下载页面上获得试用许可证



注意...请注意,所描述的操作模式(对合并请求的分析)需要企业许可证。因此,如果要尝试这种操作模式,请不要忘记在“消息”字段中指出您需要企业许可证。



如果发生合并请求,那么我们仅需要分析已更改文件的列表,否则我们将分析所有文件。分析之后,我们需要将日志转换为所需的格式。



现在,在您看到算法的工作之后,就可以继续编写脚本了。为此,您需要修改.gitlab-ci.yml文件,如果没有,请创建它。要创建它,您需要单击项目的名称->设置CI / CD



image5.png


现在我们可以编写脚本了。首先,让我们编写将安装分析仪并输入许可证的代码:



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


由于安装和激活必须在所有其他脚本之前进行,因此我们使用特殊的before_script标记我将对此片段进行一些解释。



准备安装分析仪:



  - 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


添加PVS-Studio存储库和分析器:



  - 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


$ PVS_NAME-用户名。



$ PVS_KEY-产品密钥。



恢复项目依赖关系,其中$ CI_PROJECT_DIR是项目目录的完整路径:



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


为了进行正确的分析,项目必须成功构建,并且必须还原其依赖项(例如,必须加载必要的NuGet程序包)。



您可以通过单击设置,然后单击CI / CD设置包含许可证信息的环境变量



image6.png


在打开的窗口中,我们找到右侧Variables,单击Expand按钮并添加变量。结果应如下所示:



image7.png


现在您可以进行分析了。首先,让我们添加一个脚本进行全面分析。我们将解决方案的路径传递给-t标志,并将-o标志传递给将分析结果写入其中的文件的路径。我们对返回码也很感兴趣。在这种情况下,我们对当返回码包含分析期间发出警告的信息时终止的操作感兴趣。该代码段如下所示:



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


返回码就像位掩码一样工作。例如,如果分析后发出警告,则返回码为8。如果许可证在一个月内到期,则返回码为4。如果在分析过程中发现错误,并且许可证在一个月内到期,则代码中返回值,两个值都将被写入:将数字加在一起并得到最终的返回码-8 + 4 = 12。因此,通过检查相应的位,可以在分析期间获得关于各种状态的信息。返回代码在文档“使用PVS-Studio从命令行检查Visual Studio / MSBuild / .NET Core项目”的“ pvs-studio-dotnet(Linux / macOS)返回代码”部分中有更详细的描述



在这种情况下,我们对所有返回码都感兴趣,出现8。



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


当返回码包含我们感兴趣的数字的位时,我们将得到1,否则,我们将得到0。



是时候将解析添加到合并请求中了。在执行此操作之前,让我们为脚本准备一个位置。我们仅在合并请求发生时才需要执行。看起来像这样:



merge:
  script:
  only:
  - merge_requests


让我们继续脚本本身。我遇到了这样一个事实,即虚拟机对源/主服务器一无所知因此,我们为她提供了一些帮助:



  - git fetch origin


现在,让我们了解分支之间的区别,并将结果保存到txt文件中:



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


其中$ CI_COMMIT_SHA是最后一次提交的哈希。



接下来,我们使用-f标志运行文件列表分析我们将接收到的早期.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


用于检查合并请求的完整脚本如下所示:



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


在所有脚本运行之后,仅保留添加日志的转换。我们使用after_script标签plog-converter实用程序



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


plog-converter 实用程序是一个开源项目,用于将分析器错误报告转换为各种形式,例如HTML。在文档相应部分的“ Plog Converter Utility”小节中提供了对该实用程序的详细说明



顺便说一句,如果您想方便地在IDE中本地处理.json报告,那么我建议使用我们的IDE Rider插件相应文档中更详细地描述了它的使用



为了方便起见,以下是整个.gitlab-ci.yml



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


将所有内容添加到文件后,点击提交更改为了确认一切正确,请转到CI / CD- > Pipelines- > Running将打开一个虚拟机窗口,其末尾应为以下内容:



image8.png


我们看到了乔布斯成功-成功,一切都很好。现在,您可以测试您的工作了。



工作实例



作为工作示例,让我们创建一个简单的项目(在master中),其中将有多个文件。之后,在另一个分支中,我们将仅更改一个文件并尝试发出合并请求。



请考虑以下两种情况:修改后的文件包含错误,什么时候没有。首先,有一个错误的例子。



假设master分支中有一个Program.cs文件,其中不包含错误,而在另一个分支中,开发人员添加了错误代码,并希望发出合并请求。他犯了什么样的错误并不那么重要,主要的是它存在。例如,我忘记了throw操作符(是的,他们错了):



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


让我们看一下分析有错误的示例的结果。另外,为确保仅解析一个文件,我在pvs-studio-dotnet启动行中添加了-r标志



image9.png


我们看到分析器发现错误,并且不允许合并分支。



检查示例无错误。我们修复代码:



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


合并请求分析的结果:



image10.png


如我们所见,未发现任何错误,并且任务执行成功,我们希望对其进行检查。



结论



在合并分支之前过滤掉错误的代码非常方便而且令人愉快。因此,如果您使用的是CI / CD,请尝试在静态分析器中进行构建以进行测试。此外,这非常简单。



感谢您的关注。





如果您想与说英语的读者分享这篇文章,请使用翻译链接:Nikolay Mironov。使用PVS-Studio for C#在GitLab中合并请求的分析



All Articles