Azure Pipeline:在一个模板中设置变量,在另一个模板中的表达式中使用它

Azure Pipeline: Setting variable in one template, use it in expression in another

我试图达到的目标:

  1. 在名为 set-variable.yml
  2. 的模板 1 中设置变量 featureName
  3. 将变量 featureName 作为参数传递给名为 check-variable.yml
  4. 的模板 2
  5. 检查模板 2 的编译时表达式中的 featureName 参数是否为空。

pipeline.yml:

trigger:
  - '*' # Run on all Branches

pool:
    vmImage: ubuntu-latest

stages:
- stage: test1
  jobs:
  - job: test1
    steps:
    - template: set-variable.yml
    - template: check-variable.yml
      parameters:
        featureName: $(setVariables.featureName)

设置-variable.yml:

steps:
- script: |
    featureName=''
    echo "##vso[task.setvariable variable=featureName;isOutput=true]$featureName"
  displayName: Set variable 
  name: setVariables

检查-variable.yml:

parameters:
- name: featureName
  type: string
  default: ''


steps:
- ${{ if ne(parameters.featureName, '') }}:
  - script: |
      echo "This should not be executed, but it is!"
    displayName: "featureName != ''"

问题是,check-variable.yml 中的步骤 featureName != '' 被执行了,即使我将 set-variables.yml 模板中的 featureName 变量设置为空。

(将变量 featureName 作为参数传递给模板 check-variable.yml 有效,请参阅下面的调试尝试)

=== 调试 1 ===

出于调试目的,我用一些调试任务扩展了 check-variable.yml

检查-variable.yml:

parameters:
- name: featureName
  type: string
  default: ''


steps:
- script: |
    echo "Check feature"
    echo "- featureNameDotted: [${{ parameters.featureName }}]"
    echo "- featureNameArray: [${{ parameters['featureName'] }}]"
    echo "- featureNameEnvDotted: [$featureNameEnvDotted]"
    echo "- featureNameEnvArray: [$featureNameEnvArray]"
    echo "- json: [${{ convertToJson(parameters.featureName) }}]"
    echo "- length: [${{ length(parameters.featureName) }}]"
    echo

    if [[ -z $featureNameEnvDotted ]]; then
      echo "featureNameEnvDotted is (empty or null)"
    else
      echo "featureNameEnvDotted not (empty or null)"
    fi
    echo

    if [[ $featureNameEnvDotted = '' ]]; then
      echo "featureNameEnvDotted = ''"
    else
      echo "featureNameEnvDotted != ''"
    fi
    echo

    if [[ $featureNameEnvDotted = 'hello' ]]; then
      echo "featureNameEnvDotted = 'hello'"
    else
      echo "featureNameEnvDotted != 'hello'"
    fi
  env:
    featureNameEnvDotted: ${{ parameters.featureName }}
    featureNameEnvArray: ${{ parameters['featureName'] }}
  displayName: "Debug: All"
  
- ${{ if eq(parameters.featureName, '') }}:
  - script: |
      echo 
    env:
      featureName: ${{ parameters.featureName }}
    displayName: "Debug: Empty!!"

- ${{ if ne(parameters.featureName, '') }}:
  - script: |
      echo 
    env:
      featureName: ${{ parameters.featureName }}
    displayName: "Debug: Not empty!!"
  
- ${{ if eq(parameters.featureName, 'hello') }}:
  - script: |
      echo 
    env:
      featureName: ${{ parameters.featureName }}
    displayName: "Debug: Equals 'hello'"

- ${{ if ne(parameters.featureName, '') }}:
  - script: |
      echo "This should not be executed, but it is!"
    displayName: "featureName != ''"

任务Debug: All的输出是:

Check feature

  • featureNameDotted: []
  • featureNameArray: []
  • featureNameEnvDotted: []
  • featureNameEnvArray: []
  • json: []
  • length: [27]

featureNameEnvDotted is (empty or null)

featureNameEnvDotted = ''

featureNameEnvDotted != 'hello'

bash 如果一切正常。 featureName 为空且不是 'hello'。 'length'一个没看懂

并执行以下任务:

为什么任务 Debug: Not empty!!featureName != '' 得到执行,但任务 Debug: Empty!! 没有? featureName 参数 IMO 为空!

=== 调试 2 ===

check-variable.yml 保持不变。但是我在 set-variable.yml 模板中将 featureName 设置为值“hello”。有了这个我想检查变量 featureName 是否正确传递给模板的参数 check-variable.yml

设置-variable.yml:

steps:
- script: |
    featureName='hello'
    echo "##vso[task.setvariable variable=featureName;isOutput=true]$featureName"
  displayName: Set variable 
  name: setVariables

任务Debug: All的输出是:

Check feature

  • featureNameDotted: [hello]
  • featureNameArray: [hello]
  • featureNameEnvDotted: [hello]
  • featureNameEnvArray: [hello]
  • json: [hello]
  • length: [27]

featureNameEnvDotted not (empty or null)

featureNameEnvDotted != ''

featureNameEnvDotted = 'hello'

这又看起来不错。该参数确实包含值 'hello' 并且 if 看起来不错(不过,长度我不明白)。

这里是要执行的任务列表:

为什么Debug: Equals 'hello'没有执行?

parameters.featureName 包含类似于值 'hello' 的内容,但它不完全是字符串 'hello'。我是不是做错了什么?

我发现了问题。评估为 27 的 ${{ length(parameters.featureName) }} 将我推向了正确的方向。 27 是传递给模板 check-variable.yml.

的字符串 $(setVariables.featureName) 的长度

这可以用我在 check-variable.yml 中输入的以下表达式进行测试:

- ${{ if eq(parameters.featureName, '$(setVariables.featureName)') }}:
  - script: |
      echo 
    env:
      featureName: ${{ parameters.featureName }}
    displayName: "Debug: Equals 'dollar(setVariables.featureName)'"

这总是在设置 featureName 或为空时执行。

我认为发生的情况是,当在模板内评估 ${{ ... }} 等编译时表达式时,参数 featureName 被评估为 $(setVariables.featureName)${{ if ... }} 表达式以及带有 ${{ parameters...}} 的脚本任务就是这种情况。在对 ${{ ... }} 表达式求值后,它开始执行脚本任务。它在那里找到变量 $(setVariables.featureName) 并对其求值。但是对于带有 if 语句的编译时表达式,永远不会对 $(setVariables.featureName) 进行求值。在那里它只需要变量的名称。

所以为了让它工作,我做了一个工作,我在脚本任务中设置了一个变量,并使用任务条件来评估它。

check-variable.yml:

parameters:
- name: featureName
  type: string
  default: ''


steps:
- script: |
    echo "##vso[task.setvariable variable=featureName]${{ parameters.featureName }}"
  displayName: "Set featureName var"

- script: |
    echo "Only execute me when featureName is not empty"
  displayName: "featureName != ''"
  condition: and(succeeded(), ne(variables.featureName, ''))