Azure DevOps Yaml管道:阶段条件变量语法

3
我正在处理一个Azure DevOps多阶段YAML管道。我在第一阶段设置了一个变量,然后在下一个阶段中,我有一个基于该变量的条件。我还在下一个阶段中检索变量值。显然,在条件和阶段级别上访问阶间变量的语法存在细微差别。我无法弄清楚我需要在条件中使用的语法。我已经尝试了所有可能的变化,但似乎都不起作用。在下面的示例中,我期望lint阶段运行,但它被跳过了。这里的条件应该是确切的语法是什么?
stages:
- stage: build
  displayName: build
  pool:
    name: Azure Pipelines
    vmImage: ubuntu-latest
  dependsOn: []
  jobs:
  - deployment: build_job
    environment:
      name: "test"
    strategy:
      runOnce:
        deploy:
          steps:
          - task: PowerShell@2
            displayName: "get commitMessage variable"
            name: getCommitMessage
            inputs:
              targetType: inline
              pwsh: true
              script: |
                $commitMessage = "abcd_import/"
                echo "setting commitMessage: $commitMessage"
                echo "##vso[task.setvariable variable=commitMessage;isOutput=true]$commitMessage"

- stage: lint
  displayName: lint
  dependsOn:
  - 'build'
  condition: contains(stageDependencies.build.build_job.outputs['build_job.getCommitMessage.commitMessage'], 'import/')
  pool:
    name: Azure Pipelines
    vmImage: ubuntu-latest
  variables:
  - name: BUILD_STAGE_GET_COMMIT_MESSAGE
    value: $[stageDependencies.build.build_job.outputs['build_job.getCommitMessage.commitMessage']]
  jobs:
  - deployment: validate
    environment:
      name: "test"
    strategy:
      runOnce:
        deploy:
          steps:
          - task: PowerShell@2
            displayName: "commitMessage is empty"
            name: fail
            inputs:
              targetType: inline
              pwsh: true
              script: "echo $(BUILD_STAGE_GET_COMMIT_MESSAGE)"

更新(答案):我在此事上提出了一个微软支持案例,并得到了解决方案。正确的语法是

condition: contains(dependencies.build.outputs['build_job.build_job.getCommitMessage.commitMessage'], 'import/')

关于这个奇怪的问题,有几点需要注意:
  • 使用阶段变量的语法在使用它作为条件和将其传递为另一个变量时是不同的。
  • 如果源阶段是作业,则语法与源阶段是部署作业时不同。
  • 最重要的是,我无法在 MS 文档中找到正确的语法。
  • 我找不到任何方法来诊断问题,例如:在构建日志中查看阶段输出 JSON 将非常有帮助。
  • 最后,我认为 Azure DevOps 团队真的搞砸了这个功能。语法应该在作业/部署作业、条件和变量分配之间保持一致。在当前状态下真的很痛苦。
4个回答

5

在一个阶段中,要引用另一个阶段的输出变量,您应使用以下表达式格式:

  • 在阶段级别上,引用另一个阶段的输出变量的格式为dependencies.STAGE.outputs['JOB.TASK.VARIABLE']
  • 在作业级别上,引用另一个阶段的输出变量的格式为stageDependencies.STAGE.JOB.outputs['TASK.VARIABLE']

有关更多详细信息,请参见关于“在不同阶段中使用输出”的文档。

此外,在一个阶段上,如果您使用另一个阶段的输出设置了一个阶段级别变量,应该使用格式stageDependencies.STAGE.JOB.outputs['TASK.VARIABLE']而不是dependencies.STAGE.outputs['JOB.TASK.VARIABLE']。请参见this document

enter image description here

以下是一个参考示例:
  1. azure-pipelines.yml
parameters:
- name: RunStgB
  type: string
  default: YesRun
  values:
  - YesRun
  - NoRun

stages:
- stage: A
  displayName: 'Stage A'
  pool:
    vmImage: ubuntu-latest
  jobs:
  - job: A1
    displayName: 'Job A1'
    steps:
    - task: Bash@3
      name: setOutput
      displayName: 'Set output variable'
      inputs:
        targetType: inline
        script: |
          echo "parameters.RunStgB = ${{ parameters.RunStgB }}"
          echo "##vso[task.setvariable variable=RunStgB;isoutput=true]${{ parameters.RunStgB }}"

- stage: B
  displayName: 'Stage B'
  dependsOn: A
  condition: eq(dependencies.A.outputs['A1.setOutput.RunStgB'], 'YesRun')
  variables:
  - name: Output_RunStgB
    value: $[ stageDependencies.A.A1.outputs['setOutput.RunStgB'] ]
  pool:
    vmImage: ubuntu-latest
  jobs:
  - job: B1
    displayName: 'Job B1'
    steps:
    - task: Bash@3
      displayName: 'show output variable'
      inputs:
        targetType: inline
        script: echo "Output_RunStgB = $(Output_RunStgB)"
  1. 结果。

    enter image description here

    enter image description here


这个答案不适用,请注意@DevOpsy正在使用部署作业,而你正在使用普通作业。他们的条件设置应该是不同的。请参考此文档中的第二个注释。 - Oscar

1
我曾经向微软技术支持提出过这个问题,并得到了解决方案。正确的语法是:
condition: contains(dependencies.build.outputs['build_job.build_job.getCommitMessage.commitMessage'], 'import/')

我已经更新原问题并附上了答案。


我可以确认这个是有效的。 - MeneerBij

0

阶段依赖关系很难调试。没有评估的日志,只能靠试错。奇怪的是工作名称的双重引用??有人可以确认一下是否也适用于您(点赞)?

阶段条件:dependencies.STAGE.outputs['JOB.JOB.TASK.VARIABLE']

例子

stages:
- stage: stage_A
  jobs:
  - job: job1
    steps:
      # Note: isOutput is set to true
    - bash: echo "##vso[task.setvariable variable=boolVar1;isOutput=true]true"
      name: task_1  # Note name is important for reference

- stage: stage_B  # no dependsOn, automatically depends on previous stage.
  condition: and(succeeded(), eq(dependencies.stage_A.outputs['job1.job1.task_1.boolVar1'], 'true'))
  jobs:
  - job: running
    variables: 
      boolVar1: $[ stageDependencies.stage_A.job1.outputs['job1.task_1.boolVar1']]
    steps:
    - bash: echo "Variable reference inside Job: $(boolVar1)"

0

我尝试过了,但是没有用,舞台仍然被跳过了。有没有办法查看依赖结构? - DevOpsy
将这两个阶段中的作业更改为部署作业,它就无法正常工作。请参考我在原帖中提供的示例。 - DevOpsy
好的,是的,我也不明白为什么在每种可能的情况下语法都不同。 - Schamal
是的,对于不同情况,语法存在差异,更令人惊讶的是,这甚至没有在文档中涵盖(尽管文档已经很详尽了,但仍然缺少一些场景)。我认为Azure DevOps团队真的搞砸了这个功能,因为我不得不两次指定作业名称才能使其正常工作,而且甚至没有办法进行诊断。 - DevOpsy

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