前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >量化你团队的代码质量

量化你团队的代码质量

作者头像
我与梦想有个约会
发布于 2023-10-21 07:44:16
发布于 2023-10-21 07:44:16
1.1K00
代码可运行
举报
文章被收录于专栏:jiajia_dengjiajia_deng
运行总次数:0
代码可运行

在疫情背景下各大公司都有所异动,toB 的团队企业内卷也越来越明显。此时此刻如果团队中的产品又出现各种低级问题无疑是雪上加霜。本文围绕团队在产品质量攻坚工作中做的一些质量检查手段,介绍如何让你团队的代码质量可以量化,并保留最珍贵、可维护、可持续、可传承的工程化代码。

整合目标

本文除了让大家了解这些工具如何使用以外,还会重点描述如何组织这些代码质量的周边工具链使其达到工程化程度,讨论什么该做,什么不该做,为什么这么做。我对所谓 工程化 有以下几个明确的定义:

  • 可维护:贴近 GitOps,尽量将所有可变配置放到代码仓库,而不是分散维护,Everything is code.
  • 可持续:不是应付一次检查或攻坚,而是形成常态
  • 可传承:新人只关注代码,不关注质量工具的配置细节,通过类似于 MRs 的结果反馈不断改进自身代码质量

一些涉及到权限控制的位置(如代码质量阈设置)是需要有管理员把控的,要实施这些步骤首先团队的技术管理负责人要有这些认知并且能在关键点拍板。如果仅认为这些东西有了就够了恐怕是很难实施下去的! 本文示例均已一个简单的 ne-phoenix 基础库代码作为示例,介绍围绕该工程展开的质量突击。

准备工具

  • clang-tidy、infer 用于静态代码检查
  • lcov 用于统计单元测试代码覆盖率
  • gcovr 用于生成覆盖率报告及转为 SonarQube 支持的报告格式
  • sonar-scanner 用于传送以上工具的报告结果到 SonarQube 平台(平台搭建请参考官方文档)
  • pre-commit 可选,用于提交时本地执行静态代码检查

这些工具在 macOS 中均可通过 brew 来进行安装,比较特殊的是 clang-tidy,它在 LLVM 工具链中,您需要在 brew install llvm 后再通过 brew link llvm 按提示将可执行文件添加到环境变量中,使脚本可以直接访问到 clang-tidy 可执行程序。

Code coverage

单元测试、API 测试、集成测试,只听这些概念就足够让我们晕头转向,但无论如何,我一直很认同一句话:没有覆盖率统计的测试就是耍流氓。即便你提供了所谓每天的自动化测试报告,貌似可以量化,但真正的作用谁有知道呢?虽然覆盖率统计并不能代表代码就是 100% 可靠的。但它可以通过量化的数据告诉我们代码的哪些分支、哪些逻辑我们还没有覆盖,至少能让你知道,你的测试是不是在做一些无意义的事情。 在 ne-phoenix 基础库中,我们以 CMake + Conan 驱动整个工程的编译,单元测试的框架使用了 Google Test。要统计执行测试程序后对代码的覆盖情况,我们要做以下几点工作:

  • 增加编译选项为 coverage 做准备
  • lcov 初始化一次基础扫描
  • 编译并运行测试可执行程序
  • lcov 扫描执行测试程序后的结果捕获覆盖到的代码情况
  • lcov 与基础报告对比生成结果

这个步骤比较繁琐,我们找到了一个开源的 CMake 插件 CodeCoverage.cmake,有了这个插件,您只需要在您的工程中添加几行 CMake 代码即可实现覆盖率统计能力:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (APPLE)
    include(CodeCoverage)
    append_coverage_compiler_flags()
endif ()

.....
..... 

if (BUILD_TESTING)
    add_subdirectory(testing)
    if (APPLE)
        setup_target_for_coverage_lcov(
            NAME coverage
            SONARQUBE TRUE
            BASE_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}"
            EXECUTABLE testing
            EXECUTABLE_ARGS --gtest_output=xml:result.xml
            EXCLUDE "/*v1/*" "/*/.conan/data/*" "/*CompilerId*" "/*/testing*" "/*/*_unittest.cc"
        )
    endif ()
endif ()

首先在脚本开始判断平台并引入 CodeCoverage.cmake 插件,调用 append_coverage_compiler_flags() 接口全局添加统计代码覆盖率所需的编译选项。随后调用 setup_target_for_coverage_lcov() 添加一个自定义 CMake 目标用来执行并输出覆盖率统计报告,它的参数分别如下:

  • NAME 在 CMake 中生成的自定义目标名称
  • SONARQUBE 是否生成 SonarQube 兼容的覆盖率统计报告
  • BASE_DIRECTORY 要统计覆盖率源码的起始目录
  • EXECUTABLE 执行测试的程序,这里使用接入了 Google Test 的可执行程序
  • EXECUTABLE_ARGS 执行测试程序是的命令行参数,用于生成 GTest 结果报告为 xml 上报给 GitLab
  • EXCLUDE 在报告中排除一些不需要的目录

