【问题标题】:Azure DevOps Yaml pipelines: Stage condition variable syntaxAzure DevOps Yaml 管道:阶段条件变量语法
【发布时间】:2022-09-23 19:17:33
【问题描述】:

我正在开发一个 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)\"

更新(答案):我为此提出了一个 MS 支持案例并得到了解决方案。正确的语法是

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

关于这个奇怪问题的几点:

  • 使用阶段变量的语法与在 条件并使用它作为另一个变量传入。
  • 同样,如果源阶段是作业,则语法不同,如果源阶段是部署作业,则语法是不同的。
  • 最重要的是,我在 MS 文档的任何地方都找不到正确的语法。
  • 我找不到任何诊断问题的方法,例如:在构建日志中查看阶段输出 json 真的很有帮助。
  • 最后,我相信 Azure DevOps 团队真的把这个功能搞砸了。作业/部署作业、条件和变量分配的语法应该是一致的。目前的状态真的很痛苦。

    标签: azure-devops azure-pipelines-yaml multistage-pipeline


    【解决方案1】:

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

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

    更详细的可以查看“Use outputs in a different stage”的文档。

    此外,在一个阶段,如果您使用另一个阶段的输出设置阶段级变量,您应该使用格式stageDependencies.STAGE.JOB.outputs['TASK.VARIABLE']代替dependencies.STAGE.outputs['JOB.TASK.VARIABLE'].见this document

    下面是一个示例作为参考:

    1. 天蓝色管道.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. 结果。

    【讨论】:

    • 这个答案不起作用,请注意@DevOpsy 正在使用部署作业,而您正在使用普通作业。它们的条件设置应该不同。请参阅this document 中的第二条注释。
    【解决方案2】:

    我为此提出了一个 MS 支持案例并得到了解决方案。正确的语法是

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

    我也用答案更新了原始问题。

    【讨论】:

    • 我可以确认这是有效的。
    【解决方案3】:

    如此处所述:https://docs.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=azure-devops#dependencies 我认为您的情况不是这个

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

    应该是这样的:

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

    【讨论】:

    • 我试过了,没有用,阶段仍然被跳过。有没有办法查看依赖结构?
    • 将这两个阶段的这些作业更改为部署作业,它就会停止工作。有关示例,请参见我上面原始帖子中的示例。
    • 好的,是的,也没有得到它,为什么语法在每种可能的情况下都不同。
    • 是的,各种情况下的语法有所不同,更令人惊讶的是,它甚至没有包含在文档中(感觉很详尽,但仍然缺少一些场景)。我相信 Azure DevOps 团队真的把这个功能搞砸了,因为我必须两次指定作业的名称才能让它工作,甚至无法诊断。
    【解决方案4】:

    阶段依赖项很难调试。没有评估日志,这是跟踪和错误。奇怪的是工作名称的双重引用?有人可以证实这一点,如果它也适用于你(upvote)?

    舞台条件:依赖项.STAGE.outputs['JOB.JOB.TASK.VARIABLE'].

    例子

    stages:
    - stage: stage_A
      jobs:
      - job: job1
        steps:
          - bash: echo "##vso[task.setvariable variable=boolVar1;isOutput=true]true"
            name: task_1
    
    - stage: stage_B  # no dependsOn, automatically depends on previous stage.
      condition: and(succeeded(), eq(dependencies.stage_A.outputs['job1.job1.task_1.boolVar1'], 'true'))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-10
      • 2021-11-16
      • 1970-01-01
      • 2020-10-31
      • 2021-11-23
      • 1970-01-01
      • 2023-01-05
      • 1970-01-01
      相关资源
      最近更新 更多