持续集成 (CI) 教程

注意

  • 这是一个高级主题,需要具备 Conan 的先验知识。 请先阅读并实践用户教程

  • 本节面向设计和实施涉及 Conan 软件包的 CI 流水线的 devops 和构建工程师。如果不是这种情况,您可以跳过本节。

对于不同的用户和组织,持续集成具有不同的含义。 在本教程中,我们将介绍用户对其软件包的源代码进行更改,并希望自动为这些软件包构建新的二进制文件,并计算这些新的软件包更改是否能顺利集成或破坏组织的主要产品的情况。

在本教程中,我们将使用这个小型项目,该项目使用多个软件包(默认情况下为静态库)来构建几个应用程序,一个视频游戏和一个地图查看器实用程序。 gamemapviewer 是我们的最终“产品”,我们将它们分发给我们的用户

digraph game { node [fillcolor="lightskyblue", style=filled, shape=box] rankdir="BT" "game/1.0" -> "engine/1.0" -> "ai/1.0" -> "mathlib/1.0"; "engine/1.0" -> "graphics/1.0" -> "mathlib/1.0"; "mapviewer/1.0" -> "graphics/1.0"; "game/1.0" [fillcolor="lightgreen"]; "mapviewer/1.0" [fillcolor="lightgreen"]; { rank = same; edge[ style=invis]; "game/1.0" -> "mapviewer/1.0" ; rankdir = LR; } }

依赖关系图中的所有软件包都使用版本范围 requires 其直接依赖项,例如,game 包含 requires("engine/[>=1.0 <2]"),因此将自动使用依赖项的新补丁和次要版本,而无需修改配方。

注意

重要提示

  • 本节编写为实践教程。 旨在通过复制机器中的命令来重现。

  • 本教程介绍了一些工具、良好实践和解决 CI 问题的常用方法。 但没有万能的解决方案。 本教程不是唯一应该做的事情。 不同的组织可能有不同的需求和优先级、不同的构建服务能力和预算、不同的规模等。 本教程中介绍的原则和实践可能需要调整。

  • 如果您有任何问题或反馈,请在 https://github.com/conan-io/conan/issues 中提交新问题

  • 但是,某些原则和最佳实践对于所有方法都是通用的。 诸如软件包不变性、使用存储库之间的升级而不是为此目的使用 channel 之类的事情都是应该遵循的良好实践。

软件包和产品流水线

当开发人员对软件包源代码进行一些更改时,我们将考虑整个系统 CI 的 2 个不同部分或流水线:软件包流水线产品流水线

  • 软件包流水线负责在单个软件包的代码更改时构建它。 如果需要,它将针对不同的配置构建它。

  • 产品流水线负责构建主要组织“产品”(实现最终应用程序或可交付成果的软件包),并确保依赖项中的更改和新版本正确集成,并在必要时重建图中的任何中间软件包。

这个想法是,如果某个开发人员对 ai 软件包进行了更改,从而生成了新的 ai/1.1.0 版本,则软件包流水线将首先构建这个新版本。 但是这个新版本可能会意外中断或需要重建一些使用者软件包。 如果我们组织的主要产品game/1.0mapviewer/1.0,则可以触发产品流水线,在这种情况下,它将重建 engine/1.0game/1.0,因为它们受到更改的影响。

存储库和升级

多个服务器端存储库的概念对于 CI 非常重要。 在本教程中,我们将使用 3 个存储库

  • develop:此存储库是开发人员在其机器中配置的主要存储库,以便能够 conan install 依赖项并进行工作。 因此,它有望非常稳定,类似于 git 中的共享“develop”分支,并且存储库应包含该组织预定义平台的预编译二进制文件,因此开发人员和 CI 不需要执行 --build=missing 并一次又一次地从源代码构建。

  • packages:此存储库将用于临时上传由“软件包流水线”构建的软件包,而不是直接将它们上传到 develop 存储库,并在这些软件包经过完全验证之前避免中断。

  • products:此存储库将用于临时上传由“产品流水线”构建的软件包,同时构建和测试新的依赖项更改不会破坏主要的“产品”。

digraph repositories { node [fillcolor="lightskyblue", style=filled, shape=box] rankdir="LR"; subgraph cluster_0 { style=filled; color=lightgrey; rankdir="LR"; label = "Packages server"; "packages\n repository" -> "products\n repository" -> "develop\n repository" [ label="promotion" ]; } }

升级是用于使软件包从一个流水线到另一个流水线可用的机制。 将上述软件包和产品流水线与存储库连接起来,将有 2 个升级

  • 当已使用 packages pipeline 为单个软件包构建了不同配置的所有不同二进制文件,并将其上传到 packages 存储库时,可以认为软件包的新版本和更改是“正确的”,并将其升级(复制)到 products 存储库。

  • products pipeline 从源代码构建了因 products 存储库中的新软件包版本而需要重建的所有必要软件包,并且已检查组织“产品”(例如 game/1.0mapviewer/1.0)未损坏时,则可以将软件包从 products 存储库升级(复制)到 develop 存储库,以使它们可供所有其他开发人员和 CI 使用。

注意

本教程仅对开发流程进行建模。 在生产系统中,将有其他存储库和升级,例如 QA 团队的 testing 存储库和最终用户的最终 release 存储库,这样软件包就可以从 develop 升级到 testing,然后再升级到 release,因为它们通过了验证。 在 软件包升级 中阅读有关升级的更多信息。

让我们从本教程开始,转到下一节进行项目设置