添加完成后只需要如下两条命令,就可以自动在 CMake 缓存目录生成覆盖率统计报告了:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 初始化工程为 Debug
cmake -Bbuild -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=14
# 编译 coverage 目标
cmake --build build --config Debug --target coverage

生成 coverage 目标完成后,该目标会自动化执行测试程序并统计出报告:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Writing directory view page.
Overall coverage rate:
  lines......: 80.5% (1583 of 1966 lines)
  functions..: 78.3% (503 of 642 functions)
SonarQube code coverage info report saved in coverage_sonarqube.xml.
Open ./coverage/index.html in your browser to view the coverage report.

我们打开 build/coverage/index.html 就可以看到完整的覆盖率情况了:

点击某个文件进入可查看当前测试程序覆盖到了哪些条件判断,其中红色的表示你的测试程序没有覆盖到该位置的代码:

除了可视化的 html 查看覆盖率报告外,还输出了 SonarQube 兼容的 xml 格式报告 build/coverage_sonarqube.xml 文件,稍后我们介绍如何将该文件上传到 SonarQube 平台用以统计。 同时测试程序的成功、失败情况也输出在了 build/result.xml 中,稍后我们介绍如何将该文件上传到 GitLab 展示。

Code static analyzer

无论颗粒度是怎样的测试不仅能帮助我们发现业务流程中的问题,也能让我们尽快发现代码实现上的问题。但代码质量、可读性、可扩展性这些都是无法得知的,这些可以通过静态代码检查来实现。 Google 团队在 Chromium 项目中很早就应用了诸多静态代码检查工具,有的是依赖编译的,有的是通过正则模式分析的,各有优劣。仰仗于各个大厂和开源社区的努力,周边工具链越来越给力,类 clang-tidy、infer 的工具,不仅能实现完整的静态代码检查,还可以完全替代以前的正则类扫描工具如 cpplint 等。本文以 clang-tidy 分析 C++ 代码举例,让我们一起了解如何从头分析一个完整的工程。 如果你是 CMake 工程,做到这件事情非常简单,只需要在 CMake 初始化工程时增加参数:-DCMAKE_EXPORT_COMPILE_COMMANDS=ON,该参数的增加会告知 CMake 将所有源文件的编译选项写入到一个名为 compile_commands.json 的 json 文件中。后续所有的静态代码检查都是基于该文件进行的。 以 ne-phoenix 工程举例,首先使用如下命令生成工程配置:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cmake -Bbuild -DCMAKE_BUILD_TYPE=Debug \
    -DBUILD_TESTING=ON \
    -DCMAKE_CXX_STANDARD=14 \
    -DCMAKE_EXPORT_COMPILE_COMMANDS=ON

compile_commands.json 会生成到 CMake 的缓存目录 build 下,然后调用 clang-tidy 命令,对你关注的文件进行分析:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
clang-tidy -p=build main.cpp

clang-tidy 有默认的规则是启用所有,如果你希望控制规则细节,可在工程目录放置一个 .clang-tidy 配置文件,内容类似如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Checks: >
  -*,
  abseil-*,
  bugprone-*,
  clang-analyzer-*,
  google-*,
  misc-*,
  modernize-*,
  performance-*,
  portability-*,
  readability-*,
  -google-readability-braces-around-statements,
  -google-readability-namespace-comments,
  -google-runtime-references,
  -misc-non-private-member-variables-in-classes,
  -modernize-return-braced-init-list,
  -modernize-use-trailing-return-type,
  -modernize-avoid-c-arrays,
  -performance-move-const-arg,
  -readability-braces-around-statements,
  -readability-identifier-length,
  -readability-magic-numbers,
  -readability-named-parameter,
  -readability-redundant-declaration,
  -readability-function-cognitive-complexity,
  -bugprone-narrowing-conversions,
  -bugprone-easily-swappable-parameters,
  -bugprone-implicit-widening-of-multiplication-result

# WarningsAsErrors: "*"
HeaderFilterRegex: ".*"

FormatStyle: file

该规则参考了 Google Cloud 开源项目配置,所有配置项可参考 LLVM 官网:Extra Clang Tools 上面单独调用 clang-tidy 只能分析单个文件,如果要分析多个文件,我们要把所有文件依次传给 clang-tidy。这样命令写起来比较繁琐且不易阅读。更重要的是无法实现多个实例同时对多个文件进行检查,效率极低。LLVM 工具链中早就想好了这些问题,他们提供了 run-clang-tidy.py 提供我们进行批量分析,见:LLVM run-clang-tidy.py。有了这个脚本,我们就可以批量进行分析了:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
python3 .build/run-clang-tidy.py -p=build -j 8 > build/clang-tidy-output.txt
  • -p 表示指定 compile_commands.json 文件所在目录
  • -j 8 表示最多可以同时执行 8 路分析不同的文件,加快分析速度

