如何在Azure DevOps YAML中动态解析变量名

3
变量支持的一致性和语法在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)的值: < p > < code > 'TestCategory=bvttestonly | TestCategory=logintest'


3
你尝试过 indyx: $[ variables[format('{0}{1}', 'testCategories', variables['System.JobPositionInPhase'])] ] 吗?我现在无法真正测试它,所以将其发布为评论,你可能需要将那个 . 更改为其他内容。 - Luizgrs
@Luizgrs:我会尝试并告诉你。 - Vyas Bharghava
解决方法:使用在运行时创建的JSON动态矩阵策略。请参考https://stackoverflow.com/questions/59076036/generate-job-matrix-from-all-possible-combinations-of-input-parameters/62649918#62649918。 - Vyas Bharghava
4个回答

6
这可能对你有用:
variables
   indyx: $[ variables[format('{0}{1}', 'testCategories', variables['System.JobPositionInPhase'])] ]

对我来说起作用了,在稍微不同的情况下也需要一些动态变量名。


2
如何在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)而不是它的值。
如果我将$(System.JobPositionInPhase)替换为1,则一切正常。
由于嵌套变量目前还不支持,因此我们需要为每个testCategories的值展开嵌套变量作为解决方法。
- job: B
  condition: and(succeeded(), eq(dependencies.A.outputs['printvar.skipsubsequent'], 'Value1'))
  dependsOn: A
  steps:
  - script: echo hello from B

请查看表达式依赖以了解更多详情。
希望这可以帮助到您。

1
感谢Leo确认嵌套变量无法使用。我理解依赖对象的工作原理。现在,难点来了:如何用另一种方法模拟它?动态地为使用并行或矩阵策略的并行作业提供值?我只能通过“noOfVMs”管道变量在运行时知道需要多少代理。 - Vyas Bharghava
@VyasBharghava,嗯,是的,你说得对。虽然我们可以将您的任务拆分为具有依赖关系的单独作业以解决嵌套变量,但我们无法在其中一个作业中获取$(System.JobPositionInPhase)的值。这是一个很大的挑战,我会尝试检查是否有其他方法来解决这个问题。 - Leo Liu
谢谢!!!我在过去的几天里做了很多工作来看看哪些是有效的。所以,变量在哪里(跨作业、本地甚至在VG中)都无关紧要,变量都不会解析。我认为这个问题只存在于并行中。如果没有这个,我就不能用并行来做任何有用的事情。我想分发用户提供的测试类别和并发测试,或者将不同池中的所有活动代理还原到以前的快照(重新启动后将安装和测试Windows厚客户端)等。 - Vyas Bharghava
@VyasBharghava,确实,这个问题似乎陷入了无限循环。如果我们想要解决嵌套变量的问题,我们需要将任务拆分为单独的作业。但是,在这种情况下,$(System.JobPositionInPhase)变量将无效。 - Leo Liu
我使用矩阵策略进行解决,其中我硬编码所有变量引用(例如,我期望的最大值为20个并行作业),每个矩阵作业直接引用变量:$(testCategory1)...到$(testCategory20)。我计划在shell脚本任务中测试此值,并在该值为空时跳过它。后续任务将被跳过,作业结束。然而,这意味着最多会安排20个作业,无论是否只需要2个作业(也就是说,testCategory3及以后为空)。产品团队能否提供官方解决方法? - Vyas Bharghava
此外,我明白期望对变量解引用进行多次通行以到达一个值可能是不合理的:'$(var $(index))'。然而,在variables ['testCategory $ {System.JobPositionInPhase)']中使用变量名作为查找键字符串至少必须起作用。 - Vyas Bharghava

1

我通过使用get-item读取相应的环境变量来实现动态名称解析,从而构建变量的名称并获取其值。

在我们的情况下,我们将自动生成的分支名称保存到变量组中,并且每个存储库都有自己的变量。

$branchVarName = "$(Build.Repository.Name).BranchName".replace(".","_")
$branchName = (get-item -Path Env:$branchVarName).value
write-host "/$(System.TeamProject)/_apis/build/builds?&repositoryId=$(Build.Repository.ID)&repositoryType=TFSGit&branchName=refs/heads/$branchName&api-version=6.0"

在第二行中请注意,我使用.value引用变量content,因为get-item返回名称/值键对。
这个提取必须在脚本中完成,但如果需要在另一个上下文中使用,它可以作为输出变量公开。

0
如果我正确理解了您的问题,那么问题在于管道在作业运行时评估所有变量。在这种情况下的解决方案是将任务拆分为具有依赖关系的单独作业。
请查看我在此帖子中的答案,并告诉我是否符合您的要求:YAML pipeline - Set variable and use in expression for template

我只需要运行时评估。并行策略会自动将下面提到的步骤切分成单独的作业。我已经设置好了作业之间的依赖关系。我可以很好地访问ExecPrerequisiteJob的输出变量,但唯一的问题是下标访问。 - Vyas Bharghava

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接