持续集成 (CI) 教程

注意

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

在本教程中,我们将使用这个使用多个包(默认情况下为静态库)来构建几个应用程序的小项目,一个视频游戏和一个地图查看器实用程序。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

  • 然而,一些原则和最佳实践对于所有方法都是通用的。例如,包的不可变性、在仓库之间使用提升(promotions)以及不使用 `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:此仓库将用于临时上传由“产品流水线”构建的包,同时构建和测试新的依赖项更改是否会破坏主要的“产品”。

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" ]; } }

提升(Promotions)是将包从一个流水线提供给另一个流水线的机制。将上述包和产品流水线与仓库连接起来,将会有 2 次提升。

  • 当 `packages pipeline` 为单个包构建了不同配置的所有不同二进制文件,并将它们上传到 `packages` 仓库后,包的新版本和更改就可以被视为“正确”并提升(复制)到 `products` 仓库。

  • 当 `products pipeline` 从源代码构建了所有必需的包,因为 `products` 仓库中的新包版本需要重新构建,并且已经检查过组织的“产品”(例如 `game/1.0` 和 `mapviewer/1.0`)没有被破坏时,这些包就可以从 `products` 仓库提升(复制)到 `develop` 仓库,以便它们可供所有其他开发人员和 CI 使用。

注意

本教程仅模拟开发流程。在生产系统中,将有其他仓库和提升,例如为 QA 团队准备的 `testing` 仓库,以及为最终用户准备的最终 `release` 仓库,这样包在通过验证时可以从 `develop` 提升到 `testing`,再到 `release`。在 包提升 中阅读更多关于提升的内容。

让我们开始教程,进入下一节进行项目设置。