分析时间视工程目录源码文件多少而定,如果代码中使用的模板较多,分析的时间会较长。分析完成后会在 build 目录下生成名为 clang-tidy-output.txt 的分析结果,手动打开该文件你就可以可以看到一分析的错误信息了。接下来就是将这个报告上传到 SonarQube 平台。

SonarQube 集成

由于考虑篇幅问题,这里不详细介绍 SonarQube 的部署及多分支插件的安装,这部分资料官网和 StackOverflow 资料非常多,大家可参考搭建部署。在上传报告前参考文章开头,先安装好 sonar-scanner 上传工具。将项目的配置信息保存到名为 sonar-project.properties 的配置文件中并存放到项目根目录下,内容类似:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# must be unique in a given SonarQube instance
sonar.host.url=http://10.246.152.58:9000
sonar.projectKey=ne-phoenix
sonar.login=sqp_86571ff6d309106814c26e22621e23d87******
sonar.qualitygate.wait=true
sonar.sources=.
sonar.sourceEncoding=UTF-8
sonar.cxx.file.suffixes=.cxx,.cpp,.cc,.c,.hxx,.hpp,.hh,.h
sonar.lang.patterns.objc=**/*.m,**/*.mm
sonar.cxx.clangtidy.reportPaths=build/clang-tidy-output.txt
sonar.exclusions=build/**,**/*_unittest.*,conanfile.py,uploadConan.py

各个参数用途如下:

  • sonar.host.url SonarQube 服务器地址
  • sonar.projectKey SonarQube 平台上创建的工程名
  • sonar.login SonarQube 上传 token
  • sonar.qualitygate.wait 表示等待 SonarQube 返回扫描结果
  • sonar.source 表示源码是当前根目录
  • sonar.sourceEncodin 表示以 UTF-8 格式分析报告
  • sonar.cxx.file.suffixes 表示要分析的 C++ 文件后缀
  • sonar.lang.patterns.objc 表示要分析的 Objective-C 代码的文件后缀
  • sonar.cxx.clangtidy.reportPaths 表示要上报的 clang-tidy 分析报告
  • sonar.exclusions 表示要排除的目录,包括测试覆盖率、静态分析结果

上传时只需要调用 sonar-scanner 即可将当前分支信息上报到 SonarQube 平台,如果一切顺利,将会返回如下内容:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
INFO: ------------------------------------------------------------------------
INFO: EXECUTION SUCCESS
INFO: ------------------------------------------------------------------------
INFO: Total time: 26.011s
INFO: Final Memory: 25M/108M
INFO: ------------------------------------------------------------------------
➜  ne-phoenix git:master)

此时再次打开 SonarQube 平台,就可以看到分析结果了(一定要安装 cxx-community 插件并应用 clang-tidy 规则):

SonarQube 支持设置每个工程的质量阈,如果您的团队短时间内无法对新代码实现高的覆盖率,可适当调整质量阈,以管理员身份登陆 SonarQube,点击上方菜单的 Quility Gates:

内置有默认的质量阈,代码覆盖率的要求达到了 80%,您可以自己手动新建一个质量与并在单独的工程设置中选择你自己创建的质量阈。

CI 集成

GitLab 测试报告集成

GitLab 和 SonarQube 都支持展示测试覆盖率统计结果,GitLab 还可以把测试的所有子项内容展示在 Pipeline 结果页中:

GitLab 展示测试覆盖率:

要显示这些内容在 GitLab 上非常简单,你只需在 gitlab-ci.yml 中将 GTest 测试结果的 result.xml 当作 Artifacts 上传到 GitLab 即可:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
stages:
  - step-analysis
  - step-conan-package-test
  - step-deploy

coverage:
  stage: step-analysis
  script:
    - export
    - git checkout -B "$CI_BUILD_REF_NAME" "$CI_BUILD_REF"
    - cmake -Bbuild -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON -DCMAKE_CXX_STANDARD=14 -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
    - cmake --build build --config Debug --target coverage --parallel
    - lcov --list build/coverage.info
  only:
    - merge_requests
  artifacts:
    when: always
    reports:
      junit: build/result.xml
  tags:
    - yunxin-darwin-runner

命令跟我们本地测试一样,先初始化 CMake 工程,然后编译 coverage 项目,编译时会自动执行代码覆盖率检查并输出 result.xml,最后调用 lcov 在终端输出了覆盖率报告内容,类似如下效果:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$ lcov --list build/coverage.info
Reading tracefile build/coverage.info
                                               Lines      FunctionsBranches  
