即使前一个作业被跳过,Azure Pipelines也不会跳过后续的作业
我试着通过谷歌搜索和咨询AI,但似乎还是搞不清楚以下问题。
我有一个流水线,依次是 Build -> Detect IaC changes -> IaC -> Deploy Dev/Test。其中IaC(Infrastructure as Code,基础设施即代码)正在部署Azure DevOps资源。你大概也能猜到,我只想在确实有变更时才部署IaC,因为这会额外花费几分钟。这个逻辑已经实现,但我遇到的问题是:如果 Detect IaC changes 判断没有IaC变更,因此跳过 IaC 这个作业,那么后续的流水线 Deploy Dev/Test 也会被跳过……其实不应该。
我的主流水线大致如下:
jobs:
- template: '../../../infra/devops/deploy-azure-resources.yml'
parameters:
...
forceIaC: ${{ parameters.forceIaC }}
- template: '../../../infra/devops/deploy-app-service.yml'
parameters:
dependsOn: ['iac']
...
appName: ${{variables.appName}}
useDeploymentSlots: true
而 deploy-azure-reosurces.yml 看起来大致如下:
jobs:
- job: detect_iac_changes
displayName: 'Detect IaC changes'
steps:
- checkout: self
fetchDepth: 2
- task: PowerShell@2
name: detection
displayName: 'Detect bicep file changes'
inputs:
targetType: 'inline'
script: |
if ('${{ parameters.forceIaC }}' -eq 'true') {
Write-Host "ForceIaC is enabled. Skipping detection."
Write-Host "##vso[task.setvariable variable=shouldDeployIaC;isOutput=true]true"
return
}
$bicepChanges = git diff --name-only HEAD~1 HEAD | Where-Object { $_ -eq '${{ parameters.bicepFile }}' }
if ($bicepChanges) {
Write-Host "Bicep file '${{ parameters.bicepFile }}' has changed."
Write-Host "##vso[task.setvariable variable=shouldDeployIaC;isOutput=true]true"
} else {
Write-Host "No changes detected in '${{ parameters.bicepFile }}'. Skipping deployment."
Write-Host "##vso[task.setvariable variable=shouldDeployIaC;isOutput=true]false"
}
- job: iac
displayName: 'Deploy IaC'
dependsOn: detect_iac_changes
condition: eq(dependencies.detect_iac_changes.outputs['detection.shouldDeployIaC'], 'true')
steps:
- checkout: self
- task: AzureResourceManagerTemplateDeployment@3
displayName: 'Run bicep file'
inputs:
deploymentScope: 'Subscription'
connectedServiceName: '${{ parameters.serviceConnection }}'
location: 'westeurope'
csmFile: '${{ parameters.bicepFile }}'
overrideParameters: '-environmentCode ${{ parameters.environmentCode }}'
- task: PowerShell@2
displayName: 'Purge Cache'
inputs:
targetType: 'inline'
script: |
az cache purge
而 deploy-app-service.yml 看起来大致如下:
parameters:
- name: dependsOn
type: object
default: []
- name: environmentName
displayName: 'Environment name'
default: ''
- name: jobName
displayName: 'Name of the deployment job'
default: 'deploy'
jobs:
- deployment: ${{ parameters.jobName }}
environment: ${{ parameters.environmentName }}
dependsOn: ${{ parameters.dependsOn }}
strategy:
runOnce:
...
我猜这与 dependsOn: ['iac'] 有关,但我并不确定需要做出哪些不同的改动,才能让被跳过的作业也被视作依赖来“接受”?
解决方案
我在你分享的流水线代码中没有看到任何条件。
要实现这一点,你需要使用 condition 属性。
下面我给出主流水线及用于提供条件执行值的子流水线:
return-false.yml
jobs:
- job: ReturnFalse
steps:
- bash: |
echo "##vso[task.setvariable variable=result;isOutput=true]false"
name: setOutput
return-true.yml
jobs:
- job: ReturnTrue
steps:
- bash: |
echo "##vso[task.setvariable variable=result;isOutput=true]true"
name: setOutput
dummy.yml
steps:
- bash: |
echo 'Dummy hello world'
name: dummyPrint
main.yml - 这个文件使用上述文件,然后按条件执行作业或其他流水线脚本:
trigger: none
jobs:
- template: return-true.yml
- job: Step1
dependsOn: ReturnTrue
variables:
shouldRun: $[ dependencies.ReturnTrue.outputs['setOutput.result'] ]
steps:
- bash: echo "This runs only when value is true - should be printed"
condition: eq(variables['shouldRun'], 'true')
- bash: echo "This step always runs"
- job: DummyConditionalStepShouldRun
dependsOn: Step1
condition: eq(dependencies.ReturnTrue.outputs['setOutput.result'], 'true')
steps:
- template: dummy.yml
- template: return-false.yml
- job: Step2
dependsOn: ReturnFalse
variables:
shouldRunForStep2: $[ dependencies.ReturnFalse.outputs['setOutput.result'] ]
steps:
- bash: echo "This runs only when value is true - should NOT be printed"
condition: eq(variables['shouldRunForStep2'], 'true')
- bash: echo "This step always runs"
- job: DummyConditionalStepShouldNOTRun
dependsOn: Step2
condition: eq(dependencies.ReturnFalse.outputs['setOutput.result'], 'true')
steps:
- template: dummy.yml
- job: AlwaysRunJob
dependsOn: [Step2, Step1]
condition: always()
steps:
- bash: echo "This job always runs"
为了完整起见,你也可以互换使用 if:
parameters:
- name: message
type: string
steps:
- script: echo Hello ${{parameters.message}}
- ${{ if ne(parameters.message, 'Production') }}:
- script: |
echo This step only runs if parameter passed was different than 'Production'
- script: |
echo This step only runs if parameter passed was different than 'Production'
condition: ne('${{ parameters.message }}', 'Production')
编辑
在你更新之后,下面是对我有用的设置。在你的脚本中,我没有看到主文件中声明参数:
parameters:
- name: testFlag
type: string
对我有用的一个示例:
jobs:
- job: check_flag
displayName: 'Check flag'
steps:
- task: PowerShell@2
name: check
displayName: 'Check flag'
inputs:
targetType: 'inline'
script: |
if ('${{ parameters.testFlag }}' -eq 'true') {
Write-Host "param is true: ${{ parameters.testFlag }}"
} else {
Write-Host "param is different from true: ${{ parameters.testFlag }}"
}
以及来自 main.yml 的用法
parameters:
- name: testFlag
type: string
...
- template: dummy-with-param.yml
parameters:
testFlag: ${{ parameters.testFlag }}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。