

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# CI/CD 流程的不同之处有多大
<a name="fully-cicd-process-differences"></a>

CI/CD 管道使用*基于主干的现代工作流程，在这种工作流程*中，开发人员将频繁的小更新合并到主分支（或主*干*）中，该分支或主干是通过管道的 CD 部分构建和测试的。 CI/CD 该工作流程取代了 *Gitflow 工作流程*，其中的开发和发布分支通过发布计划分开。在许多组织中，Gitflow 仍然是一种流行的版本控制和部署方法。但是，它现在被认为是遗留的，要集成到 CI/CD 管道中可能具有挑战性。

对于许多组织而言，从 Gitflow 工作流程到基于主干的工作流程的转换尚未完成，导致它们在迁移过程中停滞不前，从未完全迁移到 CI/CD。不知何故，它们的管线仍然保留旧版工作流程的某些残余，卡在过去与现在之间的过渡状态。查看 Git 工作流程中的差异，然后了解使用旧版工作流程对以下方面有何影响：
+ [环境完整性](environment-integrity.md)
+ [发行版](releases.md)
+ [安全性](security.md)

为了更轻松地识别现代配置中的旧版 Git 工作流程残余，让我们比较一下 [Gitflow](#gitflow-approach) 与[基于主干](#trunk-based-approach)的现代方法。

## Gitflow 方法
<a name="gitflow-approach"></a>

下图显示 Gitflow 工作流程。Gitflow 方法使用多个分支同时跟踪多个不同版本的代码。您可以计划在未来某个时间点发布应用程序更新，而开发人员仍对当前版本的代码继续开发。基于主干的存储库可以使用功能标志来实现此目的，但 Gitflow 默认内置此功能。



![\[包含功能、开发、发布和修补程序分支的 Gitflow 工作流程\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/strategy-cicd-litmus/images/gitflow-workflow.png)


Gitflow 方法的结果之一是应用程序环境通常不同步。在标准 Gitflow 实施中，开发环境反映了代码的当前状态，而预生产和生产环境则冻结在最新版本的代码库状态。

当生产环境中出现缺陷时，情况会变得复杂，因为如果不暴露未发布的功能，开发人员使用的代码库就无法合并到生产环境中。Gitflow 处理这种情况的方式是使用修补程序。从发布分支创建修补程序分支，然后直接部署到上层环境。修补程序分支随后合并到开发分支，以使代码保持最新。

## 基于主干的方法
<a name="trunk-based-approach"></a>

下图显示基于主干的工作流程。在基于主干的工作流程中，开发人员在功能分支中本地构建和测试功能，然后将这些更改合并到主分支中。然后，按顺序将主分支构建到开发、预生产和生产环境。每个环境之间都会进行单元测试和集成测试。



![\[基于主干的工作流程，包含功能分支和主分支。\]](http://docs.aws.amazon.com/zh_cn/prescriptive-guidance/latest/strategy-cicd-litmus/images/trunk-based-workflow.png)


使用此工作流程，所有环境都运行相同的代码库。上层环境不需要修补程序分支，因为您可以在主分支中实施更改，而无需暴露未发布的功能。始终假定主分支是稳定、没有缺陷且随时可以发布。这可以帮助您将其集成为 CI/CD 管道的来源，该管道可以在管道中的所有环境中自动测试和部署您的代码库。

# 基于主干的方法对环境完整性的优势
<a name="environment-integrity"></a>

正如许多开发人员所知道的那样，一次代码更改有时可能会产生[蝴蝶效应](https://www.americanscientist.org/article/understanding-the-butterfly-effect)（American Scientist 文章），即一个看似无关的微小偏差会引发连锁反应，导致意想不到的结果。开发人员随后必须进行全面调查以找出根本原因。

科学家进行实验时，会将受试者分为两组：实验组和对照组。目的是使实验组和对照组除了实验测试内容之外完全相同。如果实验组中出现了对照组中没有出现的情况，那么唯一的原因就是测试的内容。

将部署中的变更视为实验组，将每个环境视为独立的对照组。仅当下层环境的对照组与上层环境的对照组完全相同时，下层环境的测试结果才是可靠的。环境偏差越大，在上层环境中发现缺陷的可能性就越大。换句话说，如果代码变更将在生产环境中失败，我们宁愿其先在测试版中失败，这样它们就永远无法投入生产。这就是为什么应尽一切努力使每个环境（从最低测试环境到生产环境本身）保持同步的原因。这称为*环境完整性*。

任何完整 CI/CD 流程的目标都是尽早发现问题。使用基于主干的方法保留环境完整性，几乎可以消除对修补程序的需求。在基于主干的工作流程中，问题很少会首先出现在生产环境中。

在 Gitflow 方法中，将修补程序直接部署到上层环境后，再将其添加到开发分支中。这会保留该修复程序以备未来版本使用。但是，该修补程序是直接根据应用程序当前状态开发和测试的。即使该修补程序在生产环境中完美运行，当其与开发分支中的较新的功能交互时，也有可能出现问题。由于通常不希望为修补程序部署修补程序，因此这会导致开发人员花费额外的时间尝试使该修补程序重新适配开发环境。在许多情况下，这可能导致巨额技术债务，并降低开发环境的总体稳定性。

环境中发生故障时，所有更改都会回滚，以使环境恢复到其以前的状态。对代码库的任何更改都应从第一阶段重新启动管线。当生产环境中确实出现问题时，修复也应该通过整个管线进行。与使用此方法可避免的问题相比，经过下层环境所花的额外时间通常可以忽略不计。由于下层环境的全部目的是在错误进入生产环境之前将其捕获，因此通过 Gitflow 方法绕过这些环境是一种效率低下且不必要的风险。

# 基于主干方法的发布优势
<a name="releases"></a>

在旧版工作流程中，开发人员正在开发的应用程序状态可能包含多个尚未投入生产的未发布功能，而这往往是导致需要修补程序的原因之一。生产环境和开发环境仅当计划发布时才会同步，然后它们会立即再次开始出现差异，直到下一次计划发布。

在完整的 CI/CD 流程中可以安排发布时间。您可以使用功能标志来延迟将代码发布到生产环境中。但是，完整的 CI/CD 流程使计划发布变得不必要，从而提高了灵活性。毕竟，*持续*是 CI/CD 中的一个关键词，这表明变更准备就绪后就会发布。避免维护几乎总是与下层测试环境不同步的独立发布环境。

如果管线并非完全 CI/CD，则上层和下层环境之间的差异通常发生在分支级别。开发人员在开发分支中工作，并维护一个独立的发布分支，该分支仅在计划发布时才会更新。随着发布分支与开发分支出现差异，可能会引起其他复杂情况。

除了环境不同步之外，由于开发人员在开发分支上工作并习惯于远超生产环境的应用程序状态，因此每当生产环境出现问题时，他们都必须重新调整以适应生产状态。开发分支的状态可能有许多领先于生产环境的功能。当开发人员每天在该分支中工作时，很难记住哪些功能已经发布到生产环境，哪些功能尚未发布到生产环境。这增加了在修复其他错误的过程中引入新错误的风险。其结果是陷入看似无休止的修复循环，导致延长时间线，使功能发布延迟数周、数月甚至数年。

# 基于主干方法的安全优势
<a name="security"></a>

完整的 CI/CD 流程提供了一种完全自动化的单一事实来源部署方法。管线只有一个入口点。软件更新从一开始就进入管线，然后按原样从一个环境传递到另一个环境。如果在管线的任何阶段发现问题，则修复该问题的代码更改必须经过相同的流程并从第一阶段开始。减少管线的入口点同时减少了将漏洞引入管线的可能途径。

此外，由于入口点是距离生产环境最远的点，因此这显著降低了漏洞到达生产环境的可能性。如果您在完全 CI/CD 管线中实施手动批准流程，则仍可对更改是否升级到下一个环境作出允许执行或不执行的决策。决策者不一定是部署变更的同一个人。这将代码更改部署者与这些更改批准者的责任分开。这也使得技术水平较低的组织领导者更容易胜任批准者的角色。

最后，单一入口点可帮助您将对生产环境用户界面（UI）控制台的写入访问权限限制为少数用户甚至零用户。通过减少可在控制台中进行手动更改的用户数量，可以降低发生安全事件的风险。在传统工作流程中，在生产环境中手动管理控制台的能力比使用 CI/CD 自动化方法更为必要。这些手动更改更难跟踪、审查和测试。进行这些更改通常是为了节省时间，但从长远来看，其会给项目增加大量的技术债务。

控制台安全问题不一定是由恶意行为者造成的。控制台中出现的许多问题都是意外。意外安全漏洞非常普遍，而这导致了零信任安全模式的兴起。该模式的部分理念是，当即使内部员工也拥有尽可能少的访问权限（也称为*最低权限*）时，发生安全事故的可能性就会降低。通过将所有流程都限制在自动化管线内来保持生产环境的完整性，从而几乎消除与控制台相关的安全问题风险。