Filename                                       Rate    NumRate  NumRate   Num
================================================================================
[/Users/yunxin/builds/Kri8Pkvi/0/netease-im/ne_phoenix/src/ne_base/]
base/ne_object.h                                100%     850.0%  24    -    0
base/ne_object_ability...nnect_able_supportor.h80.8%    2671.4%   7    -    0
base/ne_object_ability...ble_shared_from_this.h62.5%     866.7%   6    -    0
base/ne_object_ability...ent/ne_signal_from3p.h 0.0%    10 0.0%   4    -    0
base/ne_object_ability...ak_closure_supportor.h 100%     250.0%   4    -    0
crypto/md5.cpp                                 86.5%   20883.3%  12    -    0
design_patterns/scoped_generic.h                0.0%     4 0.0%   3    -    0
device/mac/platform_device_mac.mm              89.5%    19 100%   3    -    0
device/platform_device.cpp                     77.8%     966.7%   3    -    0
device/posix/platform_device_posix.cpp         92.6%    2750.0%   2    -    0
file/file_util.cpp                             85.0%    4071.4%   7    -    0
file/file_version_info.h                        0.0%     2 0.0%   4    -    0
file/mac/file_version_info_mac.mm               0.0%    42 0.0%  24    -    0
file/ne_filesystem.cpp                         85.1%   141 100%  14    -    0
log/log_file.cpp                               93.2%    74 100%  10    -    0
log/log_file.h                                  100%     6 100%   6    -    0
log/log_mmap_file.cpp                          80.9%   173 100%  16    -    0
log/log_os_filesys_util_posix.cc               82.5%    5787.5%   8    -    0
mmkv/mmkv.cpp                                  84.4%    45 100%   6    -    0
mmkv/mmkv.h                                     100%    15 100%   7    -    0
numerics/safe_conversions_impl.h                100%     5 100%  13    -    0
numerics/safe_math.h                            100%     8 100%  23    -    0
numerics/safe_math_impl.h                       100%    14 100%  31    -    0
path_util/path_util.cpp                        95.7%    46 100%  11    -    0
string/string_number_conversions.cc            77.2%   16784.8% 105    -    0
string/string_util.cpp                         77.6%   19688.9%  18    -    0
string/string_util.h                           83.3%     6 100%   2    -    0
synchronization/lock.h                         71.4%    21 100%   7    -    0
system/mac/sys_info_mac.cc                     60.7%    2857.1%   7    -    0
system/posix/sys_info_posix.cc                 55.6%    1850.0%   4    -    0
system/sys_info.cc                              100%     4 100%   2    -    0
system/sys_info.h                               100%     1 100%   4    -    0
system/sys_tool.cpp                            75.9%    2985.7%   7    -    0
thread/task_loop_interface.h                    100%     650.0%  12    -    0
thread/task_thread.cpp                         83.1%   14283.3%  24    -    0
thread/task_thread.h                           91.6%   13193.3%  45    -    0
thread/thread.cpp                              81.5%   11960.6%  33    -    0
thread/thread.h                                81.8%    1177.8%   9    -    0
thread/thread_interface.h                      84.0%    2573.3%  15    -    0
time/time.cpp                                   100%    19 100%   5    -    0
time/time.h                                     100%    25 100%   4    -    0
value/ne_any.h                                 46.3%    4177.9%  95    -    0
================================================================================
                                         Total:80.6%  197878.8% 646    -    0

最后的 Total:80.6% 就是总的覆盖率情况,这一步很重要,我们要在 GitLab 中添加一段正则代码,匹配最终的结果,GitLab 会在 Job 执行完成后从输出内容中正则匹配到对应内容并显示到 GitLab Job 结果页面,打开 Project->Settings->CI/CD 页面,展开 General pipelines 选项卡,在最下方的 Test coverage parsing 中输入如下正则,即可匹配到覆盖率统计数据:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Total:\(\d+\.?\d+\%)

如下图所示:

添加后 Save 保存,下一次触发 Pipeline 就会自动上报覆盖率百分比结果。

SonarQube 测试覆盖率集成

要上传测试覆盖率到 SonarQube 只需要在 sonar-project.properties 的配置文件中添加一行上报之前生成的 sonarqube_coverage.xml 即可:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# must be unique in a given SonarQube instance
sonar.host.url=http://10.246.152.58:9000
sonar.projectKey=ne-phoenix
sonar.login=sqp_86571ff6d309106814c26e22621e23d8778eb0bc
sonar.qualitygate.wait=true
sonar.sources=.
sonar.sourceEncoding=UTF-8
sonar.cxx.file.suffixes=.cxx,.cpp,.cc,.c,.hxx,.hpp,.hh,.h
sonar.lang.patterns.objc=**/*.m,**/*.mm
sonar.cxx.clangtidy.reportPaths=build/clang-tidy-output.txt
sonar.coverageReportPaths=build/coverage_sonarqube.xml
sonar.exclusions=build/**,**/*_unittest.*,conanfile.py,uploadConan.py

主意倒数第二行。通过次方式上传报告后,在 SonarQube 平台就可以展示测试覆盖率百分比的情况了:

SonarQube 平台支持设置统一的质量阈,当你的代码发现 Major 级别以上的错误又或者覆盖率达不到一定百分比,则 SonarQube 会回报给 GitLab 告诉他本次 MR 不通过并创建一个临时的错误 Job:

