Azure DevOps YAML流水线:Terraform无变更时跳过审批及后续阶段
解决Azure DevOps Terraform流水线无变更时跳过带审批的Apply阶段问题
我之前也碰到过这个头疼的问题——Azure DevOps确实会优先触发关联环境的手动审批,再检查作业/阶段的条件,导致无变更时仍需要人工跳过审批,非常低效。下面是几个经过验证的可行方案:
方案1:阶段级条件控制(最推荐)
核心思路是在Plan阶段输出变更状态变量,然后用阶段级的Condition直接控制整个Apply阶段是否启动,这样当无变更时,Apply阶段根本不会被触发,自然也就不会触发审批。
步骤示例:
在Plan阶段设置输出变量
给Plan阶段的作业命名,然后在检查变更的步骤中输出标记变量:stage: PlanShared jobs: - job: PlanJob name: PlanJob # 必须设置name才能跨阶段传递输出变量 steps: - task: TerraformTaskV4@4 inputs: provider: 'azurerm' command: 'plan' workingDirectory: '$(System.DefaultWorkingDirectory)/shared' commandOptions: '-out=tfplan -detailed-exitcode' - bash: | exit_code=$? # Terraform plan的退出码:0=无变更,2=有变更,其他=失败 if [ $exit_code -eq 2 ]; then echo "##vso[task.setvariable variable=hasSharedChanges;isOutput=true;]yes" elif [ $exit_code -eq 0 ]; then echo "##vso[task.setvariable variable=hasSharedChanges;isOutput=true;]no" else echo "Terraform plan执行失败,退出码:$exit_code" exit $exit_code fi name: CheckChanges condition: succeeded()在Apply阶段添加阶段级Condition
直接用Plan阶段的输出变量控制整个阶段是否运行:stage: ApplyShared dependsOn: PlanShared # 只有当Plan阶段检测到变更时,才启动本阶段 condition: eq(dependencies.PlanShared.outputs['PlanJob.CheckChanges.hasSharedChanges'], 'yes') jobs: - deployment: ApplyShared displayName: 'Apply - shared' environment: 'infra-shared' # 这里的手动审批只会在阶段启动时触发 strategy: runOnce: deploy: steps: - task: TerraformTaskV4@4 inputs: provider: 'azurerm' command: 'apply' workingDirectory: '$(System.DefaultWorkingDirectory)/shared' commandOptions: 'tfplan'
这个方案的优势是逻辑清晰,完全避免了不必要的审批触发,是官方推荐的最佳实践。
方案2:用环境Gate自动检查变更
如果不想修改流水线YAML,可以给目标环境添加入口Gate,让系统自动检查是否有变更,无变更时自动拒绝部署:
- 进入Azure DevOps的「环境」页面,找到
infra-shared环境 - 添加一个「运行脚本」类型的Gate,配置脚本下载
TerraformBuild工件,检查.shared-changes文件是否存在 - 如果文件不存在(无变更),脚本返回非零退出码,Gate自动失败,部署被终止,无需人工干预
这个方案适合需要在环境层面统一管控的场景,但灵活性不如方案1。
方案3:拆分作业流程(临时过渡方案)
如果你暂时无法调整阶段结构,可以拆分Apply阶段的作业:
- 先执行一个检查变更的作业,设置变量
- 部署作业依赖检查作业,同时添加作业级Condition,并且将环境审批移到作业的Gate中(而不是直接关联环境)
不过这个方案不如方案1简洁,仅作为临时过渡使用。
内容的提问来源于stack exchange,提问作者Michael Lihs
相关产品推荐
相关产品推荐

