持续集成

持续整合(英语:Continuous integration,缩写CI),又译为持续集成,是一种软件工程流程,是将所有软件工程师对于软件的工作副本持续集成到共享主线(mainline)的一种举措。该名称最早由[1]葛来迪·布区(Grady Booch)在他的布区方法英语Booch method[2]中提出,在测试驱动开发(TDD)的作法中,通常还会搭配自动单元测试。持续集成的提出主要是为解决软件进行系统集成时面临的各项问题,极限编程称这些问题为集成地狱(integration hell)。

“持续集成持” 操作时的画面

解释

持续集成的宗旨是避免集成问题,如同在极限编程(XP)方法学中描述的集成地狱。持续集成并非普遍接受是用来改善集成频率的方法,因此重要的是区分两者所带来的效益[来源请求]

在极限编程方法学,持续集成需要达到最佳成果,必须依靠着自动化集成单元测试并通过测试驱动开发。首先必须设想在上线运作之前,已在开发环境完成并通过所有的单元测试。这将帮助避免一个开发者的作业流程,导致其他开发者作业的中断。如果有需要,可以在完整上线运作之前进用部分已完成的功能,例如使用功能切换

接着进行CI伺服器建置概念的阐述、自动化执行单元测试的周期与每次测试需要提交给开发者的报告。建置CI伺服器的用途(不一定要执行单元测试) 已经开始在极限编程(XP)社群之外的团队练习。如今,许多企业组织已经开始采用持续性集成,而非采用完整的极限编程(XP)。

除了自动化单元测试,组织在运用持续性集成(CI)一般会建置CI伺服器来维护持续性套用质量控制的程序-小部分的影响,并且经常性使用。除了执行单元与集成测试之外,还有额外的静态与动态测试,量测与描述性能,从程序来原始码摘录与文件格式与促成手动质量保证(QA)程序。持续性质量控制应用程式用意在提升软件质量以及减少交付的时间,在完成所有开发后,取代传统软件上线质量控制机制。此非常相似进行频繁集成的最初概念让集成得以在QA程序上更容易地达成。

同样的道理,持续性交付的最佳实践进一步扩展了持续性集成(CI),以确保软件检核在主要程序上并且能够布署到用户以确保实际的布署流程可以非常快速。

工作流程

当从事变更时,开发者会从目前基础代码库复制以进行作业,其他开发者提交代码的变更至来源代码库,并透过副本的方式取代来源代码库的代码。不只变更目前的代码库,新的代码也可以新增成为程序库、其它共享资源与潜在冲突。

当分支代码保持在取出状态时间越长,当分支代码开发者进行主线重新集成时,就愈容易遭遇集成多重冲突的风险以及失败。当开发者将代码提交到代码库时,首先必须更新代码以反映他们在代码库中的更改,因为他们拿到了副本。代码库包含的更改越多,开发人员在提交自己的更改前必须执行的工作越多。

终于,该程序库也许变成非常不同于开发者的目标代码,他们进入有时候被称为合并地狱或集成地狱[3]的阶段,这时候开发者所花费的集成时间,将超过最初代码开发的时间。

持续性集成涉及预先集成与预先与经常性的集成,借此来避免踩到集成地狱的陷阱,实践的目标是减少重工、减少成本与时间[4]

持续性集成补充的实践是在提交成果之前,每个开发人员必须执行一个完整的构建与执行及通过所有的单元测试集成测试,这些都是当持续性集成伺服器侦测到代码有新的提交时,必须经常性与自动化的进行。

历史

葛来迪·布区于1994年出版的《面向对象分析设计与应用》(Object-Oriented Analysis and Design with Applications)第二版[5]中,首次提出持续集成这个名词。

1997年,肯特·贝克与Ron Jeffries建立了极限编程方法,将持续集成作为极限编程的一部分。

最佳实践

本节列出了各个作者就如何实现持续集成提出的最佳实践,以及如何自动化的进行相关实践。组建自动化本身就是最佳实践。

持续性集成–经常将新的或改变的代码与现有的代码库进行汇集,这作业应该频繁地发生,在提交构建之间不存在中间窗口,并且没有错误可以在没有开发人员注意到并立即纠正的情况下产生。最佳的做法是透过每次提交一个程序库来触发建构,而不是定期预定的版本才进行建构。在快速提交的多开发者环境实践是这样的:在每次提交之后的短时间内触发,然后在时间到期后开始建构,或者在上次建构间隔一段时间之后。许多自动化工具都有提供相关的自动化调度。

另一个要因是建构一个支持原子提交的版本控制系统,此系统可以让开发人员的每次变更都可成为单一提交操作,但如试图从只有改变一半的文件进行构建没有意义。

为了实现上述目标,持续集成必须依靠以下原则。

维护一个代码库

这种做法意味着使用项目来源代码版本控制系统。所有项目相关的代码都需要存储在该代码库中,在这种做法的控制界中,依惯例该系统应该可以从新取出的进行构建并且不需要额外的作业。提倡极限编程法的马丁·福勒也主张,必须有简单的工具来支持程序开发的分支作业。相反的,最好将所有变更集成起来而不是同时维护多个版本的软件。简单的说,这是将软件开发工作版本化的地方。

自动构建

透过一个单一指令来达成系统建构。许多的建构工具软件如MAKE已存在许多年,其他较新的工具程序都频繁的使用在持续性集成环境。建构的自动化应该包含自动化作业与集成作业,并且通常包含正式环境的布署。在许多案例中,代码的建构不仅仅只是编译二进制元,通常总是伴随的文件的产生、网站的建构、状态数据与布署的封装媒体。(如Debian的DEB、Red Hat的RPM与微软的MSI文件)。

