持续集成 (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。请在 软件包提升 中阅读有关提升的更多信息。

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