Azure YAML管道条件插入不起作用

5
考虑下面的流水线片段,这是一个模板的一部分。
- task: Bash@3
  inputs:
    targetType: 'inline'
    script: |
      echo "##vso[task.setvariable variable=AppType;]WebJob"
      echo "##[debug] AppType set to WebJob"

# This works, using the task condition
- task: DotNetCoreCLI@2
  condition: eq(variables['AppType'], 'WebJob')
  displayName: 'net publish for WebJob'
  inputs:
    command: 'publish'

# This doesn't work, using the conditional insertion, index syntax
- ${{ if eq(variables['AppType'], 'WebJob') }}:
  - task: DotNetCoreCLI@2
    displayName: 'net publish for WebJob'
    inputs:
      command: 'publish'

# This also doesn't work, using the conditional insertion, property dereference syntax
- ${{ if eq(variables.AppType, 'WebJob') }}:
  - task: DotNetCoreCLI@2
    displayName: 'net publish for WebJob'
    inputs:
      command: 'publish'

为什么任务条件有效但条件插入无效呢?使用第二个方法时,我没有收到任何错误提示,只是任务未显示,就像if条件没有被满足一样。
4个回答

5
Azure YAML管道的条件插入无法正常工作
众所周知,${{}}语法用于编译时: 表达式
# Note the syntax ${{}} for compile time and $[] for runtime expressions.

因此,当我们执行管道时,条件插入${{ if eq(variables['AppType'], 'WebJob') }}已经被评估,但是Bash任务尚未运行,AppType的值将始终为null。这就是为什么条件插入不起作用的原因。
为了解决这个问题,我们可以直接定义变量:
 variables:
   AppType: WebJob

或者我们可以定义运行时参数:

parameters:
  - name: AppType
    displayName: AppType
    default: WebJob

谢谢,你为我节省了大量时间。你的解释应该写在 Azure Pipelines 的“表达式”、“变量”和“条件”文档的顶部,并用红色标出。 - Pavel Sapehin

2
${{}} 语法在模板编译时进行评估,而不是在执行过程中进行评估,因此当作业正在设置时,任务将从工作流中删除,因为变量尚不存在,它不会等到实际需要运行任务才评估条件。

您可以使用 $[] 条件语法进行运行时评估,或依赖于 condition: 语法。

根据文档:

# Two examples of expressions used to define variables
# The first one, a, is evaluated when the YAML file is compiled into a plan.
# The second one, b, is evaluated at runtime.
# Note the syntax ${{}} for compile time and $[] for runtime expressions.
variables:
  a: ${{ <expression> }}
  b: $[ <expression> ]

See:


1
感谢您的解释。语法“- $[ if eq(variables.AppType, 'WebJob') ]:”是无效的。 - goosseno
你有用过 Azure DevOps Server 吗? - 4c74356b41
我认为在那种情况下运行时条件无效。模板条件必须使用编译时表达式语法。https://learn.microsoft.com/en-us/azure/devops/pipelines/process/templates - jessehouwing

0

我曾希望在运行时在模板底部设置一个变量,并在顶部使用条件包含来防止模板的某些部分在以后再次被包含...

但是,刘磊指出的编译时间限制阻止了我这样做。我能做到的最接近的方法是使用参数:

# some-template.yml
parameters:
- name: firstParameter
  type: string
  default: ''
- name: hasAlreadyBeenRun
  type: boolean
  default: false

steps:
- ${{ if ne(parameters.hasAlreadyBeenRun, true) }}:
  - task1 that only needs run once
  - task2 that only needs run once
  - task3 that only needs run once
- task to repeat

# consuming-definition.yml
steps:
- ${{ if eq(someCondition1, true) }}:
  - template 'some-template.yml'
  - some task 1
- ${{ if eq(someCondition2, true) }}:
  - some task 2
  - some task 3
- ${{ if eq(someCondition3, true) }}:
  - template 'some-template.yml'
    parameters:
      hasAlreadyBeenRun: ${{ eq(someCondition1, true) }}
  - some task 4
- ${{ if eq(someCondition4, true) }}:
  - template 'some-template.yml'
    parameters:
      hasAlreadyBeenRun: ${{ or(eq(someCondition1, true), eq(someCondition3, true)) }}
  - some task 5

0

我已经在流水线上测试了您的条件,并进行了更改,现在它可以正常工作。您应该更改条件语法,一切都将正确无误。

- task: Bash@3
  inputs:
   targetType: 'inline'
   script: |
     echo "##vso[task.setvariable variable=AppType;]WebJob"
     echo "##[debug] AppType set to WebJob"
- task: CmdLine@2
  inputs:
    script: echo Key:'$(AppType)' 
# This doesn't work, using the conditional insertion, index syntax
  ${{ if eq(variables['AppType'], 'WebJob') }}:
- task: CmdLine@2
  inputs:
    script: echo Key:'$(AppType)'
# This also doesn't work, using the conditional insertion, property dereference syntax
  ${{ if eq(variables.AppType, 'WebJob') }}:
- task: CmdLine@2
  inputs:
    script: echo Key:'$(AppType)'

我建议你尝试使用Visual Studio Code和一个插件或任何IDE来纠正你的YAML文件。

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