繁体   English   中英

如何使用 Azure DevOps Server 2019 中的 YAML 构建从多个发布分支配置 CI 构建?

[英]How to configure CI builds from multiple release branches using YAML builds in Azure DevOps Server 2019?

我们的产品中有多个发布分支(目前这是不可避免的)。 对于这个问题,假设我们有两个:

  1. 掌握
  2. 发布/r-858

两者都有经典的 CI 构建。 现在我想用 YAML 构建替换它们。 我们的要求很简单 - 有两个不同的构建定义指向 YAML 脚本 - 一个用于master ,一个用于release/r-858

一开始我以为这是一个微不足道的练习:

  1. master中创建 YAML 构建脚本。 将 CI 触发器设置为master
  2. Cherry-pick(不要介意为什么不合并)来release/r-858 - 将 CI 触发器设置为release/r-858

不理想,因为这两个脚本仅在 CI 触发器上有所不同。 但是“我正在学习,现在已经足够了”对我自己说。

但是,这个简单的方案行不通! 我为 release/r-858 创建的构建是在 master 更改时触发的!

我仔细检查了我所知道的关于构建的每一个设置——一切看起来都是正确的。

请注意:

主构建

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

发布/r-858 构建

在此处输入图像描述

哦,看那个。 它在主分支上显示 YAML,嗯? 也许这是一个无辜的演示错误:让我们检查一下我应该构建的分支:

在此处输入图像描述

是的,文件不同 - 我正在使用触发器尝试解决这个问题所涉及的相同问题。 原始代码使用release/r-858而不是$(Build.SourceBranch)作为 CI 触发器,但由于它没有帮助我开始使用各种触发器值。

为了消除任何疑问,这里是分支对应于 release/r-858 的证明:

C:\xyz\58 [arch/shelve/798914 ≡ +0 ~17 -0 !]> git lg -2
cfdb6a9a86a |  (HEAD -> arch/shelve/798914, origin/arch/shelve/798914) Rename azure-pipelines-ci-58.yml to azure-pipelines-ci.yml and sync it with the master version (68 seconds ago) [Kharitonov, Mark] (2020-08-14 09:09:46 -0400)
a931e3bd96b |  (origin/release/r-858, release/r-858) Merged PR 90230: 793282 Work Assignments Merge (28 minutes ago) [Mihailichenco, Serghei] (2020-08-14 12:02:20 -0400)
C:\xyz\58 [arch/shelve/798914 ≡ +0 ~17 -0 !]>

无论如何,更多的构建属性:

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

问题

因此,开发人员将一些代码推送到 master,现在 release/r-858 构建正在运行:

在此处输入图像描述

在此处输入图像描述

为什么是这样? 我们的一个人在Microsoft 开发人员社区论坛中提出了类似的问题,但该主题对我来说没有意义。

我在这里做错了什么?

编辑 1

想象一个大型企业单体应用程序。 它在 858 版中部署在生产环境中。同时,开发人员致力于下一个版本以及已在 prod 中部署的版本的热修复和服务包。

只能在 master 或 release/r-858 或两者中进行更改(但不能同时进行)。 许多团队同时在应用程序的许多不同方面工作,因此 QA 有许多部署应用程序的 pod。 正如我上面提到的 - 大约 150 个 pod 用于前沿(主)和大约相同数量的已发布代码,因为有积极的工作来测试热修复和服务包。

我很欣赏这种安排并不理想。 这不是因为我们喜欢它,而是因为一个人必须处理十年前的决定。 我们正在努力改变它,但这需要时间。

无论如何,当前的过程是有 2 个构建定义(实际上有更多不同的原因)。 到目前为止,我们使用的是经典的 CI 构建,现在我们想要迁移到 YAML(我们已经将其用于微服务,但不是单体)。

现在我明白了,我们可以基于相同的构建定义拥有不同的发布管道,但使用不同的分支过滤器。

也许我们会的。 但是我不明白为什么在这里有不同的构建定义是错误的,因为每个分支都是一个长期存在的发布分支。

编辑 2

您可以忽略$(Build.SourceBranch)和映像release/r-858 最终结果完全相同。 在我带来的场景中,上面的代码提交给 master,而不是 release/r-858。

编辑 3

这非常令人困惑。 假设我正在创建一个新的 YAML 构建。 该对话框显示“在任何分支中选择 YAML”,但他们指出,一旦选择此分支,该分支将成为构建的默认分支。 那就是我们可以在这里看到的分支:

在此处输入图像描述

如果我在 master 分支中有一个 YAML 文件,则默认分支release/r-858的构建甚至无法使用它,除非它合并到 release/r-858。 我试过了 - 我:

  1. 创建了一个新的 YAML 构建
  2. 从主分支中选择 YAML 文件
  3. 运行并立即取消构建
  4. 然后去编辑构建并将构建的分支从 master 更改为 release/r-858 - 它允许我保存构建,即使该分支中不存在 YAML

但是当我再次尝试运行构建时,我得到了这个:

在此处输入图像描述

An error occurred while loading the YAML build pipeline. File /Build/azure-pipelines-ci.yml not found in repository bla-bla-bla branch refs/heads/release/r-858 version 5893f559292e56cf6db48687fd910bd2916e3cef.

事实上,查看原始构建定义,进程部分包含 YAML 文件路径,但不包含分支:

    "process": {
        "yamlFilename": "Build/azure-pipelines-ci.yml",
        "type": 2,
        "resources": {},
        "target": null
    },

