产品流水线

产品流水线 回答了一个更具挑战性的问题:我的“产品”是否能够与新版本的软件包兼容?能否与软件包及其依赖项兼容?这才是真正的“持续集成”部分,其中不同软件包中的更改会与组织的重要产品进行实际测试,以检查集成是否顺畅或出现中断。

让我们继续上面的例子,如果我们现在有一个新的 ai/1.1.0 包,它是否会破坏现有的 game/1.0 和/或 mapviewer/1.0 应用程序?是否有必要从头重新构建一些直接或间接依赖于 ai 包的现有软件包?在本教程中,我们将 game/1.0mapviewer/1.0 作为我们的“产品”,但这个概念将在稍后进一步解释,特别是为什么从“产品”的角度思考比尝试显式地自顶向下地在 CI 中建模依赖项更重要。

在我们这个例子中,产品流水线 的本质是上传到 products 仓库的新 ai/1.1.0 版本会自动落入有效的版本范围,我们的版本控制方法意味着这种次要版本增加将需要从头构建其消费者,在本例中是 engine/1.0game/1.0,并且是按照那个特定的顺序构建,而所有其他软件包将保持不变。了解哪些软件包需要从头构建以及构建顺序,并执行该构建以检查主要组织产品是否与新依赖项版本保持正常工作,这是产品流水线的责任。

什么是产品

产品 是一个组织(公司、团队、项目)作为最终结果交付并为用户提供某些价值的主要软件工件。在本例中,我们将 game/1.0mapviewer/1.0 视为“产品”。请注意,可以将同一软件包的不同版本定义为产品,例如,如果我们必须为不同客户维护不同版本的 game,我们也可以将 game/1.0game/2.3 以及不同版本的 mapviewer 作为产品。

“产品”方法除了专注于业务价值的优势外,还有一个非常重要的优势:它避免了在 CI 层面上建模依赖关系图。试图建模反向依赖关系(即,在 CI 级别表示给定软件包的依赖项或使用者)是一种常见的尝试。在我们的例子中,如果我们为构建 ai 包配置了一个作业,我们可以为 engine 包配置另一个作业,该作业在 ai 包之后触发,并通过某种方式在 CI 系统中配置这种拓扑。

但这种方法完全无法扩展,并且有非常重要的局限性

  • 上面的例子相对简单,但在实践中,依赖关系图可能包含更多的软件包,甚至数百个,使得在 CI 中定义所有软件包之间的依赖关系变得非常繁琐且容易出错。

  • 依赖项会随着时间而演变,会使用新版本,一些依赖项会被删除,一些新的依赖项会被添加。在 CI 级别建模的存储库之间的简单关系可能导致 CI 非常低效、缓慢且耗时,如果不是脆弱的话,它会因为某些依赖项的更改而不断中断。

  • 发生在依赖关系图下游的组合性质,一个相对稳定的顶级依赖项,例如 mathlib/1.0,可能被多个使用者使用,例如 ai/1.0ai/1.1ai/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.0game/1.0 的新二进制文件。在接下来的部分中,我们将以增量的方式呈现产品流水线,就像软件包流水线一样。