多年来,Mozilla 的工程团队引入了代码质量工具。这个工具链在复杂的 Firefox 开发周期的各个阶段发挥作用。 在这篇文章中,我们将探讨我们开发的工具类型、它们解决的一些挑战以及我们开发的架构解决方案。当我们谈论代码质量工具时,我们指的是以下类型的工具:
- 静态分析
- 代码风格检查
- 编码风格
- 代码覆盖率
一般来说,对于规模小于构建 Firefox 桌面浏览器的开发项目,简单的 CI(持续集成)作业设置和配置相对容易。它们针对有限数量的语言。许多开发人员可以使用各种 CI 平台和设置。
Firefox 是一个庞大的(2100 万行代码)开源软件项目,起源于 1998 年的 Netscape。 我们使用多种语言(C++、Rust、JavaScript、Python 等),每天管理数百个更改,并处理规模为几 GB 的代码库。这带来了一些独特的挑战。
工具
在这篇文章中,我们不会列出我们运行的所有工具。 相反,我们将重点关注我们工具的为什么和如何。
您可以在我们的文档中找到所有工具的详细信息:https://firefox-source-docs.mozilla.ac.cn/code-quality/
由于很难在 Firefox 开发人员的工作站上强制使用工具(例如,钩子),我们决定将精力集中在审查阶段运行这些工具。
挑战
不同类型的错误
我们在测试质量时会遇到不同类型的错误。这是我们的第一个挑战。
- 某些问题总会破坏 CI(持续集成),没有误报(构建错误,一些强制的格式规则未遵守等)。例如,我们有针对我们的代码库的自定义 C++ 检查器。我们知道它们会给产品带来问题。因此,我们确保破坏 CI,以防止代码落地并给产品带来麻烦。
- 潜在错误: 从不同的角度来看,C/C++ 要么过于复杂,要么就是有问题的语言。因此,已经开发了一些工具(静态分析器)来防止出现问题。但是,这些检查器会产生误报。(否则,它们将是编译器触发的错误。)
- 不错的工具: 可以使代码库更加一致的检查器。这些工具使代码更易读,并减少了技术债务。
代码库的大小
我们的下一个主要挑战:我们正在处理 2100 万行代码。在启用新的检查器之前,我们无法修复所有数百个现有问题,我们也不想强迫开发人员修复所有不是由于他们提出的更改而产生的预先存在的问题。因此,在如此大规模的操作中,我们不得不提出不同的解决方案。
为了解决这个问题,我们确定并部署了两种解决方案。当问题很容易修复(例如 eslint、flake8 等)时,我们创建并维护了一个可以运行这些工具的目录/文件列表,并逐步在越来越多的目录中修复问题。
对于像 C++ 静态分析器这样的更复杂的检查器,我们开发了一些启发式方法来识别问题是新的还是旧的。要么我们创建一个以前允许使用的列表(例如:过时的线程使用),要么我们使用一些启发式方法评估缺陷是新的还是已经存在的。
架构
我们当前基础设施的最大优势是,我们使用的是 Mozilla 优秀的工程团队构建的现有工具。我们使用Taskcluster,这是我们内部用于大量测试和构建 Firefox 的 CI 系统。此外,我们依赖于我们自己的Phabricator 实例来审查每个 Firefox 修补程序,然后再将其发布。
工作流程
每个修补程序都遵循相同的工作流程。
- Phabricator 通知我们的 Web 服务,需要分析新的修补程序。
- Web 服务使用一组工作进程将修补程序及其祖先应用到预先克隆的代码库中。(请记住,Firefox 主代码库 的大小为几 GB!)
- 应用后,该修补程序将被推送到我们的Try 服务器 上。Try 服务器是 Mozilla 开发人员用来触发 CI 构建(尝试构建)的 Mercurial 服务器。
- Try 服务器在 Taskcluster 上创建一组代码分析任务:这些任务及其触发规则由开发人员在 Firefox 源代码中自行定义。
- 每个代码分析任务都会生成一个 JSON 负载,其中列出了在堆栈中发现的所有潜在缺陷。
- 最后,一个发布任务会分析、聚合和过滤所有问题。 然后,它将相关问题发布到 Phabricator 和我们的 Web 服务中。这样,开发人员可以随时查看它们,并在出现问题时收到通知。
此工作流程通常在 12 到 15 分钟内完成大多数修补程序。修改大量文件的某些修补程序可能会触发更多分析器,因此处理速度较慢。
您可以在项目文档中找到有关架构的更多信息。
优势
这种方法的主要优势是:它允许我们使用许多开发人员自己计算机上可用的现有工具。(这可以通过使用mach 工具实现。)
另一个重大优势是:我们不需要维护自己的分析器,也不需要维护它们的依赖项。这些分析器可以确保使用最新版本持续运行,因为它们是在 Firefox 代码库中定义的,并且由世界各地的人维护。
我们目前支持特定的分析器(clang-tidy、clang-format、rustfmt、mozlint 等),以及通用格式。这使得任何 Firefox 开发人员都可以轻松扩展我们的平台功能。
外观
以下是 Phabricator 上问题的几个屏幕截图。这些是大多数 Mozilla 的 Firefox 开发人员可能会看到的流程视图。
修订版中发现的所有问题:
汇总注释列表:
在修补程序本身中报告的问题
未来计划
这个代码质量工作流程项目是由一个相对较小的团队在过去几年中构建的,并在过去一年中达到了极高的稳定性水平。现在,我们能够在平均不到 15 分钟的时间内处理来自 Firefox 开发人员的每个修补程序。
我们还使用这个平台支持其他几个 Mozilla 项目:NSS(Firefox 中的主要加密库)、一些 CI 内部项目,以及未来预计的新的项目。
几个月来,感谢我们与育碧的合作,我们一直在进行一项实验,使用机器学习在审查阶段分析修补程序。该分析会提交一份详细报告,根据大量因素(例如复杂性、流程指标等)评估修补程序的风险。 未来,这个项目可能会让我们减少 Firefox 代码库中的回归次数,并加快审查速度。
在接下来的几个季度中,我们计划将模糊测试引入着陆阶段,方法是将 Mozilla 模糊测试器移植到 Taskcluster(模糊测试团队付出了巨大努力!)。我们还想在不给开发人员发送垃圾邮件的情况下报告更多问题,通过仅报告修订版更新时可能出现的新问题、列出补丁带来的问题或与先前已知状态进行比较,来避免重复。
最后,我们希望通过利用工程流团队开发的新电子邮件通知系统来增强我们的报告机制。这可能会改变问题在 Phabricator 中的显示方式,并扩展我们对检测到的问题的评论和代码风格检查的能力。
带来补丁。我们预计它们会随着 Firefox 的每个新版本不断出现。但我们为开发的代码质量工具感到自豪,这些工具支持 Mozilla 工程师和贡献者构建更好的 Firefox。
如何参与构建 Firefox
想要参与进来,或了解更多关于构建 Firefox 的信息?有许多方法可以参与到我们浏览器技术的构建中。代码审查平台也是开源的,可以在 Github 上获取,欢迎贡献。
关于 Bastien Abadie
Mozilla 的高级软件工程师,代码审查机器人的维护者
7 条评论