该分支仅出现在定义的存储库部分中:

    "repository": {
        "defaultBranch": "refs/heads/release/r-858",
        ...
    },

我很清楚,一个构建定义可用于 CI 构建多个分支。 但是我需要实现的这个 model 是每个发布分支的构建定义。 由于以下原因,我不能有一个单一的构建定义:

  1. 由于开发强度不同,不同的发布分支有不同的代理池。 请记住,这是在带有自托管代理的本地 Azure DevOps 服务器上。 我们可以用一个构建定义来表达这个要求吗?
  2. 我们想要控制的不同构建变量值,而不向 YAML 文件存储库发送拉取请求。 您如何使用单个构建定义来做到这一点? 例如,其中一个变量控制版本 Major.Minor。 它们在每个发布分支中都不同。

因此,在我们的情况下,我看不到任何避免多个构建定义的方法。 造成这种情况的根本原因是发布分支,但我们不能在不久的将来丢弃它们。

所以,我们有 2 个构建定义。 这迫使我们有 2 个 YAML - 每个分支一个,因为默认分支为 release/r-858 的构建定义希望在该分支中找到 YAML,否则我们无法手动触发构建。 这是必须的,即使构建有 CI 触发器。

因此,2 个构建定义,2 个 YAML(每个分支一个)。 到目前为止,我的手是被迫的。 但是现在我被告知发布分支构建将由主 YAML 触发,因为发布分支构建链接到相同的 YAML 文件名,忽略了构建的默认分支!

因为这是发生的事情 - 提交被签入到 master 并且除了 master 分支构建之外还调用了发布分支构建。 两个构建定义都使用主 YAML 脚本构建完全相同的分支(主)。 但是因为发布分支构建有不同的变量集,所以最终结果是完全错误的。

这是不合理的。 我将创建一个虚拟 repo 以干净地复制它并在此处发布。

编辑 4

正如所承诺的 - 一个微不足道的复制。 鉴于:

  1. master 分支构建 test-master-CI
  2. 发布分支构建测试-r58-CI

由于有两个构建定义必然意味着两个 YAML(每个分支一个),因此它们是:

C:\xyz\DevOps\Test [master ≡]> cat .\azure-pipelines.yml
trigger:
  branches:
    include:
      - master

name: $(BuildVersionPrefix).$(DayOfYear)$(Date:HH)

steps:
  - script: echo master
C:\xyz\DevOps\Test [master ≡]> git co release/r-858
Switched to branch 'release/r-858'
Your branch is up to date with 'origin/release/r-858'.
C:\xyz\DevOps\Test [release/r-858 ≡]> cat .\azure-pipelines.yml
trigger:
  branches:
    include:
      - release/r-858

name: $(BuildVersionPrefix).$(DayOfYear)$(Date:HH)

steps:
  - script: echo release/r-858
C:\Dayforce\DevOps\Test [release/r-858 ≡]>

其中BuildVersionPrefix = 59.0 为 master 和 58.3 为 release/r-858

当我手动触发每个构建时,我得到了这个:

在此处输入图像描述

现在我对 master 进行更改。 瞧 - 两个构建都被触发:

在此处输入图像描述

在这两种情况下,都使用来自 master 分支的 YAML。 但是发布分支定义了 BuildVersionPrefix = 58.3,因此发布分支构建定义执行的主构建具有虚假版本。

这真的是该功能应该如何工作的吗? 这使得 CI YAML 触发器对我的场景毫无用处。 感谢马特帮助我意识到这一点。

我想我明白了混乱的来源。 当您配置管道时,您正在指定分支(请注意,描述说明文件在任何分支中)和文件名。

在此处输入图像描述

您正在做的只是复制监控。 如果你真的要检查它,我想你会看到,当你推送到发布分支时,它不会触发主 YAML 管道......它只是第二次触发发布 YAML 步骤。 这是因为管道只是监视对 repo 的更改并根据 YAML 配置进行响应。 在这种情况下,您推送到发布,它评估有一个 YAML 与该触发器(发布分支的副本)匹配并为两个构建定义触发。

我在模拟管道上验证了这一点。 我在创建时选择了不同的分支,但我认为唯一真正影响的是它将用于计划构建的默认分支。 我在这两个中创建了一个简单的 echo 语句,它使用发布分支 YAML 配置。

在此处输入图像描述

我认为,如果您真的想达到您期望的结果,您将需要使用您在定义中定义的覆盖触发器,而不是依赖于 YAML 触发器中的内容。

在此处输入图像描述

我有同样的问题,马特帮我解决了这个问题。

我只是写这个,因为让这个工作对我有用的唯一方法是在一个分支上创建一个构建 YAML 文件(使用正确的配置)。 然后在另一个分支上创建另一个 YAML 文件。 然后在 Devops 中的新 shiny YAML 编辑器中创建管道。

The key is, when in the "Configure" section of a new pipeline, select: "Existing Azure Pipelines YAML file" which allows you to select a branch and a YAML file within that branch.

在此处输入图像描述

这使我能够让 SystemOne 分支构建和测试系统一站点,而 SystemTwo 分支构建和测试系统二站点。

我还使用通配符在 SystemOne.yml 中添加了触发器。 例如

trigger:
batch: true
branches: 
  include:
    - SystemOne/*

SystemTwo.yml 也是如此。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM