持续集成与持续部署之间的真正区别

https://www.freecodecamp.org/news/the-real-difference-between-ci-and-cd/

有很多内容描述什么是持续集成,持续交付和持续部署。但是这些过程首先要达到什么目的?

了解正确使用CI和CD所解决的问题至关重要。这将使您的团队可以改善您的流程,避免花费精力去追求那些不会给您的流程带来任何价值的幻想指标。

持续集成是团队问题

如果您在团队中工作,则可能有多个开发人员在同一个存储库中工作。存储库中有一个主分支,其中载有最新版本的代码。开发人员在不同分支上从事不同的工作。变更完成后,他们会将其推送或合并到主分支。最终,整个团队将拉动这一变化。

我们要避免的情况是错误的提交使其进入主分支。错误意味着代码无法编译或应用程序无法启动或无法使用。为什么?不是因为应用程序损坏了,还是因为所有测试必须始终为绿色。这不是问题,您可以决定不部署该版本,然后等待修复。

问题是您的整个团队都陷入了困境。所有提出错误提交的开发人员都将花费5分钟来思考为什么它不起作用。有些人可能会尝试查找错误的提交。有些人会尝试与有问题的代码作者并行解决问题。

这对您的团队来说是浪费时间。最糟糕的是,重复发生的事件加剧了对主分支机构的不信任,并鼓励开发人员分开工作。

持续集成就是为了防止主分支中断,从而使您的团队不会陷入困境。而已。这并不是要让所有测试始终保持绿色并且主分支在每次提交时都可以部署到生产中。

持续集成的过程独立于任何工具。您可以手动验证分支和主分支的合并在本地是否有效,然后仅将合并实际推送到存储库。但这将是非常低效的。这就是为什么使用自动检查实现持续集成的原因。

检查确保至少:

  • 该应用程序应构建并启动
  • 最关键的功能应始终保持工作状态(用户注册/登录过程以及关键的业务功能)
  • 所有开发人员都依赖的应用程序通用层应该是稳定的。这意味着对这些零件进行单元测试。

实际上,这意味着您需要提取适用于您的任何单元测试框架并保护应用程序的公共层。有时,代码不是很多,可以很快完成。另外,您还需要添加“烟雾测试”以验证代码是否已编译以及应用程序是否启动。这对于具有疯狂依赖注入的技术(例如Java Spring或.NET core)尤其重要。在大型项目中,很容易误连接依赖项,因此必须验证该应用程序始终启动。

如果您有成百上千的测试,则不需要为每个合并运行所有测试。这将花费大量时间,并且大多数测试可能会验证“非团队阻止者”功能。

我们将在接下来的部分中看到连续交付的过程将如何充分利用这许多测试。

与工具无关

工具和自动检查都可以。但是,如果您的开发人员仅合并他们工作了数周的巨型分支机构,那么他们将无济于事。团队将花费大量时间合并分支,并修复最终会出现的代码不兼容问题。与错误的提交阻塞在一起一样浪费时间。

持续集成与工具无关。这是关于小块工作并将新代码集成到主分支并频繁提取的问题。

通常至少每天一次。将您正在处理的任务拆分为较小的任务。经常合并您的代码,并经常提取。这样一来,没有人能分开工作超过一两天,问题就没有时间滚雪球了。

一项大型任务不需要全部都在一个分支中。应该永远不会。将进行中的工作合并到主分支的技术称为“抽象分支”和“功能切换”。有关  更多详细信息,请参见博客文章“ 如何开始进行持续集成 ”。

优质CI的关键点

非常简单。保持简短。最多3-7分钟。这与CPU和资源无关。这与开发人员的生产力有关。生产力的首要规则是专注。做一件事,完成它,然后移到下一件事。

上下文切换成本很高。研究表明,当您被打扰时,大约需要23分钟才能重新专注于某件事。

想象一下,您推动分支进行合并。您开始另一个任务。您花了15到20分钟才能进入。在您进入区域后的一分钟,您会从20分钟长的CI构建中收到针对先前任务的“构建失败”通知。您回来修复它。您再次推动它。您来回走动很容易超过20分钟。

每天一次或两次将20分钟乘以团队中开发人员的数量……这是浪费了很多宝贵的时间。

现在,假设反馈是否在3分钟内到来。您可能根本不会启动新任务。您将有证据再次阅读您的代码,或者在等待时检查PR。失败的通知将到来,您将对其进行修复。然后,您可以继续执行下一个任务。这就是您的流程应启用的重点。

保持CI的构建时间短,这是一个折衷方案。在CI范围内运行时间更长或几乎没有价值的测试应移至CD步骤。是的,那里的故障也需要修复。但是,由于它们不会阻止任何人做他们的事情,因此您可以在完成工作后将这些修补程序作为“下一项任务”来处理。只需在工作时关闭通知,然后不时检查一下即可。保持上下文切换到最小。

