喜欢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分支中。另外,我们不想每次都分析整个项目。此外,合并分支时,我们具有已更改文件的列表。因此,我建议为合并请求添加检查。
这是在实现静态分析器之前合并请求的外观:
也就是说,所有在change分支中的错误都将转到master分支。由于我们不愿意这样做,因此我们添加了分析,现在该图如下所示:
我们分析changes2,如果没有错误,我们接受合并请求,否则我们拒绝它。
顺便说一句,如果您有兴趣分析C / C ++的提交和提取请求,那么可以在此处阅读有关内容。
Gitlab
GitLab是一个基于Web的开源DevOps生命周期工具,它为Git提供了一个代码仓库管理系统,它具有自己的Wiki,错误跟踪器,CI / CD管道等。
在开始执行合并请求的分析之前,需要注册并上传项目。如果您不知道该怎么做,那么我建议我的同事写一篇文章。
注意...下述环境设置方法是其中一种。目的是显示设置分析和运行分析仪所需的环境的步骤。在您的情况下,也许最好将准备环境(添加存储库,安装分析器)和分析的阶段分开:例如,使用必要的环境准备Docker映像并使用它们,或使用其他方法。
为了更好地了解现在将要发生的事情,我建议看一下下图:
分析器需要.NET Core SDK 3才能工作,因此,在安装分析器之前,您需要添加Microsoft存储库,将从中安装分析器所需的依赖项。在相应的文档中介绍了为各种Linux发行版添加Microsoft存储库。
要通过程序包管理器安装PVS-Studio,您还需要添加PVS-Studio存储库。在文档的相应部分中详细介绍了为不同发行版添加存储库。
分析仪需要许可证密钥才能操作。您可以在分析仪下载页面上获得试用许可证。
注意...请注意,所描述的操作模式(对合并请求的分析)需要企业许可证。因此,如果要尝试这种操作模式,请不要忘记在“消息”字段中指出您需要企业许可证。
如果发生合并请求,那么我们仅需要分析已更改文件的列表,否则我们将分析所有文件。分析之后,我们需要将日志转换为所需的格式。
现在,在您看到算法的工作之后,就可以继续编写脚本了。为此,您需要修改.gitlab-ci.yml文件,如果没有,请创建它。要创建它,您需要单击项目的名称->设置CI / CD。
现在我们可以编写脚本了。首先,让我们编写将安装分析仪并输入许可证的代码:
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来设置包含许可证信息的环境变量。
在打开的窗口中,我们找到右侧的Variables项,单击Expand按钮并添加变量。结果应如下所示:
现在您可以进行分析了。首先,让我们添加一个脚本进行全面分析。我们将解决方案的路径传递给-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。将打开一个虚拟机窗口,其末尾应为以下内容:
我们看到了乔布斯成功-成功,一切都很好。现在,您可以测试您的工作了。
工作实例
作为工作示例,让我们创建一个简单的项目(在master中),其中将有多个文件。之后,在另一个分支中,我们将仅更改一个文件并尝试发出合并请求。
请考虑以下两种情况:修改后的文件包含错误,什么时候没有。首先,有一个错误的例子。
假设master分支中有一个Program.cs文件,其中不包含错误,而在另一个分支中,开发人员添加了错误代码,并希望发出合并请求。他犯了什么样的错误并不那么重要,主要的是它存在。例如,我忘记了throw操作符(是的,他们错了):
void MyAwesomeMethod(String name)
{
if (name == null)
new ArgumentNullException(....);
// do something
....
}
让我们看一下分析有错误的示例的结果。另外,为确保仅解析一个文件,我在pvs-studio-dotnet启动行中添加了-r标志:
我们看到分析器发现错误,并且不允许合并分支。
检查示例无错误。我们修复代码:
void MyAwesomeMethod(String name)
{
if (name == null)
throw new ArgumentNullException(....);
// do something
....
}
合并请求分析的结果:
如我们所见,未发现任何错误,并且任务执行成功,我们希望对其进行检查。
结论
在合并分支之前过滤掉错误的代码非常方便而且令人愉快。因此,如果您使用的是CI / CD,请尝试在静态分析器中进行构建以进行测试。此外,这非常简单。
感谢您的关注。
如果您想与说英语的读者分享这篇文章,请使用翻译链接:Nikolay Mironov。使用PVS-Studio for C#在GitLab中合并请求的分析。