而如果一切正常,也会创建一个反馈入口:

点击即可直达本次 Merge request 的分析详情。

Merge request 增量代码静态检查

如果你实操过代码静态检查,你会发现在你庞大的工程中做一次代码静态分析的时间成本是非常昂贵的,我们不可能也不允许在每次 CI 阶段都要等待这么长的时间,符合逻辑的场景应该是只检查本次变更,如果能细化到代码行就更好了。可以实现吗?当然! LLVM 工具链提供了一个脚本 clang-tidy-diff.py,它可以实现细化到代码行。用于帮助我们在 CI 集成时对增量数据进行检查。下载该脚本保存到项目工程的 .build 目录下。 同样的在使用 clang-tidy-diff.py 脚本进行增量分析时,也是需要生成整个项目的 compile_commands.json 配置文件。该脚本只是将我们变更的文件列表通过参数的方式传递给 clang-tidy 可执行文件。然后到 compile_commands.json 中查找这些文件的编译指令来进行静态代码检查。生成请参考上方全量分析命令。 在发起一个 Merge request 或者 Pull request 时,一些 CI 集成工具都会帮我们收集要合并的分支已经合并的目标分支信息。通过这两个分支我们就可以确定下来修改的文件有多少。以下 git 命令可以展示从开启新的功能分支后所有的提交及文件变更信息:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
git diff -U0 feature/new-feature origin/develop^

以 GitLab CI 举例,假如 feature/new-feature 是基于 develop 开出的新功能分支,当发起 Merge request 时,会有两个变量分别描述这两个分支的信息。

  • ${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME} 用来描述新的 feature 分支
  • ${CI_MERGE_REQUEST_TARGET_BRANCH_NAME} 用来描述目标合并分支

连带上面的已经实践过的 gitlab-ci.yml 代码,在 GitLab .gitlab-ci.yml 中我们可以这样编写脚本:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
coverage:
  stage: step-analysis
  script:
    - export
    - git checkout -B "$CI_BUILD_REF_NAME" "$CI_BUILD_REF"
    - cmake -Bbuild -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON -DCMAKE_CXX_STANDARD=14 -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
    - cmake --build build --config Debug --target coverage --parallel
    - lcov --list build/coverage.info
    - set +e && git diff -U0 origin/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}^ ${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME} 
      python3 .build/clang-tidy-diff.py -path=build -p1 -j 8 > build/clang-tidy-output.txt && set -e
    - sonar-scanner -Dsonar.pullrequest.key=${CI_MERGE_REQUEST_IID}
      -Dsonar.pullrequest.branch=${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME}
      -Dsonar.pullrequest.base=${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}
      -Dsonar.gitlab.ref_name=${CI_COMMIT_REF_NAME}
      -Dsonar.gitlab.commit_sha=${CI_COMMIT_SHA}
      -Dsonar.gitlab.project_id=${CI_PROJECT_PATH}
      -Dsonar.projectVersion=${CI_COMMIT_REF_NAME}
  only:
    - merge_requests
  artifacts:
    when: always
    reports:
      junit: build/result.xml
  tags:
    - yunxin-darwin-runner

注意第 10,11 行,我们通过 git diff 将变更信息传递给 clang-tidy-diff.py 脚本,该脚本会自己分析 git diff 结果对变更文件进行静态代码检查。同时在使用 sonar-scanner 进行扫描时我们也传递对应的源分支、目标分支信息,SonarQube 会创建一个 Merge Request 的分支分析信息提供您查看。 需要注意的是给 git diff 传递 base 时需要指定 origin 使用远端分支,通常情况下 GitLab CI 只会 checkout 你要编译的分支,本地可能不存在 base 分支的代码,无法进行比较。如 origin/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}^ 这样在上报到 SonarQube 平台后我们就可以按分支查看分析报告了(提要安装好多分支插件 branch-plugin):

查看某个 MR 或者某个分支的数据是单独显示的。

Merge request 反馈

数据上报到 SonarQube 平台后,我们每次都要人工去这个平台查看反馈报告,这样非常不方便,幸运的是 SonarQube 提供了 SCM 平台反馈能力,以管理员身份登录 SonarQube 平台,设置 GitLab 的配置如下(前提要安装好多分支插件 branch-plugin):

确保配置没有问题后,选择一个你的项目,进入项目设置页面,输入项目 ID 并选择刚才配置好的 GitLab API 保存:

确认连接无问题后保存,再次触发某个 Pipeline 并上报结果到 SonarQube 后,SonarQube 平台会调用 GitLab 提供的 API 将问题数据回报给每个 MR,并且在你有问题的代码中添加评论,效果如下:

Pre-commit 集成

