Azure DevOps - 分支策略在拉取请求期间导致多个构建 运行

Azure DevOps - Branch Policies are resulting in multiple builds running during Pull Requests

我们的仓库是有文件夹的,文件夹里的代码有时会依赖其他文件夹里的代码,但只有一个方向。解释方式:

C依赖B

B 依赖于 A

我们的 Pull Request 策略需要 3 个构建:

我们有一个只构建文件夹 C 的构建 (BuildC)

我们有一个构建 B 和 C 的构建 (BuildB)

我们有一个构建 A、B 和 C 的构建 (BuildA)

政策规定:

文件夹 C 中的更改需要 BuildC

文件夹 B 中的更改需要 BuildB

文件夹 A 中的更改需要 BuildA

想要的效果: 根据具体情况,我希望 Pull Request 只需要三个构建中的一个。以下是案例:

BuildA - 应该 运行 当文件夹 A 有变化时(即使其他地方有变化)

BuildB - 当 B(and/or C)中有变化但 A 中没有变化时应该 运行。如果文件夹 A 中有变化,这个构建不应该 运行

BuildC - 应该 运行 当唯一的变化在文件夹 C 中时...如果文件夹 A and/or 除了 C 之外还有 B 中存在变化...这个构建不应该 运行.

实际发生的情况是,如果您更改文件夹 A 和 C 中的内容,两个构建 运行:BuildA 和 BuildC...如果文件夹 C 中的更改依赖于文件夹 A,则 BuildC 构建失败.无论如何,buildC的运行是一种浪费。

有没有办法让 Azure DevOps 仅排队 1 个构建...但最好的一个。因此,在我们的示例中,BuildA 将 运行 而不是 BuildC...但是如果更改仅在文件夹 C 中,它将 运行 Build C?

无法使用构建触发器或策略来完成您想要的。没有“文件夹 X 中有更改时不要构建”。虽然有一些选择,但它们需要重新考虑一下:

选项 1:使用职位和条件

  • 创建一个具有构建阶段和 4 个作业的管道。
  • 第一个作业使用命令行工具检测哪些项目需要重建并设置输出变量
  • 其他 3 个作业依赖于第一个作业,并设置了一个条件,仅在变量(在第一个作业中设置)具有特定值时触发。

这样您就可以完全控制所有 3 个项目的构建顺序。

选项 2:使用编排管道

选项 3:使用管道工件

不是在构建 C 中构建 A+B+C,而是从 A+B 下载结果,然后构建 C。这将需要在每个作业结束时上传管道工件,并为每个后续作业做增量通过下载这些工件来构建,从而跳过构建过程。

如果您想跳过构建代码,您甚至可以下载“最后一次成功”的结果。

选项 4:使用 NuGet

使用 nuget 包发布构建 A 的输出并在构建 B 中使用它们,而不是管道工件。甚至,在作业 A 中发布 A 并在相同的构建定义中从作业 B 使用它。

选项 5:依赖增量构建

If you're running on a self-hosted agent, you can turn off the "Clean" option for your pipeline, in care the same agent has built your build before, if will simply re-use the build output of the previous run, in case none of the input files have changed (and you haven't made any incorrect msbuild customizations). It will essentially skip building A if msbuild can calculate it won't need to build A.


具有多个作业的单个构建的优点是您可以指定作业 A、B、C 的顺序,并且可以控制每个作业中发生的事情。最大的缺点是每个作业都会增加获取源代码或下载工件的开销。您可以通过为要发布和恢复的片段明确设置通配符来稍微优化一下。

如果您在后续阶段不需要源(并且不使用 YAML 管道),您可以使用我的 Don't Sync Sources 任务(即使使用 Git)来跳过同步步骤,让您能够准确控制每项工作中发生的事情。

其中许多选项都依赖于您确定自上次成功构建以来哪些项目包含更改的文件。您可以使用 git 或 tfvc 命令行实用程序来告诉您更改了哪些文件,但是当您打开构建批处理时,创建完美的脚本可能会有点困难,在这种情况下,多个更改将立即触发您的构建,所以你不能只依赖“最新的变化”。在这种情况下,您可能需要确保 REST API 询问 Azure DevOps al commitIds 或与此构建关联的所有变更集编号,以执行适当的差异来计算哪些项目包含变更。

从长远来看,依赖具有多个作业或 nuget 包的单个构建可能会更容易维护。