产品流水线¶
产品流水线 回答了一个更具挑战性的问题:我的“产品”是否能与新版本的软件包兼容?以及与它们依赖项的兼容性?这才是真正的“持续集成”部分,其中不同软件包中的更改会针对组织的重要产品进行实际测试,以检查事物是否能顺利集成或出现中断。
让我们继续上面的例子,如果我们现在有一个新的 ai/1.1.0 包,它会破坏现有的 game/1.0 和/或 mapviewer/1.0 应用程序吗?是否有必要从头重新构建一些直接或间接依赖于 ai 包的现有包?在本教程中,我们将 game/1.0 和 mapviewer/1.0 作为我们的“产品”,但这个概念将在稍后进一步解释,特别是为什么考虑“产品”而不是尝试显式地从顶层到底层建模 CI 中的依赖关系很重要。
在我们这个例子中,产品流水线 的本质是上传到 products 存储库的新 ai/1.1.0 版本会自动落入有效版本范围,我们的版本控制方法意味着这种次要版本增加将需要从头构建其使用者,在本例中是 engine/1.0 和 game/1.0,并且按此特定顺序,而所有其他包将保持不变。知道哪些包需要从头构建以及按照什么顺序构建,并执行该构建以检查主要的组织产品是否在新依赖版本下保持正常工作,这是产品流水线的职责。
什么是产品¶
产品 是一个组织(公司、团队、项目)作为最终结果交付并为这些工件的用户提供某种价值的主要软件工件。在本例中,我们将 game/1.0 和 mapviewer/1.0 视为“产品”。请注意,可以为同一包定义不同版本作为产品,例如,如果我们必须为不同的客户维护不同版本的 game,我们可以有 game/1.0 和 game/2.3,以及不同版本的 mapviewer 作为产品。
“产品”方法除了关注业务价值的优势外,还有另一个非常重要的优势:它避免了在 CI 层建模依赖关系图。这是一种常见的尝试,试图建模反向依赖模型,即在 CI 级别表示给定包的依赖项或使用者。在我们这个例子中,如果我们为构建 ai 包配置了一个作业,那么我们可能有一个用于 engine 包的另一个作业,该作业在 ai 作业之后触发,并在 CI 系统中以某种方式配置这种拓扑。
但这种方法根本无法扩展,并且有非常重要的限制
上面的例子相对简单,但实际上依赖关系图可能包含更多包,甚至数百个包,这使得在 CI 中定义包之间的所有依赖关系变得非常繁琐且容易出错。
依赖关系会随着时间的推移而演变,新版本会被使用,一些依赖关系会被删除,更老的依赖关系会被添加。在 CI 层面建模的存储库之间的简单关系可能导致非常低效、缓慢且耗时的 CI,甚至可能导致因某些依赖关系发生变化而持续中断的脆弱 CI。
在依赖关系图的下游发生的组合性质,其中一个相对稳定的顶层依赖项,例如
mathlib/1.0可能会被多个使用者使用,例如ai/1.0、ai/1.1、ai/1.2,而它们又可能被多个engine的不同版本使用,依此类推。仅构建消费者的最新版本在许多情况下是不够的,而构建所有版本则成本极高。“反向”依赖模型,即询问给定包的“依赖项”是什么,在实践中极具挑战性,尤其是在 Conan 这样的分散式方法中,包可以存储在不同的存储库中,包括不同的服务器,并且没有一个中央数据库存储所有包及其关系。此外,“反向”依赖模型与直接模型类似,也是条件性的。由于依赖关系可能依赖于任何配置(设置、选项),因此反向依赖也依赖于相同的逻辑,并且这种逻辑会随着每个新的修订版和版本而演变和变化。
在 C 和 C++ 项目中,“产品”流水线比其他语言更有必要和更关键,因为编译模型中的头文件文本包含成为使用者二进制工件的一部分,以及由于本机工件链接模型。
构建中间包的新二进制文件¶
一个常见的问题是,当消费者包构建针对新的依赖项版本时,其版本将是多少。以我们的例子明确来说,我们已经定义了需要重新构建 engine/1.0 包,因为它现在依赖于新的 ai/1.1.0 版本
我们应该创建一个新的
engine/1.1版本来构建新的ai/1.1.0吗?还是应该保留
engine/1.0版本?
答案在于 二进制模型以及依赖关系如何影响 package_id。Conan 有一个二进制模型,它同时考虑了依赖项的版本、修订版和 package_id,以及不同的包类型(package_type 属性)。
建议将包版本与源代码保持一致。如果 engine/1.0 是根据其源代码存储库的特定提交/标签构建的,并且该存储库的源代码根本没有更改,那么拥有一个与源版本不同的不断变化的包版本就会非常令人困惑。使用 Conan 二进制模型,我们将为 engine/1.0 获得 2 个不同的二进制文件,具有 2 个不同的 package_id。一个二进制文件将针对 ai/1.0 版本构建,另一个二进制文件将针对 ai/1.1.0 构建,类似于
$ conan list engine:* -r=develop
engine/1.0
revisions
fba6659c9dd04a4bbdc7a375f22143cb (2024-08-22 09:46:24 UTC)
packages
2c5842e5aa3ed21b74ed7d8a0a637eb89068916e
info
settings
...
requires
ai/1.0.Z
graphics/1.0.Z
mathlib/1.0.Z
de738ff5d09f0359b81da17c58256c619814a765
info
settings
...
requires
ai/1.1.Z
graphics/1.0.Z
mathlib/1.0.Z
让我们看看产品流水线如何使用新的依赖项版本来构建 engine/1.0 和 game/1.0 的新二进制文件。在接下来的部分中,我们将以增量的方式呈现产品流水线,就像包流水线一样。