如果你的团队启用了 pre-commit-hooks,您可以添加如下脚本,在每次提交时就检查一次变更的文件,这样在没有上传代码到 GitLab 时就可以及时的发现问题:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.0.1
    hooks:
    -   id: trailing-whitespace
        args: [--markdown-linebreak-ext=md]
    -   id: check-added-large-files
    -   id: check-merge-conflict
    -   id: end-of-file-fixer
    -   id: no-commit-to-branch
        args: ['--pattern', '^(?!((bugfixfeaturereleasehotfixsupportci)\/[A-Za-z0-9\_\-\.]+)$develop).*']
    -   id: check-case-conflict

-   repo: https://github.com/pocc/pre-commit-hooks
    rev: v1.3.4
    hooks:
    -   id: clang-format
        args: [--style=File, -i]
    -   id: clang-tidy
        args: [-p=build]

最后两行描述了如何在提交时进行 clang-tidy 的检查。pre-commit 相关信息请见文章最后扩展阅读。

总结

日常开发中一些 IDE 的辅助工具可以帮助我们随写随发现问题,如 VSCode 的 clang-tidy 检查、CLion 自带 clang-tidy 检查、VS IDE clang-tidy 检查等。通过 IDE 自带的测试工具如 VS Code TestMate、VS IDE 的 Test Explorer 都可以帮助我们本地执行单元测试、API 测试代码。这些可个根据不同开发者不同的开发环境需求而定,并不是强制要求。我们只要在 GitLab 做收口即可。 至此,代码质量相关工具工程化基本结束,我们从代码提交到 CI 再到 SonarQube 报告最后到反馈全流程均通过仓库代码配置文件的方式实现,符合我们预期的想法。在未来维护和扩展中给后来者提供了非常详尽的历史,将最有价值的数据留给他们。这也是写这篇文章的初衷。

扩展阅读

