在脚本中设置变量

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

在管道中使用 PowerShell 和 Bash 脚本时,如果能够设置可在将来的任务中使用的变量,则通常会很有帮助。 新设置的变量在同一任务中不可用。

如果你要执行的操作不受某个任务的支持(例如调用自定义 REST API 和分析响应)时,则脚本非常有用。

你将使用 task.setvariable 日志记录命令在 PowerShellBash 脚本中设置变量。

注意

部署作业对输出变量使用不同的语法。 若要详细了解部署作业中对输出变量的支持,请参阅部署作业

若要在管道中使用带有条件的变量,请参阅指定条件

关于 task.setvariable

添加包含 task.setvariable 的变量时,以下任务可以按照宏语法 $(myVar) 使用该变量。 默认情况下,变量仅适用于同一作业中的任务。 如果添加参数 isoutput,则用于调用变量的语法会更改。 请参阅设置用于同一作业的输出变量

设置包含值 foo 的变量 myVar

- bash: |
    echo "##vso[task.setvariable variable=myVar;]foo"

读取变量 myVar

- bash: |
    echo "You can use macro syntax for variables: $(myVar)"

设置变量属性

task.setvariable 命令包含用于将变量设置为机密、输出变量和只读的属性。 可用属性包括:

  • variable = 变量名称(必需)
  • issecret = 布尔值(可选,默认值为 false)
  • isoutput = 布尔值(可选,默认值为 false)
  • isreadonly = 布尔值(可选,默认值为 false)

若要在下一阶段中使用变量,请将 isoutput 属性设置为 true。 若要引用 isoutput 设置为 true 的变量,请包含任务名称。 例如 $(TaskName.myVar)

将变量设置为只读后,下游任务无法覆盖该变量。 将 isreadonly 设置为 true。 将某个变量设置为只读会使该变量不可变,因而可增强安全性。

将变量设置为机密

issecret 设置为 true 时,变量的值将另存为机密并从日志中屏蔽。

注意

Azure Pipelines 在向管道日志发出数据时会努力屏蔽机密,因此你可能会在输出和日志中看到未设置为机密的其他变量和数据掩码。

设置机密变量 mySecretVal

- bash: |
    echo "##vso[task.setvariable variable=mySecretVal;issecret=true]secretvalue"

获取机密变量 mySecretVal

- bash: |
    echo "##vso[task.setvariable variable=mySecretVal;issecret=true]secretvalue"
- bash: |
    echo $(mySecretVal)

bash 中的机密变量输出。

屏幕截图显示 bash 变量输出。

输出变量的级别

有四种不同类型的输出变量,其语法各不相同:

注意

如果将来的阶段或作业依赖于设置变量的阶段或作业,则将来的阶段或作业只能访问输出变量。 若要将输出变量设为可访问,请确保下一阶段或作业依赖于创建变量的阶段或作业。 如果多个阶段或作业需要使用相同的输出变量,请使用 dependsOn 条件来建立此依赖项。

设置用于同一作业的输出变量

在同一作业中使用输出变量时,无需使用 isoutput 属性。 默认情况下,该变量将可用于同一作业中的下游步骤。 但是,如果你确实要添加 isoutput 属性,则需要使用任务名称引用该变量。

此处的脚本在不指定 isoutput 的情况下设置同作业输出变量 myJobVar,并在指定 isoutput=true 的情况下设置 myOutputJobVar

jobs:
- job: A
  steps:
  - bash: |
     echo "##vso[task.setvariable variable=myJobVar]this is the same job"
  - bash: |
     echo "##vso[task.setvariable variable=myOutputJobVar;isoutput=true]this is the same job too"
    name: setOutput

此脚本获取同作业变量 myJobVarmyOutputJobVar。 请注意,添加 isoutput=true 后,用于引用输出变量的语法会更改。

jobs:
- job: A
  steps:
  - bash: |
     echo "##vso[task.setvariable variable=myJobVar]this is the same job"
  - bash: |
     echo "##vso[task.setvariable variable=myOutputJobVar;isoutput=true]this is the same job too"
    name: setOutput
  - bash: |
     echo $(myJobVar) 
  - bash: |
     echo $(setOutput.myOutputJobVar)

设置要在将来的作业中使用的输出变量

跨作业使用输出变量时,请使用 dependencies 引用这些变量。 用于在将来的作业或阶段中访问输出变量的语法,根据该变量的设置者和使用者之间的关系而变化。 在依赖关系中了解每种案例。

