45

除了变量组之外,我还试图将 2 个值之一分配给一个变量,但找不到如何使用 IF ELSE 的参考。

基本上我需要将这个 jerkins 逻辑转换为 azure 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或之类的错误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

或者

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

4

7 回答 7

43

此代码有效。
我对参数做类似的事情。

variables:
  - name: var1
    ${{ if eq(parameters.var1, 'custom') }}:
      value: $(var1.manual.custom)
    ${{ if ne(parameters.var1, 'custom') }}:
      value: ${{ parameters.var1 }}
于 2020-09-22T13:57:45.467 回答
34

2021 年 9 月 9 日更新

我们现在有原生的 if else 表达式,我们可以这样写

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

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

原始回复

带有模板表达式${{ 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)'
于 2020-09-22T20:18:05.087 回答
7

微软几周前发布了 YAML 管道的新功能,它可以让你做到这一点:IF ELSE符号。

https://docs.microsoft.com/en-us/azure/devops/release-notes/2021/sprint-192-update#new-yaml-conditional-expressions

使用 ${{ else }} 和 ${{ elseif }} 表达式在 YAML 文件中编写条件表达式变得更加容易。以下是如何在 YAML 管道文件中使用这些表达式的示例。

steps:
- script: tool
  env:
    ${{ if parameters.debug }}:
      TOOL_DEBUG: true
      TOOL_DEBUG_DIR: _dbg
    ${{ else }}:
      TOOL_DEBUG: false
      TOOL_DEBUG_DIR: _dbg
variables:
  ${{ if eq(parameters.os, 'win') }}:
    testsFolder: windows
  ${{ elseif eq(parameters.os, 'linux' }}:
    testsFolder: linux
  ${{ else }}:
    testsFolder: mac
于 2021-10-20T13:47:31.940 回答
3

我认为现在您将需要使用任务来自定义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"
于 2019-11-13T00:34:08.667 回答
3

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

- 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来检查 的值并不是多余的:因为总是返回or ,所以我们可以安全地使用将这些值分别映射到和。System.DebugreplaceeqTrueFalsereplace'--verbose'''

一般来说,我强烈建议坚持使用布尔表达式(例如,应用布尔值函数,如eq,gtin)作为内部replace应用程序的第一个参数。如果我们没有这样做,而只是写了例如

        replace(
          replace(
            lower(variables['System.Debug']),
            'true',
            '--verbose'
          ),
          'false',
          ''
        )

那么,如果System.Debug设置为 eg footruebar,则 的值VERBOSE_FLAG将变为foo--verbosebar

于 2021-04-21T14:36:36.273 回答
1

Azure YAML if-else 解决方案(当您group定义了此后使用的所需名称/值表示法时。

variables:
- group: my-global
- name: env
  value: a       # set by default
- name: env
  ${{ if eq(variables['Build.SourceBranchName'], 'master') }}:
  value: b     # will override default

如果您没有group定义:

variables:
 env: a       # set by default
 ${{ if eq(variables['Build.SourceBranchName'], 'master') }}:
 env: b      # will override default
于 2021-05-21T02:20:26.670 回答
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 Pipelines 的官方文档trigger是: Azure Pipelines YAML 触发器文档

更新 1

我在这里重新发表我的评论并附上额外的注释:我正在考虑使用不同的管道,因为在 CI 变量之间进行杂耍的复杂性并不比在一个带有触发器的 YAML 中拥有多个作业更易于维护。具有触发器的多项工作也迫使我们对分支管理有明确的区分和规定。由于这些可维护性优势,我的团队已经使用了一年的触发器和条件分支包含。

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

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

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

于 2019-11-13T07:44:16.193 回答