持续集成 (CI) 教程¶
注意
这是一个高级主题,需要先了解 Conan。请先阅读并练习用户教程。
本节面向设计和实施涉及 Conan 包的 CI 流水线的 DevOps 和构建工程师。如果不是这种情况,您可以跳过本节。
持续集成对于不同的用户和组织具有不同的含义。在本教程中,我们将涵盖以下场景:当用户更改其包的源代码时,他们希望自动为这些包构建新的二进制文件,并计算这些新的包更改是否能干净地集成或破坏组织的主要产品。
在本教程中,我们将使用这个小型项目,它使用多个包(默认是静态库)来构建几个应用程序,一个视频游戏和一个地图查看器工具。game
和 mapviewer
是我们的最终“产品”,即我们分发给用户的产品。
依赖图中的所有包都使用版本范围对其直接依赖项进行 requires
,例如,game
包含 requires("engine/[>=1.0 <2]")
,因此依赖项的新补丁版本和次要版本将自动使用,而无需修改配方。
注意
重要说明
本节以实践教程的形式编写。旨在通过复制您机器上的命令来重现。
本教程介绍了一些工具、最佳实践和 CI 问题的常见方法。但没有万能药。本教程并非唯一正确的方法。不同的组织可能有不同的需求和优先事项、不同的构建服务能力和预算、不同的规模等。本教程中介绍的原则和实践可能需要进行调整。
如果您有任何问题或反馈,请在https://github.com/conan-io/conan/issues 提交新问题
然而,一些原则和最佳实践对于所有方法都是通用的。例如,包的不可变性,在存储库之间使用晋升,以及不为此目的使用
channel
都是应该遵循的良好实践。
包和产品流水线¶
当开发人员更改包源代码时,我们将考虑整个系统 CI 的两个不同部分或流水线:包流水线和产品流水线。
包流水线负责在代码更改时构建单个包。如果需要,它将为不同的配置构建它。
产品流水线负责构建组织的主要“产品”(实现最终应用程序或可交付成果的包),并确保依赖项中的更改和新版本正确集成,如果需要,重新构建图中的任何中间包。
这个想法是,如果某个开发人员对 ai
包进行更改,生成新版本 ai/1.1.0
,那么包流水线将首先构建这个新版本。但这个新版本可能会意外地破坏或需要重新构建一些使用者包。如果我们的组织主要产品是 game/1.0
和 mapviewer/1.0
,那么产品流水线可以被触发,在这种情况下,它将重新构建 engine/1.0
和 game/1.0
,因为它们受到更改的影响。
存储库和晋升¶
多个服务器端存储库的概念对于 CI 非常重要。在本教程中,我们将使用 3 个存储库。
develop
:这个存储库是开发人员在他们的机器上配置的主要存储库,用于conan install
依赖项并进行工作。因此,它预计会非常稳定,类似于 git 中的共享“develop”分支,并且存储库应该包含组织预定义平台的预编译二进制文件,以便开发人员和 CI 不需要--build=missing
并一次又一次地从源代码构建。packages
:这个存储库将用于临时上传由“包流水线”构建的包,而不是直接上传到develop
存储库,以避免在这些包完全验证之前造成中断。products
:这个存储库将用于临时上传由“产品流水线”构建的包,同时构建和测试新的依赖项更改不会破坏主要的“产品”。
晋升是用于将包从一个流水线提供给另一个流水线的机制。将上述包和产品流水线与存储库连接起来,将有 2 次晋升:
当使用
packages pipeline
为单个包的不同配置构建了所有不同的二进制文件,并上传到packages
存储库时,新版本和对包的更改可以被认为是“正确”的,并晋升(复制)到products
存储库。当
products pipeline
由于products
存储库中的新包版本而从源代码构建了所有需要重新构建的必要包,并检查了组织的“产品”(例如game/1.0
和mapviewer/1.0
)未损坏时,这些包可以从products
存储库晋升(复制)到develop
存储库,以供所有其他开发人员和 CI 使用。
注意
不可变性的概念在包管理和 DevOps 中非常重要。强烈不鼓励修改
channel
,请参阅包晋升。版本控制方法很重要。本教程将遵循默认的 Conan 版本控制方法,详情请参见此处。
本教程仅模拟开发流程。在生产系统中,将有其他存储库和晋升,例如供 QA 团队使用的 testing
存储库,以及供最终用户使用的最终 release
存储库,以便包在通过验证后可以从 develop
晋升到 testing
再到 release
。有关晋升的更多信息,请参阅包晋升。
让我们开始本教程,转到下一节进行项目设置。