如何在带有变量组的天蓝色DevOps yaml管道的变量中使用IF ELSE?

时间:2019-11-12 16:38:52

标签: azure-devops

除变量组外,我正在尝试将2个值之一分配给变量,并且找不到如何使用IF ELSE的引用。

基本上,我需要将这种jerkins逻辑转换为天蓝色的DevOps。

詹金斯

if (branch = 'master') { 
   env = 'a'
} else if (branch = 'dev'){
    env ='b'
}

我从以下引用中找到1个引用,但是如果变量部分没有变量组,则该引用似乎可以工作。

https://stackoverflow.com/a/57532526/5862540

但是在我的管道中,我已经有一个用于秘密的变量组,因此我必须使用名称/值约定,并且该示例不适用于诸如expected a mappingA mapping was not expected或{ {1}}

Unexpected value 'env'

variables:
- group: my-global
- name: env
  value:
    ${{ if eq(variables['Build.SourceBranchName'], 'master') }}: 
      env: a
    ${{ if eq(variables['Build.SourceBranchName'], 'dev') }}: 
      env: b

5 个答案:

答案 0 :(得分:6)

此代码有效。
我在参数上也做类似的事情。

variables:
  - name: var1
    ${{ if eq(parameters.var1, 'custom') }}:
      value: $(var1.manual.custom)
    ${{ if ne(parameters.var1, 'custom') }}:
      value: ${{ parameters.var1 }}

答案 1 :(得分:3)

我发现了对某些场景有些有用的技巧。例如,人们可能希望根据是否启用系统调试来调整任务输入。这不能使用“标准条件插入”(${{ if … }}:) 来完成,因为 System.Debug 不在模板表达式的范围内。所以,runtime expressions 来拯救:

- job:
  variables:
    VERBOSE_FLAG: $[
        replace(
          replace(
            eq(lower(variables['System.Debug']), 'true'),
            True,
            '--verbose'
          ),
          False,
          ''
        )
      ]
  steps:
    - task: cURLUploader@2
      inputs:
        # …
        options: --fail --more-curl-flags $(VERBOSE_FLAG)

请注意,在调用 eq 之前使用 System.Debug 检查 replace 的值并不是多余的:因为 eq 总是返回 True 或 {{1 }},然后我们可以安全地使用 False 将这些值分别映射到 replace'--verbose'

总的来说,我强烈建议首先使用布尔表达式(例如应用布尔值 function,如 ''eqgt)内部 in 应用程序的参数。如果我们没有这样做,而是只是编写示例

replace

然后,如果 replace( replace( lower(variables['System.Debug']), 'true', '--verbose' ), 'false', '' ) 设置为例如System.Debugfootruebar 的值将变为 VERBOSE_FLAG

答案 2 :(得分:0)

我认为现在您将需要使用一个任务来使用name/value语法变量和条件变量值进行自定义。正如您所指出的,name/value语法的对象结构似乎破坏了表达式的解析。

对我来说,以下是一个相当干净的实现,并且如果您希望将其从管道中抽象出来,那么看来,供许多管道使用的简单模板应该可以满足对中央“全局”位置的需求。

variables:
  - group: FakeVarGroup
  - name: env
    value: dev

steps:
  - powershell: |
      if ($env:Build_SourceBranchName -eq 'master') {
        Write-Host ##vso[task.setvariable variable=env;isOutput=true]a
        return
      } else {
        Write-Host ##vso[task.setvariable variable=env;isOutput=true]b
      }      
    displayName: "Set Env Value"

答案 3 :(得分:0)

据我所知,有条件分支构建的最佳方法是在YAML中使用“触发器”,而不是实现复杂的“ if-else”。它也更安全,而且您对分支触发器有更明确的控制,而不必依赖CI变量。

示例:

# specific branch build 
jobs:
- job: buildmaster
  pool:
    vmImage: 'vs2017-win2016'
  trigger:
    - master

  steps:
  - script: |
      echo "trigger for master branch"

- job: buildfeature
  pool:
    vmImage: 'vs2017-win2016'
  trigger:
    - feature

  steps:
  - script: |
      echo "trigger for feature branch"

要具有包含和排除分支的触发器,可以使用具有包含和排除分支的触发器的更复杂语法。

示例:

# specific branch build
trigger:
  branches:
    include:
    - master
    - releases/*
    exclude:
    - releases/1.*

YAML中的Azure DevOps管道trigger的正式文档为: Azure Pipelines YAML trigger documentation

更新1

我在此处重新发表我的评论并附带其他说明: 我当时想使用不同的管道,因为与在一个带有触发器的YAML中具有多个作业相比,在CI变量之间进行处理的复杂性更难以维护。具有触发器的多任务也迫使我们在分支机构管理上有明确的区别和规定。由于这些可维护性优势,我的团队已使用触发器和条件分支包含项一年了。

随意不同意,但是对我来说,在任何脚本中的任何步骤中都有嵌入式逻辑可以检查会话中当前处于哪个分支,然后执行任何进一步的操作,这更像是临时解决方案。这给了我和我的团队以前的维护问题。

特别是如果嵌入式逻辑倾向于通过检查其他分支来增长,则复杂性要比分支之间的清晰分隔要复杂得多。另外,如果要长期维护YAML文件,则应在不同分支机构之间有明确的规定和路线图。冗余是不可避免的,但是从长远来看,分离特定逻辑的意图将为可维护性付出更多。

这就是为什么我在回答中也强调分支包含和排除的原因:)

答案 4 :(得分:0)

带有模板表达式${{ if ...... }}的语法不仅限于作业/阶段级别。下面的两个管道执行相同的操作并产生相同的输出:

stages:
- stage: One
  displayName: Build and restore
  variables:
  - group: PROD
  - name: env
    ${{ if eq(variables['Build.SourceBranchName'], 'master') }}:
      value: a
    ${{ if eq(variables['Build.SourceBranchName'], 'dev') }}:
      value: b
  jobs:
  - job: A
    steps:
    - script: | 
        echo '$(name)'
        echo '$(env)'
variables:
- group: PROD
- name: env
  ${{ if eq(variables['Build.SourceBranchName'], 'master') }}:
    value: a
  ${{ if eq(variables['Build.SourceBranchName'], 'dev') }}:
    value: b

steps:
- script: | 
    echo '$(name)'
    echo '$(env)'