【问题标题】:Construct a condition in Azure DevOps using 'each'使用“每个”在 Azure DevOps 中构造条件
【发布时间】:2021-01-02 08:36:07
【问题描述】:

在 Azure DevOps(YAML 管道)中,我们有一个阶段,只有在另一组阶段被跳过后才应该运行。

在下面的示例中,参数copyStages_UAT可以在触发手动运行时由用户修改,这意味着不可能硬编码dependsOncondition属性,因此需要使用指令@987654324 @。

- template: ../Stages/stage--code--depoly-to-environment.yml
  parameters:
    name: Deploy_PRD_UKS
    displayName: Deploy PRD - UK South
    dependsOn:
    - ${{ each uatStage in parameters.copyStages_UAT }}:
      - Roll_Back_${{ uatStage.name }}
    variables:
    - template: ../Variables/variables--code--global.yml
    - template: ../Variables/variables--code--prd.yml
    environment: PRD

上面的这个阶段在管道中工作,但是因为成功运行会导致在dependsOn 中定义的阶段被跳过,遗憾的是,Azure DevOps 也会跳过这个阶段。

为了解决这个问题,我尝试添加condition 来检查之前的阶段是否都被跳过了。

condition: >-
  and(replace(
    ${{ each uatStage in parameters.copyStages_UAT }}:
      eq(dependencies.Roll_Back_${{ uatStage.name }}.result, 'Skipped'), 
  ), ', )', ' )')

不幸的是,我似乎无法在这种情况下使用指令each -

在此上下文中不允许使用指令“每个”。嵌入在字符串中的表达式不支持指令。仅当整个值是表达式时才支持指令。

由于condition 只能是字符串,我如何利用表达式和/或指令来构造我想要的条件?

所需 YAML 示例

假设为参数copyStages_UAT 给出了以下值-

- name: UAT_UKS
  displayName: UAT - UK South
- name: UAT_UKW
  displayName: UAT - UK West

这就是 YAML 的编译方式。我不担心条件的格式,只要包括相关检查即可。

- template: ../Stages/stage--code--depoly-to-environment.yml
  parameters:
    name: Deploy_PRD_UKS
    displayName: Deploy PRD - UK South
    dependsOn:
    - Roll_Back_UAT_UKS
    - Roll_Back_UAT_UKW
    condition: >-
      and(
        eq(dependencies.Roll_Back_UAT_UKS.result, 'Skipped'),
        eq(dependencies.Roll_Back_UAT_UKW.result, 'Skipped')
      )
    variables:
    - template: ../Variables/variables--code--global.yml
    - template: ../Variables/variables--code--prd.yml
    environment: PRD

【问题讨论】:

    标签: azure-devops yaml azure-pipelines


    【解决方案1】:

    更新:

    为了总结您的需求,您正在寻找一个可以在 condition 中使用它的表达式,而 dependsOn 值是动态的。并且这个阶段应该只在另一组依赖阶段都被跳过后运行。

    据我所知和测试,这不能通过 each 来实现。

    为了进一步确认,我与我们的管道 PM 讨论了这个场景,他更熟悉 每个 和 YAML 管道。

    和我一样,他也认为这是不可能实现的。因为${{ each }} 期望成为映射键或值的最外层部分,所以您不能将其嵌套到条件字符串中。


    解决方法:

    您可以通过硬编码阶段来伪造它,该阶段取决于动态列表,确定它们是否都被跳过并设置输出变量。那么真正的最终工作将仅取决于那个“决策者”工作,其条件将取决于输出变量的内容。

    找出所有上游依赖项都被跳过对你来说是一个练习。您可能能够在每个阶段动态构建一个步骤。这些步骤将阶段的状态映射到具有已知名称方案的变量。然后最后(硬编码)步骤迭代已知名称方案的环境变量,并决定是否应该进行下一阶段。

    而且...是的,我知道这听起来有多难看

    【讨论】:

    • 感谢您的回复。在这种情况下,如果它所依赖的阶段已被跳过,我只想运行一个阶段。因此,使用上面的示例,两个图像都是正确的。但是,我不能使用always(),因为这意味着DeployEurope 阶段将始终运行,即使avaiableazuremerlinazure 已经运行,并且如前所述,它应该只在它依赖的阶段运行被跳过。我已经更新了我的问题(希望)让它更清楚。
    • @DavidGard,感谢您的详细解释。知道了。这对我来说很清楚。一旦我在这里更新,会分享你的建议。
    • @DavidGard,据我所知,这不可能在条件下直接使用每个。为了避免误导您,我与我们最熟悉each功能的项目经理讨论了这一点,以进一步确认。同样的结果,我们现在都认为,你需要通过使用变通来实现。请参阅我的更新答案。
    • 感谢您的确认。这并不理想,我不确定解决方法是否可行。据我所知,您只能在作业中的任务之间或阶段中的作业之间共享输出变量(使用isOutput=true) - 实际上documentation 明确表示“多作业输出变量仅适用于作业在同一阶段。”
    • @DavidGard 啊,我们在 sprint 168 中发布了一个新功能,让用户可以跨阶段访问输出变量。请参阅此功能时间线文档:docs.microsoft.com/en-us/azure/devops/release-notes/2020/…
    猜你喜欢
    • 2023-02-11
    • 1970-01-01
    • 2020-08-26
    • 2019-07-19
    • 1970-01-01
    • 1970-01-01
    • 2020-11-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多