sonarqube branch plugin:https://blog.csdn.net/ewferferr/article/details/120432746 sonarqube C++ plugin:https://blog.csdn.net/qq\_15559817/article/details/100736498 clang-tidy:https://hokein.github.io/clang-tools-tutorial/clang-tidy.html pre-commit:https://pre-commit.com/

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-12-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
大规模异构图召回在美团到店推荐广告的应用
美团到店推荐广告团队在图神经网络的长期落地实践中,思考分析了场景的特点与挑战,针对性地进行了模型设计,并通过大规模训练工具及线上部署优化多次成功落地,带来了线上收入提升。本文主要介绍了大规模图召回技术在美团到店广告场景下的实践经验,包括模型设计思路、模型迭代历程、大规模训练工具以及线上部署性能优化等,希望为从事相关工作的读者带来一些启发。
美团技术团队
2022/12/16
9200
大规模异构图召回在美团到店推荐广告的应用
美团外卖智能陪伴型导购的探索与实践
相比于其他电商场景,外卖场景对于实时发现和反馈用户兴趣的能力有着更高的要求。近年来,美团外卖算法团队摸索出了一套适用于外卖场景的智能陪伴型导购架构和策略。这一举措已经取得了显著成效,本文将详细介绍外卖搜索技术团队搭建智能陪伴型导购时,所遇到的挑战以及解决思路,希望能对大家有所帮助或启发。
美团技术团队
2023/09/05
6070
美团外卖智能陪伴型导购的探索与实践
外卖广告大规模深度学习模型工程实践
总第520篇 2022年 第037篇 在外卖广告CTR场景下,深度学习模型正在从简单DNN小模型过渡到千亿参数复杂模型。基于该背景,本文将重点针对大规模深度模型在全链路带来的挑战,从在线时延、离线效率两个方面展开,阐述外卖广告在大规模深度模型上的工程实践经验,希望能为读者提供思路上的借鉴。 导语 1 背景 2 分析 3 模型推理 3.1 分布式 3.2 CPU加速 3.3 GPU加速 4 特征服务CodeGen优化 4.1 全流程CodeGen优化 4.2 传输优化 4.3 高维ID特征编码 5 样本构建
美团技术团队
2022/07/07
7840
外卖广告大规模深度学习模型工程实践
他山之石 | OPPO 基于图神经网络的搜索推荐算法与实践
导读 大家好,这里是 NewBeeNLP。今天我们分享图神经网络在推荐系统中的应用,以及在oppo业务场景中的实践。
NewBeeNLP
2023/08/28
3790
他山之石 |  OPPO 基于图神经网络的搜索推荐算法与实践
杨玉基:知识图谱在美团推荐场景中的应用
导读:美团是一个生活服务领域的平台,需要大量知识来理解用户的搜索意图,同时对于商家侧我们也需要利用现有的知识对海量信息进行挖掘与提取,进而优化用户体验。今天分享的主题是知识图谱在美团推荐场景中的应用。主要包括以下几方面内容:
DataFunTalk
2022/05/16
1.4K0
2W字长文 | 漫谈工业界图神经网络推荐系统
图神经网络是近年来很火的一个研究方向,在生物化学,推荐系统,自然语言处理等领域都得到了广泛应用。其中图神经网络在推荐系统的应用方面,已有几篇综述[1][2][3]做过详细的归纳总结。但是让人感到美中不足的是,综述中总结的多是学术型工作,偏向于GNN模型上的微调,部分工作其实就是将上游的SGC[4],GrapSage[5],JKNet[6]等模型在几个祖传玩具数据集上刷一下结果讲一个故事,很少关心模型的扩展性,也很少关心图的构建,特征处理,线上打分等不可或缺的环节。
Houye
2021/11/17
1.5K0
2W字长文 | 漫谈工业界图神经网络推荐系统
图技术在美团外卖下的场景化应用及探索
总第534篇 2022年 第051篇 在外卖广告CTR预估建模中,我们依托图技术在场景化上进行了一系列探索。本文首先介绍了使用图网络技术的出发点,然后从特征层面的抽象图关系到子图扩展以及场景感知子图,逐步介绍如何使用图技术建模业务问题,并针对联合训练的线上服务细节及效果进行解释和分析,希望能给从事相关工作的同学带来一些帮助或启发。 1. 引言 1.1 问题与挑战 1.2 图技术介绍 2. 图技术的场景化探索 2.1 基于特征图的场景特征交叉建模 2.2 基于子图扩展的行为图建模 2.3 基于元路径的场景图
美团技术团队
2022/09/13
1.2K0
图技术在美团外卖下的场景化应用及探索
GPU在外卖场景精排模型预估中的应用实践
总第492篇 2022年 第009篇 GPU等专用芯片以较低的成本提供海量算力,已经成为机器学习领域的核心利器,在人工智能时代发挥着越来越重要的作用。如何利用GPU这一利器赋能业务场景,是很多技术研发者都要面临的问题。本文分享了美团外卖搜索/推荐业务中模型预估的GPU架构设计及落地的过程,希望能对从事相关应用研发的同学有所帮助或启发。 1 前言 2 背景 3 外卖搜推场景下的精排模型 4 模型服务架构概览 5 GPU优化实践 5.1 系统优化 5.2 计算优化 5.3 基于DL编译器的自动优化 6 性能表
美团技术团队
2022/03/04
8730
美团BERT的探索和实践
2018年,自然语言处理(Natural Language Processing,NLP)领域最激动人心的进展莫过于预训练语言模型,包括基于RNN的ELMo[1]和ULMFiT[2],基于Transformer[3]的OpenAI GPT[4]及Google BERT[5]等。下图1回顾了近年来预训练语言模型的发展史以及最新的进展。预训练语言模型的成功,证明了我们可以从海量的无标注文本中学到潜在的语义信息,而无需为每一项下游NLP任务单独标注大量训练数据。此外,预训练语言模型的成功也开创了NLP研究的新范式[6],即首先使用大量无监督语料进行语言模型预训练(Pre-training),再使用少量标注语料进行微调(Fine-tuning)来完成具体NLP任务(分类、序列标注、句间关系判断和机器阅读理解等)。
石晓文
2019/11/18
9940
美团BERT的探索和实践
微信「看一看」多模型内容策略与召回
相信对于不少人而言微信已经成为获取资讯的主要场景。与此同时,由于微信用户群体的庞大,也吸引了大量的内容生产者在微信公共平台创造内容,以获取用户关注、点赞、收藏等。微信内的内容推荐产品:看一看应运而生。
week
2020/07/20
1.6K0
微信「看一看」多模型内容策略与召回
美团大脑百亿级知识图谱的构建及应用进展
导读:美团作为中国最大的在线本地生活服务平台,连接着数亿用户和数千万商户,其背后蕴含着丰富的与日常生活相关的知识。美团知识图谱团队从2018年开始着力于图谱构建和利用知识图谱赋能业务,改善用户体验。具体来说,“美团大脑”是通过对美团业务中千万数量级的商家、十亿级别的商品和菜品、数十亿的用户评论和百万级别的场景进行深入的理解来构建用户、商户、商品和场景之间的知识关联,进而形成的生活服务领域的知识大脑。目前,“美团大脑”已经覆盖了数十亿实体、数百亿的三元组,在餐饮、外卖、酒店、到综等领域验证了知识图谱的有效性。今天我们介绍美团大脑中生活服务知识图谱的构建及应用,主要围绕以下3个方面展开:
DataFunTalk
2022/07/23
2.2K0
美团大脑百亿级知识图谱的构建及应用进展
美团图神经网络训练框架的实践和探索
总第510篇 2022年 第027篇 美团搜索与NLP团队在图神经网络的长期落地实践中,基于业务实际场景,自主设计研发了图神经网络框架Tulong,以及配套的图学习平台,提升了模型的规模和迭代效率。本文介绍了模型归纳抽象、基本框架、性能优化,以及上层工具等方面的思考和关键设计,希望为从事相关工作的同学带来启发或者帮助。 1. 前言 1.1 问题和挑战 1.2 美团的解决方案 2. 系统概览 3. 模型框架 3.1 同质图 3.2 异质图 3.3 动态图 4. 训练流程框架 5. 性能优化 5.1 图数据结
美团技术团队
2022/05/20
9000
美团图神经网络训练框架的实践和探索
检索式对话系统在美团客服场景的探索与实践
在传统的客服、IM等场景中,坐席需要花费大量时间回答用户的各种咨询,通常面临答案查询时间长、问题重复、时效要求高等挑战。因而,使用技术手段辅助坐席快速、准确、高效地回答用户的各类问题非常有必要。
美团技术团队
2022/12/16
1.2K0
检索式对话系统在美团客服场景的探索与实践
大厂的广告系统升级,怎能少了大模型的身影
机器之心报道 编辑:思 腾讯广告通过模型能力的提升助力广告主达成生意目标,同时兼顾用户体验,实现多赢局面。 模型是广告系统中的一个复杂且重要的组成部分。之所以说它很复杂,不仅在于庞大的用户量及广告场景,也在于广告这种天然的多模态数据,要求模型具有强大的拟合能力。 思考一下,如果你是一名工程师,怎样才能让你的模型理解广告的内容、主题、目标受众?对于手机、电脑等不同设备,食品、汽车等不同行业,销量、名声等不同目标,模型怎样才能理解不同的广告场景?又怎样才能从百万条广告中为受众选择合适的推送?面对流量竞争加剧的大
机器之心
2022/07/04
1.7K0
大厂的广告系统升级,怎能少了大模型的身影
综述 | GNN金融风控领域业界进展调研
由百度的paddle一个基于 PaddlePaddle 的高效易用的图学习框架
用户3946442
2022/04/11
3.6K0
综述 | GNN金融风控领域业界进展调研
腾讯太极机器学习平台|大规模训练加速框架Light 在广告粗排场景的落地
背景介绍 太极机器学习平台由腾讯云机智平台和tesla平台协同共建而成,太极联合团队在深度学习训练加速上有深厚的技术累积,曾两次刷新了 ImageNet 训练速度的世界记录,并发表相应论文。 为使团队沉淀的训练加速技术赋能鹅厂更多业务场景并创造更大价值,Light 训练产品应运而生。Light 是云帆Oteam基于当前社区主流深度学习框架开发的一套多机多卡深度学习训练加速框架,用户只需要做几行代码即可接入并获得高性能加速能力。 从去年开始,太极团队针对广告训练场景进行了专项的性能优化,并针对业务模型迭
腾讯大讲堂
2021/07/16
1.7K0
他山之石 | 预训练模型落地"最后一公里"
大家好,这里是NewBeeNLP。预训练模型如今在业界已经占据主导地位,但是随着模型规模越来越大,如何完美落地成为制约其效果的一大因素。今天和大家分享,来自美团的基于预训练语言模型压缩和蒸馏的落地实践。全文会围绕下面三点展开:
NewBeeNLP
2022/11/17
9070
他山之石 | 预训练模型落地"最后一公里"
图算法在网络黑产挖掘中的思考
导读:虚拟网络中存在部分黑产用户,这部分用户通过违法犯罪等不正当的方式去谋取利益。作为恶意内容生产的源头,管控相关黑产用户可以保障各业务健康平稳运行。当前工业界与学术界的许多组织通常采用树形模型、社区划分等方式挖掘黑产用户,但树形模型、社区划分的方式存在一定短板,为了更好地挖掘黑产用户,我们通过图表征学习与聚类相结合的方式进行挖掘。本文将为大家介绍图算法在网络黑产挖掘中的思考与应用,主要介绍:
NewBeeNLP
2021/03/03
9491
图算法在网络黑产挖掘中的思考
图神经网络系统介绍与总结分析
图神经网络算法将深度神经网络的运算(如卷积、梯度计算)与迭代图传播结合在一起:每个顶点的特征都是由其邻居顶点的特征结合一组深度神经网络来计算。
一点人工一点智能
2022/12/27
9710
图神经网络系统介绍与总结分析
广告行业中那些趣事系列15:超实用的基于BERT美团搜索实践
摘要:本篇主要学习和分析BERT在美团搜索排序中的项目实践。首先介绍了业务背景,主要对比了美团搜索业务场景和我们的应用场景;然后讲了下计算query和doc相关性的方法,主要包括计算字面相关性和计算语义相关性,重点介绍了基于BERT的语义相关性内容;最后也是本篇的重点,分析了美团搜索排序项目实践以及对我们业务的思考,其中包括数据样本增强、BERT领域适配、模型轻量化、联合训练和排序服务架构优化等一系列眼花缭乱但是又极具工程价值的优化操作,对于我们有极大的工程借鉴价值。
数据拾光者
2022/05/05
5380
广告行业中那些趣事系列15:超实用的基于BERT美团搜索实践
推荐阅读
相关推荐
大规模异构图召回在美团到店推荐广告的应用
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验