首先,设置输出变量 myOutputVar

jobs:
- job: A
  steps:
  - bash: |
     echo "##vso[task.setvariable variable=myOutputVar;isoutput=true]this is from job A"
    name: passOutput

接下来,在将来的作业中访问 myOutputVar 并将变量输出为 myVarFromJobA。 若要使用 dependencies,需要使用设置了输出变量的以往作业名称来设置将来作业的 dependsOn 属性。

jobs:
- job: A
  steps:
  - bash: |
     echo "##vso[task.setvariable variable=myOutputVar;isoutput=true]this is from job A"
    name: passOutput
- job: B
  dependsOn: A
  variables:
    myVarFromJobA: $[ dependencies.A.outputs['passOutput.myOutputVar'] ]  
  steps:
  - bash: |
     echo $(myVarFromJobA)

设置要在将来的阶段中使用的输出变量

可以跨管道中的阶段使用输出变量。 可以使用输出变量将有用的信息(例如生成的输出的 ID)从一个阶段传递到下一个阶段。

设置带有 isoutput 属性的变量后,可以在后续阶段中使用任务名称和 stageDependencies 语法引用该变量。 详细了解依赖关系

输出变量仅在下一个下游阶段中可用。 如果多个阶段使用相同的输出变量,请使用 dependsOn 条件。

首先,设置输出变量 myStageVal

steps:
  - bash: echo "##vso[task.setvariable variable=myStageVal;isOutput=true]this is a stage output variable"
    name: MyOutputVar

然后,在将来的阶段中,将输出变量 myStageVal 映射到阶段、作业或任务范围的变量,例如 myStageAVar。 请注意,映射语法使用运行时表达式 $[],并使用阶段名称 (A) 和作业名称 (A1) 跟踪从 stageDependencies 到输出变量的路径,以完全限定变量。

stages:
- stage: A
  jobs:
  - job: A1
    steps:
     - bash: echo "##vso[task.setvariable variable=myStageVal;isOutput=true]this is a stage output variable"
       name: MyOutputVar
- stage: B
  dependsOn: A
  jobs:
  - job: B1
    variables:
      myStageAVar: $[stageDependencies.A.A1.outputs['MyOutputVar.myStageVal']]
    steps:
      - bash: echo $(myStageAVar)

如果值包含换行符,你可以将换行符转义,而代理会自动取消转义:

steps:
- bash: |
    escape_data() {
      local data=$1
      data="${data//'%'/'%AZP25'}"
      data="${data//$'\n'/'%0A'}"
      data="${data//$'\r'/'%0D'}"
      echo "$data"
    }
    echo "##vso[task.setvariable variable=myStageVal;isOutput=true]$(escape_data $'foo\nbar')"
  name: MyOutputVar

FAQ

我的输出变量未呈现。 出什么问题了吗?

有多个原因会导致输出变量不显示。

  • 使用 isoutput 设置的输出变量在同一作业中不可用,而仅在下游作业中可用。
  • 根据使用的变量语法,设置输出变量值的变量在运行时可能不可用。 例如,采用宏语法 ($(var)) 的变量会在任务运行之前进行处理。 相比之下,采用模板语法的变量会在运行时进行处理 ($[variables.var])。 在设置输出变量时,你通常想要使用运行时语法。 有关变量语法的详细信息,请参阅定义变量
  • 表达式中可能包含多余的空格。 如果变量未呈现,请检查 isOutput=true 两侧是否存在多余的空格。

可以通过为依赖项添加变量,然后打印该变量,对管道作业或阶段的 dependencies 输出进行故障排除。 例如,在此管道作业 A 中设置输出变量 MyTask。 第二个作业 (B) 取决于作业 A。 一个新变量 deps 用于保存作业依赖项的 JSON 表示形式。 作业 B 中的第二步使用 PowerShell 输出 deps,以便你可以看到作业依赖项。

trigger:
- '*'

pool:
  vmImage: 'ubuntu-latest'
 
jobs:
- job: A
  steps:
    - script: |
        echo "##vso[task.setvariable variable=MyTask;isOutput=true]theoutputval"
      name: ProduceVar  
- job: B
  dependsOn: A
  variables:
    varFromA: $[ dependencies.A.outputs['ProduceVar.MyTask'] ]
    deps: $[convertToJson(dependencies)] # create a variable with the job dependencies
  steps:
  - script: echo $(varFromA) # 
  - powershell: Write-Host "$(deps)"