DevOps 技术:持续集成

软件系统非常复杂,对一个文件进行明显简单、独立的更改可能会对整个系统造成意外的影响。当大量开发者处理相关系统时,协调代码更新是个难题,而且不同开发者所做的更改可能并不兼容。

持续集成 (CI) 这一做法就是为了解决这些问题。持续集成遵循以下原则:如果某个操作需要花费大量时间和精力,您应该更频繁地执行此操作,使这个过程不那么痛苦。持续集成可创建快速反馈环并确保开发者以小批量方式工作,能够让团队开发高质量的软件、降低软件开发和维护费用,并提高团队工作效率。

如何实现持续集成

当您的组织开始实践持续集成时,开发者会定期将其所有工作集成到代码库的主版本(称为主干、主实例或主线)中。DevOps 研究和评估组织 (DORA) 的研究 (PDF) 表明,如果开发者以至少每天一次的频率将其作业合并到主干中,团队的表现会更好。合并之前和合并之后,系统都会运行一组自动化测试,用于验证更改不会引入回归错误。如果这些自动化测试失败,团队会立即停止正在进行的工作来解决此问题。

持续集成可确保软件始终处于正常运行状态,还可确保开发者分支不会大幅度偏离主干。持续集成的优势非常明显:研究 (PDF) 显示,它可以提高部署频率、系统稳定性和软件质量。

成功实现持续集成的关键要素包括以下几项:

  • 每次提交都应触发软件的构建。
  • 每次提交都应触发一系列可在几分钟内提供反馈的自动测试。

要实现这些元素,您需要以下几项:

  • 自动构建流程。持续集成的第一步是拥有一个自动脚本,它能够创建可部署到任何环境的软件包。由持续集成构建创建的软件包应具有权威性,并可供所有下游流程使用。这些构建应进行编号且可重复。每天应至少成功运行一次构建流程。
  • 一套自动化测试。如果没有,请先编写少量涵盖系统高价值功能的单元测试和验收测试 (PDF)。确保测试可靠。这样一来,当测试失败时,您就会知道存在实际问题;当测试通过时,您便可放心 - 系统没有严重问题。然后,确保测试涵盖所有新功能。这些测试应该能够快速运行,以便尽快为开发者提供反馈。您的测试每天应至少成功运行一次。归根结底,如果您有性能和验收测试,开发者应该每天都获得反馈。
  • 在每次签入时运行构建和自动化测试的持续集成系统。该系统还应向团队显示状态。您可以采用有趣的方式来显示状态 - 例如,当构建中断时,您可以使用电喇叭或红绿灯来指示。请勿使用电子邮件通知;许多人会忽略电子邮件通知或创建隐藏通知的过滤条件。聊天系统中的通知是更好且更常用的通知方式。

根据 Kent Beck 和极限编程社区(该术语的发源地)的定义,持续集成还包含两种可提高软件交付性能的拓展做法:

  • 主干开发做法,即开发者以小批量的方式处理主干/主线。他们以至少每天一次的频率将其工作合并到共享主干/主线中,而不是处理生命周期较长的功能分支。
  • 设置一份协议,规定当构建中断时,构建修复工作应该优于任何其他工作

持续集成需要自动化单元测试。这些测试应足够全面,让您有信心确定软件可按预期运行。测试还必须在几分钟或更短的时间内运行。如果自动化单元测试的运行时间较长,开发者就不会愿意频繁运行它们。如果测试不频繁运行,则测试失败可能是许多不同的更改所致,导致难以调试。不频繁运行的测试很难维护。

创建可维护的自动化单元测试套件非常复杂。解决此问题的一个好方法是采用测试驱动开发 (TDD),即开发者在实现让测试通过的代码之前,先编写最初失败的自动化测试。TDD 具有若干优势,其中一个优势是确保开发者能够编写出易于测试的模块化代码,从而降低生成的自动化测试套件的维护费用。许多组织都没有可维护的自动化单元测试套件,尽管如此,他们仍未采用 TDD。

关于持续集成的争议

如前所述,有时持续集成会被视作一种有争议的做法。持续集成需要开发者将大型功能和其他更改拆分为可频繁集成到主干中的小型增量步骤。对于不习惯以这种方式工作的开发者而言,这是一个改变。此外,当团队改用小步骤时,完成大型功能可能需要更长的时间。但总的来说,您不希望优化开发人员在分支上声明一个大型功能的速度,而是希望能尽快审核、集成、测试和部署更改。如果是独立的小型更改,并且它们所在的分支只在短时间内存在,则此流程会使软件的开发和交付更快且更稳定 (PDF)。小批量工作还可以确保开发者定期获得来自其他开发者、测试人员、客户以及自动化性能和安全测试的关于工作对系统总体影响的反馈。这可以进而帮助您更轻松、更快速地检测、分类和修复任何问题。

尽管存在这些争议,但对于希望开始持续交付之旅的任何组织来说,帮助软件开发团队实现持续集成应该是首要任务。

常见误区

以下是阻碍持续集成广泛采用的常见误区:

  • 未将所有资源放入代码库中。构建和配置应用及系统所需的一切资源都应放入代码库中。这似乎不在持续集成的涵盖范围内,但它是重要的基础步骤。
  • 未自动化构建流程。手动执行步骤可能会导致错误,并且不记录某些步骤。
  • 未在每次更改时触发快速测试。全面的端到端测试是必要的,但快速测试(通常是单元测试)对于获得快速反馈也很重要。
  • 未立即修复中断的构建。持续集成的一个关键目标是得到让每个人都可以开发的稳定构建。如果无法在几分钟内修复构建,则应确定并还原导致构建中断的更改。
  • 测试的运行时间过长。测试的运行时间不应超过几分钟,根据 DORA 的研究 (PDF),上限应为 10 分钟左右。如果构建花费的时间超过此值,您应该提高测试效率,添加更多计算资源以便并行运行它们,或者使用部署流水线模式将运行较长时间的测试拆分为单独的构建。
  • 未频繁合并到主干。许多组织都有自动化测试和构建,但并未要求每天都要合并到主干。这会导致更难集成生命周期较长的分支,并延长开发者的反馈环。

衡量持续集成的方法

前面讨论的持续集成概念概述了衡量系统和开发环境中持续集成效果的方法,如下表所示。通过收集这些指标,您可以针对它们优化流程和工具。这样可以得到更好的持续集成做法,并缩短开发者的反馈环。

测试的因素 衡量的指标
代码提交触发软件的构建 导致在没有人工干预的情况下软件构建的代码提交的百分比。
代码提交触发一系列自动测试 导致在没有人工干预的情况下运行一套自动化测试的代码提交的百分比。
每天成功执行自动构建和测试 每天成功执行的自动化构建的百分比和每天成功执行的自动化测试的百分比。
测试人员可使用当前构建进行探索性测试 构建对测试人员的可用性或不可用性。
开发者每天都收到来自验收和性能测试的反馈 来自验收和性能测试的反馈对开发者的可用性,即在一天之内为开发者提供反馈的测试所占的百分比。
中断的构建立即得到修复 从构建中断到修复(通过检查解决问题或还原破坏性更改)的时间。

后续步骤