【问题标题】:Howto: Dynamic variable name resolution in Azure DevOps YAML操作方法:Azure DevOps YAML 中的动态变量名称解析
【发布时间】:2020-03-17 20:10:51
【问题描述】:

变量支持的一致性和语法在 Azure DevOps YAML 中差异很大。 举个例子:

trigger:
- master

# Variable Group has $(testCategory1) with value
# 'TestCategory=bvttestonly | TestCategory=logintest'
variables:
  - group: DYNAMIC_VG

jobs:
  - job:
    pool: 'MyPool' #Has about 10+ self hosted agents

    strategy:
      parallel: $[ variables['noOfVMsDynamic']]

    variables:
      indyx: '$(testCategories$(System.JobPositionInPhase))'
      indyx2: $[ variables['indyx'] ] 
      testCategories: $[ variables[ 'indyx2' ] ]

    steps:
    - script: |
        echo "indyx2 - $(indyx2)"
        echo "testCategories $(testCategories)"
      displayName: 'Display Test Categories'

步骤打印:

"indyx2 - $(testCategories1)"
"testCategories $(testCategories1)"

我需要打印变量组中定义的 $(testCategories1) 的值:

'TestCategory=bvttestonly | TestCategory=logintest'

【问题讨论】:

  • 你试过indyx: $[ variables[format('{0}{1}', 'testCategories', variables['System.JobPositionInPhase'])] ] 吗?现在无法真正测试这个,所以作为评论发布,您可能需要将 . 更改为其他内容
  • @Luizgrs:我会尝试并告诉你。
  • 解决方法:使用动态矩阵策略和在运行时创建的 JSON。参考stackoverflow.com/questions/59076036/…

标签: azure azure-devops azure-devops-yaml


【解决方案1】:

操作方法:在 Azure DevOps YAML 中动态解析嵌套变量

这是因为目前构建管道尚不支持嵌套变量的值(如 $(testCategories$(System.JobPositionInPhase)))。

这就是为什么你总是得到值$(testCategories1)而不是变量testCategories1的实际值。

我在past posts 中多次遇到此问题,在 Azure Devops 支持此功能之前,我们没有完美的解决方案。

为了方便测试,我将您的 yaml 简化如下:

jobs:
  - job: ExecCRJob
    timeoutInMinutes: 800

    pool:
      name: MyPrivateAgent

    displayName: 'Execute CR'


    variables:
      testCategories1: 123456
      testCategoriesSubscripted: $(testCategories$(System.JobPositionInPhase))

    strategy:
      parallel: $[variables['noOfVMs']]     
    steps:
    - template: execute-cr.yml
      parameters:
        testCategories: $(testCategoriesSubscripted)

execute-cr.yml

steps:
    - script: echo ${{ parameters.testCategories }}

我们总是得到$(testCategories1)而不是它的价值。

如果我将$(testCategories$(System.JobPositionInPhase)) 更改为$(testCategories1),一切正常。

由于尚不支持嵌套变量,作为解决方法,我们需要为testCategories 的每个值扩展嵌套变量,例如:

- job: B
  condition: and(succeeded(), eq(dependencies.A.outputs['printvar.skipsubsequent'], 'Value1'))
  dependsOn: A
  steps:
  - script: echo hello from B

查看Expressions Dependencies 了解更多详情。

希望这会有所帮助。

【讨论】:

  • 感谢 Leo 确认嵌套变量不起作用。我了解依赖对象是如何工作的。现在,最难的部分是:我如何用另一种方法模拟这个?为使用并行或矩阵策略的并行作业动态提供值?我只会通过“noOfVMs”管道变量知道我在运行时需要多少代理。
  • @VyasBharghava,嗯,是的,你是对的。尽管我们可以将您的任务拆分为具有依赖关系的单独作业以解析嵌套变量,但我们无法在其中一项作业中获得 $(System.JobPositionInPhase) 的值。这是一个很大的挑战,我会尝试检查是否有其他方法可以解决这个问题。
  • 谢谢!!!在过去的几天里,我做了很多工作,看看什么是有效的。因此,无论变量在哪里(跨作业、本地甚至在 VG 中),变量都不会解析。我认为这个问题只是并行的。没有这个,我无法将并行用于任何有用的东西。我想分发用户提供的测试类别并同时测试或将不同池中的所有活动代理恢复到以前的快照(重新启动时将安装和测试 Windows 胖客户端)等。
  • @VyasBharghava,确实,这个问题似乎陷入了无限循环。如果我们想解析嵌套变量,我们需要将任务拆分为单独的作业。但是,在这种情况下,$(System.JobPositionInPhase) 变量将无效。
  • 我使用矩阵策略来解决问题,在该策略中我对所有变量引用进行硬编码(比如说,我预计最大的是 20 个并行作业),矩阵中的每个作业都直接引用变量:$(testCategory1)...to $(testCategory20)。我计划在一个 shell 脚本任务中测试这个值,如果值为空则让它跳过。随后的任务被跳过并且工作结束。但是,这意味着无论是否只需要 2 个作业,都将安排多达 20 个作业(意味着 testCategory3 以后为空白)。请产品团队为此提供官方解决方法吗?
【解决方案2】:

这可能对你有用:

variables
   indyx: $[ variables[format('{0}{1}', 'testCategories', variables['System.JobPositionInPhase'])] ]

它对我有用,在稍微不同的情况下也需要一些动态变量名。

【讨论】:

    【解决方案3】:

    如果我正确理解了您的问题,那么问题在于管道会在作业运行时评估所有变量。这种情况下的解决方案是将您的任务拆分为具有依赖关系的单独作业。

    看看我在这篇文章中的回答,如果你想要的话,请告诉我:YAML pipeline - Set variable and use in expression for template

    【讨论】:

    • 我只需要运行时评估。并行策略会自动将下面提到的步骤分成单独的作业。我确实已经在工作之间建立了依赖关系。我能够在 ExecCRJob 中访问 ExecPrerequisiteJob 的输出变量就好了。唯一的问题是下标访问。
    猜你喜欢
    • 2020-05-26
    • 2019-10-27
    • 2021-02-03
    • 2020-12-30
    • 2021-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多