持续交付和部署是工程问题

让我们解决一下定义,以消除这些障碍。

持续交付是指能够随时部署任何版本的代码。实际上,它是指代码的最新版本。您不会自动部署,通常是因为您不必或不受项目生命周期的限制。但是只要有人愿意,就可以在最短的时间内完成部署。有人可以成为想要在暂存或预生产环境中进行测试的测试/ QA团队。或者实际上可能是时候将代码推广到生产中了。

连续交付的想法是准备与您要在环境中运行的项目尽可能接近的工件。如果使用Java,则可以是.jar或.war文件;如果使用.NET,则可以是可执行文件。它们也可以是已转译的JS代码的文件夹,甚至是Docker容器的文件夹,无论使部署变得更短(即,您已经预先构建了尽可能多的内容)。

通过准备工件,我并不是要把代码变成工件。这通常是一些脚本和执行时间。准备方式:

运行您可以执行的所有测试,以确保代码一旦部署便可以正常工作。如果可以自动执行单元测试,集成测试,端到端测试,甚至性能测试。

这样,您可以过滤主分支的哪些版本实际上已准备好生产,哪些尚未准备就绪。理想的测试套件:

  • 确保应用程序的关键功能正常运行。理想情况下,所有功能
  • 确保没有引入任何性能破坏因素,因此当您的新版本受到众多用户的欢迎时,它就有机会持久
  • 空运行您的代码所需的任何数据库更新,以免出现意外

它不需要非常快。30分钟或1小时是可以接受的。

持续部署是下一步。您将最新和生产就绪版本的代码部署到某些环境。如果您对CD测试套件足够信任,则是理想的生产方式。

请注意,根据上下文,这并非总是可能或值得付出。连续交付通常足以提高工作效率,尤其是当您在封闭的网络中工作并且可以部署的环境有限时。也可能是软件的发布周期阻止了计划外的部署。

持续交付和持续部署(从现在起将它们称为CD)不是团队问题。他们的目的是在执行时间,维护工作和测试套件的相关性之间找到适当的平衡,以便能够说“此版本可以正常工作”。

这是一个平衡。如果您的测试持续30个小时,那就有问题了。有关Oracle数据库测试套件的外观,请参见这篇史诗般的帖子。但是,如果您花费大量时间使测试与最新代码保持同步,那会阻碍团队的进步,那也不是一件好事。另外,如果您的测试套件几乎没有任何保证,那基本上是没有用的。

在理想的世界中,我们每次提交到主分支都需要一组可部署的工件。您可以看到我们有一个垂直的可伸缩性问题:我们从代码移到工件的速度越快,我们就越准备好部署最新版本的代码。

有什么大不同?

持续集成是一个水平可伸缩性问题。您希望开发人员经常合并其代码,因此检查必须快速。理想情况下,几分钟之内就可以避免开发人员始终通过CI版本的高度异步反馈来切换上下文。

您拥有的开发人员越多,则在所有活动分支上运行简单检查(构建和测试)所需的计算能力就越高。

良好的CI构建:

确保没有将破坏基本内容并阻止其他团队成员工作的代码引入主分支,并且

足够快,可以在几分钟内向开发人员提供反馈,以防止任务之间进行上下文切换。

持续交付和部署是垂直可伸缩性问题。您需要执行一个相当复杂的操作。

好的CD版本:

确保尽可能多的功能正常运行。

速度越快越好,但这不是速度问题。30至60分钟的构建就可以了。

一个常见的误解是将CD视为诸如CI之类的水平可伸缩性问题:从代码到工件的迁移速度越快,实际处理的提交越多,就越接近理想的情况。

但是我们不需要。为每次提交尽可能快地生成工件通常是过大的。您可以尽最大的努力很好地使用CD:只有一个CD构建,它将在给定构建完成后立即选择最新提交进行验证。

毫无疑问CD。真的很难。获得足够的测试信心才能说您的软件已准备好自动部署,通常可以在诸如API或简单UI之类的底层应用程序上使用。在复杂的UI或大型整体系统上很难实现。

结论

用于执行CI和CD的工具和原理通常非常相似。但是目标是非常不同的。

持续集成是在开发人员反馈回路的速度与您执行的检查(构建和测试)的相关性之间做出的折衷。没有任何妨碍团队进步的代码可以进入主分支。

持续交付部署是要进行全面检查,以发现代码问题。检查的完整性是最重要的因素。通常以测试的代码覆盖率或功能覆盖率来衡量。尽早发现错误可以防止将损坏的代码部署到任何环境,并节省测试团队的宝贵时间。

精心设计CI和CD版本以实现这些目标并保持团队的生产力。没有工作流程是完美的。问题会时不时地出现。每次使用它们时,都可以将其作为学习的经验教训来加强您的工作流程。

发表于2019年11月27日在Fire CI博客上

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注