在模板作业中跨阶段使用管道变量

dau*_*hey 5 azure-devops azure-pipelines-yaml

问题描述

我在尝试在另一个阶段使用在一个阶段中创建的变量时遇到了一些问题,并设法找到了各种新旧文章来描述如何完成此操作。识别新语法的最新文章/帖子

$[stageDependencies.{stageName}.{jobName}.outputs['{stepName}.{variableName}']

像这样使用:

variables:
  myVariable: $[stagedependencies.CreateStageVarStage.CreateStageVarJob.outputs['SetValueStep.VariableFromFirstStage']]
Run Code Online (Sandbox Code Playgroud)

在您需要使用作业模板之前,这非常有效。

我在网上找到的示例都没有涵盖模板的情况。他们只是演示了同一个 yaml 文件中的多个阶段如何获取该值。

语法取决于能否将表达式放入变量中。不幸的是,当您在作业中使用模板时,无法声明变量并将其作为参数传递,从而导致其无法求值。

- stage: UseJobTemplateStage
  displayName: 'Use Job Template Stage'
  dependsOn: CreateStageVarStage
  jobs:
  - template: templates/job-showstagevars.yml
    parameters:
      ValueToOutput: $[ stagedependencies.CreateStageVarStage.CreateStageVarJob.outputs['SetValueStep.VariableFromFirstStage'] ]
Run Code Online (Sandbox Code Playgroud)

在这个片段中,它按原样出现。该值不会被替换。

理论上,您可以将作业设置为使表达式存在于变量块中,但这种硬编码破坏了模板的主要优点之一。

相关文章

在 Azure DevOps Pipelines 中跨阶段共享变量
Azure DevOps 发行说明 - sprint 168

dau*_*hey 3

解决方案

答案其实并不遥远。原始表达式只需要通过模板作业中的变量传递即可。基本上,将一个变量设置为参数的值,并使用宏语法来计算该变量。

parameters:
- name: ValueToOutput
  type: string

...

  variables:
  - name: LocalVarOfValueToOutputParam
    value: ${{ parameters.ValueToOutput }}
Run Code Online (Sandbox Code Playgroud)

使用 的宏语法$(LocalVarOfValueToOutputParam)将导致该值正确进入模板作业。

其他一些提示:

  • 如果您定义了矩阵策略,则需要Strategy添加ValueToOutput: $[ stagedependencies.CreateStageVarStage.CreateStageVarJob.outputs['Strategy.SetValueStep.VariableFromFirstStage'] ]
  • 如果您使用的script是 powershell,则必须使用true不带 $ 的echo "##vso[task.setvariable variable=VariableFromFirstStage;isOutput=true]$message"
  • 如果您不是在阶段之间而是在工作之间执行此操作,请使用$[ dependencies.CreateStageVarStage.CreateStageVarJob.outputs['Strategy.SetValueStep.VariableFromFirstJob'] ]

例子

如果我们有一个用于构建定义的 yaml 文件:

stages:
- stage: CreateStageVarStage
  displayName: 'Create StageVar Stage'
  jobs:
  - job: CreateStageVarJob
    displayName: 'Create StageVar Job'
    timeoutInMinutes: 5
    pool:
      name:    'Azure Pipelines'
      vmImage: 'windows-2019'
    steps:
      - checkout: none 
      - pwsh: |
          [string]$message = 'This is the value from the first stage'
          Write-Host "Setting output variable 'VariableFromFirstStage' to '$message'"
          Write-Output "##vso[task.setvariable variable=VariableFromFirstStage;isOutput=$true]$message"
        name: SetValueStep

- stage: UseJobTemplateStage
  displayName: 'Use Job Template Stage'
  dependsOn: CreateStageVarStage
  jobs:
  - template: templates/job-showstagevars.yml
    parameters:
      ValueToOutput: $[ stagedependencies.CreateStageVarStage.CreateStageVarJob.outputs['SetValueStep.VariableFromFirstStage'] ]
Run Code Online (Sandbox Code Playgroud)

使用作业模板templates/job-showstagevars.yml

parameters:
- name: ValueToOutput
  type: string

jobs:
- job: ShowStageVarJob
  displayName: 'Show stage var'
  timeoutInMinutes: 5
  pool:
    name:    'Azure Pipelines'
    vmImage: 'windows-2019'

  variables:
  - name: LocalVarOfValueToOutputParam
    value: ${{ parameters.ValueToOutput }}

  steps:
  - checkout: none
  - pwsh: |
      Write-Host "ValueToOutput parameter=${{ parameters.ValueToOutput }}"
      Write-Host "LocalVarOfValueToOutputParam (pre-processor syntax)=${{ variables.LocalVarOfValueToOutputParam }}"
      Write-Host "LocalVarOfValueToOutputParam (macro syntax)=$(LocalVarOfValueToOutputParam)"
    displayName: 'Show StageVariable'
Run Code Online (Sandbox Code Playgroud)

我们在第二阶段的输出中得到的是这样的。请注意,只有最后一个表达式的计算结果才是正确的值!

ValueToOutput parameter=$[ stagedependencies.CreateStageVarStage.CreateStageVarJob.outputs['SetValueStep.VariableFromFirstStage'] ]
LocalVarOfValueToOutputParam (pre-processor syntax)=$[ stagedependencies.CreateStageVarStage.CreateStageVarJob.outputs['SetValueStep.VariableFromFirstStage'] ]
LocalVarOfValueToOutputParam (macro syntax)=This is the value from the first stage
Run Code Online (Sandbox Code Playgroud)