让构建时会自我测试

一旦代码编辑好,下一个阶段应该要进行所有的测试,以确保软件开发的成果符合预期。

每人每天都应提交一次

透过定期的承诺,每个提交者都能够减少变更冲突的数量。一次检查一个星期的工作成果时,遭遇到集成冲突的风险相对交高,这时排解的困难性也相对升高。早期性系统的局部冲突,将可以让系统团队及时因应与进行调整建构的方向。

一天至少提交一次(每个功能构建一次)通常被定义为持续集成的一部分。此外,建议每晚在提交之后立即进行建构,以上都是下限值,实际上的频率往往要高出许多。

每份提交都应进行建置

系统应该要在每次提交之后,针对当下的版本进行建构以确认程序可正确的集成。通常实务上会使用自动化进行持续集成,也许这个也可以手动进行。在许多时候,持续集成是使用自动化持续集成的代名词,透过持续集成伺服器或应用程式监视版本控制系统的变化,然后自动进行建构的过程。

维持快速建置

每个建置必须要维持快速完成,如此一来便可以避免集成问题。

用在线环境的复本测试

拥有一个测试环境并不能保证一切顺利,也会在布署上线时产生错误,因为测试环境和正式环境或许存在很大的差距。然而,如果要建置一份与在线环境一模一样的测试环境,还需要成本考量。相反的,测试环境或是独立的预备环境应该要建置实际正式环境的扩展版本,以在可容许的成本内同时达到维护堆栈结构技术与细微化。在那些测试环境中,服务虚拟化是通常运来获得,随需求存取超出团队控制的依赖关系(如API、第三方应用程式、第三方服务与大型主机系统)、持续演变或者因太复杂无法在虚拟实验室中还原的情境。

让获取最新发布版本更容易

使建置容易让利益关系人与测试者使用,能够减少许多因为建置的成果不合乎需求的重工状况。此外,提早测是能够在提早程序布署前知道变更的缺陷。在某些情况下,也可以提前查出错误,从而减少解决问题所需的工作量。所有程序员都应该从存储库更新项目来开始新的一天。这样,他们将可保持该程序存储库的最新状态。

任何人都可以查看最后建置的结果

系统应该要让任何人都可以容易查找出建构是否中断,并且可以显示何人正在变更相关程序。

自动部署

大部分的持续集成系统允许在建置完成后自动执行代码。因此能够写一段代码来布署应用程式至任何人都可以观察的测试伺服器。在持续性集成未来的思考发展成像持续性布署迈进。持续性布署将要求直接将软件布署至测试环境中,这通常需要额外的自动化机制来防止程序缺陷。

成本与效益

持续集成目的在产生以下效益:

  1. 及早发现集成错误,且由于修订的内容较小所以易于追踪,这可以节省项目的时间与成本。
  2. 避免发布日期的前一分钟发生混乱,当每个人都会尝试为他们所造成的那一点点不兼容的版本做检查。
  3. 当单元测试失败或发生错误,若开发人员需要在不调试的情况下还原代码库到一个没有问题的状态,只需要放弃一小部分的更改 (因为集成的次数频繁)。
  4. 让 "最新" 的程序可保持可用的状态供测试、展示或发布用。
  5. 频繁的提交代码会促使开发人员建立模块化,低复杂性的代码。

关于持续性自动化测试的效益:

  1. 强制执行频繁的自动化测试纪律
  2. 当改变对全系统造成影响时立即反馈
  3. 自动化测试和持续性集成产生的软件度量(如代码覆盖度量,代码复杂度和功能完整性等)标准将开发人员集中在开发功能性,高质量的代码上,并帮助开发团队发展。

持续集成的缺点包含:

  1. 构建一个自动化测试包需要大量的工作,包括不断努力以覆盖新功能,并依照特定情境进行代码修改。
    • 无论是否采用持续性集成,测试被认为是软件开发的最佳实践,测试必须依循软件布署的最佳实务。自动化是诸如测试驱动开发之类项目方法的一个组成部分。
    • 持续性集成可以在不需要测试包下执行,但是如果必须手动和经常地完成,生产产品的质量保证成本将会提高。
  2. 建置系统需要一些工作,而且可能变得复杂,难以灵活修改。
    • 但是,也有一些开放来源代码的持续集成的项目软件可以使用。
  3. 如果范围很小或包含无法测试的旧版代码,持续性集成不一定有价值。
  4. 增加的价值取决于测试的质量以及代码的真实可测性。
  5. 较大的团队意味着不断将代码添加到集成队列中,因此追踪交付(同时保持质量)很困难,而排队可能会减慢所有人的进度。
  6. 通过一天的多次提交和合并,功能的部分代码可以轻松推送,如此一来集成测试将会失败直到整个功能开发完成。

参见

参考文献

  1. ^ Continuous Integration. (原始内容存档于2019-05-16). 
  2. ^ Booch, Grady. Object Oriented Design: With Applications. Benjamin Cummings. 1991: 209 [18 August 2014]. ISBN 9780805300918. (原始内容存档于2017-04-21). 
  3. ^ Ward Cunningham. Integration Hell. WikiWikiWeb. Ward Cunningham. 5 August 2009 [19 September 2009]. (原始内容存档于2011-08-06). 
  4. ^ What is Continuous Integration?. [2017-12-21]. (原始内容存档于2021-02-16). 
  5. ^ Grady Booch. Object-Oriented Analysis and Design with applications (2nd edition, 15th printing) (PDF). December 1998 [2 December 2014]. (原始内容存档 (PDF)于2019-08-19). 

拓展阅读

外部链接