喜欢 GitLab 但讨厌 bug? 想要提高源代码的质量吗? 那么您就来对地方了。 今天我们将告诉您如何配置PVS-Studio C#分析器来检查合并请求。 祝大家有独角兽心情,快乐阅读。
顺便说一句,我们发布了PVS-Studio 7.08,其中我们做了很多事情
- 适用于 Linux 和 macOS 的 C# 分析器;
- Rider 插件;
- 新的文件列表检查模式。
文件列表检查模式
以前,为了检查某些文件,需要将包含文件列表的 .xml 传递给分析器。 但由于这不是很方便,我们添加了传输 .txt 的功能,这使生活变得非常简单。
为了检查特定文件,您必须指定标志 --源文件 (-f)并传输 .txt 和文件列表。 它看起来像这样:
pvs-studio-dotnet -t path/to/solution.sln -f fileList.txt -o project.json
如果您有兴趣设置提交检查或拉取请求,您也可以使用此模式来执行此操作。 区别在于获取要分析的文件列表,并且取决于您使用的系统。
检查合并请求的原理
检查的主要本质是确保分析器在合并过程中检测到的问题不会落入 主 分支。 我们也不想每次都分析整个项目。 此外,当合并分支时,我们有一个已更改文件的列表。 因此,我建议添加合并请求检查。
这是实现静态分析器之前合并请求的样子:
也就是说,分支中的所有错误 变化,将移动到 master 分支。 由于我们不希望出现这种情况,因此我们添加了分析,现在该图如下所示:
我们分析 变化2 如果没有错误,我们接受合并请求,否则我们拒绝它。
顺便说一句,如果您有兴趣分析 C/C++ 的提交和拉取请求,那么您可以阅读相关内容
GitLab
在开始分析合并请求之前,您需要注册并上传您的项目。 如果您不知道如何执行此操作,那么我建议
注意。 下面描述的设置环境的方法是可能的方法之一。 目标是展示设置分析所需环境和启动分析器的步骤。 也许在您的情况下,将环境准备阶段(添加存储库、安装分析器)和分析阶段分开会更理想:例如,使用必要的环境准备 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
由于安装和激活必须在所有其他脚本之前发生,因此我们使用特殊的标签 前脚本。 让我稍微解释一下这个片段。
准备安装分析仪:
- 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 包)。
您可以通过单击设置包含许可证信息的环境变量 设置, 之后 持续集成/持续交付.
在打开的窗口中找到该项目 变量,点击右侧按钮 扩大 并添加变量。 结果应该是这样的:
现在您可以继续分析。 首先,我们添加一个脚本来进行完整的分析。 到旗帜 -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-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
剩下的就是在处理完所有脚本后添加日志转换。 我们使用标签 后脚本 和效用 plog转换器:
after_script:
- plog-converter -t html -o eLog ./PVS-Studio.json
效用
顺便说一句,如果您想从 IDE 本地方便地使用 .json 报告,那么我建议我们
为了方便起见,这里是 .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 -> 管道 -> 运行。 将打开一个虚拟机窗口,其末尾应有以下内容:
锯 作业成功 ——成功了,一切都好。 现在您可以测试您所做的事情。
工作示例
作为工作示例,让我们创建一个简单的项目(在 主)其中将包含多个文件。 之后,在另一个分支中,我们将仅更改一个文件并尝试发出合并请求。
让我们考虑两种情况:修改后的文件包含错误时和不包含错误时。 首先,举一个有错误的例子。
假设master分支中有一个文件 程序.cs,它不包含错误,但在另一个分支中,开发人员添加了错误代码并想要发出合并请求。 他犯了什么错误并不重要,重要的是它确实存在。 例如,操作员忘记了 扔 (是的,
void MyAwesomeMethod(String name)
{
if (name == null)
new ArgumentNullException(....);
// do something
....
}
我们来看一个有错误的例子的分析结果。 另外为了确保只解析一个文件,我添加了标志 -r 到 pvs-studio-dotnet 启动线:
我们看到分析器发现了错误并且不允许合并分支。
让我们检查一下示例是否有错误。 更正代码:
void MyAwesomeMethod(String name)
{
if (name == null)
throw new ArgumentNullException(....);
// do something
....
}
合并请求分析结果:
可以看到,没有发现错误,任务执行成功,这正是我们想要检查的。
结论
在合并分支之前清除坏代码是非常方便和愉快的。 因此,如果您使用 CI/CD,请尝试嵌入静态分析器进行检查。 而且,这非常简单。
感谢您的关注。
如果您想与英语读者分享这篇文章,请使用翻译链接:Nikolay Mironov。
来源: habr.com