以自定义变量为条件的Azure管道

时间:2020-06-02 12:55:34

标签: yaml azure-pipelines

我们想优化我们的管道,以避免运行特殊情况下不需要的步骤。
我创建了一个变量shouldTriggerAnyBuild,但由于总是运行指定的步骤,因此它似乎总是正确的(或被忽略了),即使后面的条件组合中的任何一个都没有运行。 >

脚本有什么问题或如何调试?

trigger:
- master
- stage
- release/*

pool:
  vmImage: 'macOS-latest'

variables:
  shouldTriggerAnyBuild: $[ or(and(eq(variables['Build.SourceBranch'], 'refs/heads/master'), not(startsWith(variables['Build.SourceVersionMessage'], 'release:'))), eq(variables['Build.SourceBranch'], 'refs/heads/stage'), startsWith(variables['Build.SourceBranch'], 'refs/heads/release/')) ]

steps:
- task: UseRubyVersion@0
  inputs:
    versionSpec: '~> 2.6'

- script: echo "y" | $ANDROID_HOME/tools/bin/sdkmanager --install 'system-images;android-29;google_apis;x86'
  displayName: 'install/setup android sdkmanager'
  condition: variables.shouldTriggerAnyBuild

- script: gem install bundler
  displayName: 'gem install bundler'
  condition: variables.shouldTriggerAnyBuild

- script: bundle install
  displayName: 'bundle install'
  condition: variables.shouldTriggerAnyBuild

- script: bundle exec fastlane ciBuildDev
  displayName: 'build dev'
  condition: and(eq(variables['Build.SourceBranch'], 'refs/heads/master'),  not(startsWith(variables['Build.SourceVersionMessage'], 'release:')))

- script: bundle exec fastlane ciDeployToTest
  displayName: 'build stage'
  condition: eq(variables['Build.SourceBranch'], 'refs/heads/stage')

- script: bundle exec fastlane ciDeployToGooglePlay
  displayName: 'build release'
  condition: startsWith(variables['Build.SourceBranch'], 'refs/heads/release/')

- task: PublishBuildArtifacts@1
  displayName: "Publish artifacts .apk"
  condition: startsWith(variables['Build.SourceBranch'], 'refs/heads/release/')
  inputs:
    PathtoPublish: ./app/build/outputs/apk/prod/app-prod-unsigned.apk
    ArtifactName: Prod_app_apk

https://docs.microsoft.com/en-us/azure/devops/pipelines/process/expressions?view=azure-devops

2 个答案:

答案 0 :(得分:1)

脚本有什么问题?

Conditions被写为expressionscondition: variables.shouldTriggerAnyBuild不会生效。 相反,您可以使用condition: eq(variables['SHOULDTRIGGERANYBUILD'], 'True')作为条件步骤。我认为这是造成您问题的直接原因。另外,请随时使用condition: eq(variables['shouldTriggerAnyBuild'], 'True'),它也可以使用。

如何调试它?

以下是在必要时调试值的快速方法:

1。将第二个值更改为不可能的变量,然后在跳过该步骤时可以检查自定义变量的实际值:

enter image description here

2。如果您想使所有内容都清晰明了,则可以执行以下操作:

- task: CmdLine@2
  inputs:
    script: |
      echo Hello world
  condition: eq(and(eq(variables['Build.SourceBranch'], 'refs/heads/master'), not(startsWith(variables['Build.SourceVersionMessage'], 'release:'))),'True')

- task: CmdLine@2
  inputs:
    script: |
      echo Hello world
  condition: eq(eq(variables['Build.SourceBranch'], 'refs/heads/stage'),'True')

- task: CmdLine@2
  inputs:
    script: |
      echo Hello world
  condition: eq(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'),'True')

由于您的变量是通过Or function通过and(eq(variables['Build.SourceBranch'], 'refs/heads/master'), not(startsWith(variables['Build.SourceVersionMessage'], 'release:')))eq(variables['Build.SourceBranch'], 'refs/heads/stage')startsWith(variables['Build.SourceBranch'], 'refs/heads/release/')组合而成的,因此您可以将它们划分以调试shouldTriggerAnyBuild的扩展方式始终True

通过这种方式,您可以轻松地调试它们以查找变量的扩展方式:

enter image description here

enter image description here

enter image description here

注意:

1.Or函数:如果任何参数为true,则求值True

2。在大多数情况下,如果先前任务之一失败,我们通常选择跳过当前任务,因此您可以考虑合并succeeded()和变量shouldTriggerAnyBuild。示例here

答案 1 :(得分:0)

经过大量的反复试验,我们发现有Build.SourceVersionMessage表示我们不能将其用作变量,因此最终遭到了黑客攻击,如下所示:

trigger:
  - master
  - stage
  - release/*

pool:
  vmImage: "macOS-latest"

variables:
  # we can't use Build.SourceVersionMessage up here because it's not defined when the variables is set here

  isMaster: ${{eq(variables['Build.SourceBranch'], 'refs/heads/master')}}
  isStage: ${{eq(variables['Build.SourceBranch'], 'refs/heads/stage')}}
  isRelease: ${{startsWith(variables['Build.SourceBranch'], 'refs/heads/release/')}}
  releaseMessagePrefix: "release:"

jobs:
  - job:
    steps:
      - task: UseRubyVersion@0
        displayName: "set ruby version"
        inputs:
          versionSpec: "~> 2.6"

      - task: Bash@3
        displayName: "set commitMessage variable"
        inputs:
          targetType: inline
          script: echo '##vso[task.setvariable variable=commitMessage]$(Build.SourceVersionMessage)'

      - script: echo "y" | $ANDROID_HOME/tools/bin/sdkmanager --install 'system-images;android-29;google_apis;x86'
        displayName: "install/setup android sdkmanager"
        condition: or(and(variables.isMaster, not(startsWith(variables.commitMessage, variables.releaseMessagePrefix))), ${{variables.isStage}}, ${{variables.isRelease}})

      - script: gem install bundler
        displayName: "gem install bundler"
        condition: or(and(variables.isMaster, not(startsWith(variables.commitMessage, variables.releaseMessagePrefix))), ${{variables.isStage}}, ${{variables.isRelease}})

      - script: bundle install
        displayName: "bundle install"
        condition: or(and(variables.isMaster, not(startsWith(variables.commitMessage, variables.releaseMessagePrefix))), ${{variables.isStage}}, ${{variables.isRelease}})

      - script: bundle exec fastlane ciBuildDev
        displayName: "Build: dev"
        condition: and(variables.isMaster, not(startsWith(variables.commitMessage, variables.releaseMessagePrefix)))

      - script: bundle exec fastlane ciDeployToTest
        displayName: "Build: stage"
        condition: ${{variables.isStage}}

      - script: bundle exec fastlane ciDeployToGooglePlay
        displayName: "Build: release"
        condition: ${{variables.isRelease}}

      - task: PublishBuildArtifacts@1
        displayName: "Publish: .apk"
        condition: ${{variables.isRelease}}
        inputs:
          PathtoPublish: ./app/build/outputs/apk/prod/app-prod-unsigned.apk
          ArtifactName: Prod_app_apk