Gitlab CI:如何仅在存在指定制品时启用Apply阶段?
可行的实现方式
1. 动态子流水线(Dynamic Child Pipelines)
这是最贴合你需求的方案,核心逻辑是让Plan阶段根据是否检测到变更,动态生成对应的CI配置文件,再触发子流水线:
- 在Terraform Plan阶段的脚本里,完成Plan操作后判断是否有变更:如果有,就生成包含Apply阶段的CI配置文件;没有变更则生成空配置或者跳过。
terraform plan -out=tfplan # 用jq判断plan输出里是否有资源变更 if terraform show -json tfplan | jq -e '.resource_changes | length > 0' > /dev/null; then # 有变更,生成带Apply阶段的配置 cat > apply-ci.yml << EOF apply: stage: apply needs: ["plan"] script: - terraform apply -auto-approve tfplan artifacts: paths: - tfplan EOF else # 无变更,生成空配置 touch apply-ci.yml fi - 在主
.gitlab-ci.yml的Plan阶段中,添加触发子流水线的配置:plan: stage: plan script: - terraform init - # 上面的Plan及生成apply-ci.yml的脚本 artifacts: paths: - apply-ci.yml - tfplan trigger: include: - artifact: apply-ci.yml job: plan strategy: depend
这样只有当Plan阶段检测到变更时,子流水线才会出现Apply阶段,完全符合你“仅在变更存在时显示Apply阶段”的要求。
2. 手动触发+脚本前置检查
如果不想用子流水线,也可以让Apply阶段始终存在,但通过脚本和手动触发限制执行:
- 把Apply阶段设为手动触发,同时在脚本开头检查Plan阶段生成的变更标记文件是否存在:
apply: stage: apply needs: ["plan"] script: - if [ ! -f ./terraform-change-flag ]; then echo "无基础设施变更,终止执行"; exit 1; fi - terraform apply tfplan when: manual allow_failure: false
这种方式下Apply阶段会一直显示,但如果没有变更标记文件,用户手动触发后会直接失败。缺点是阶段不会隐藏,但能确保只有变更存在时才能成功执行。
3. 修正rules:exists的用法(局限性较大)
你之前禁用了exists语句,其实可以调整用法,但注意它的局限性:GitLab CI在流水线启动时只能检查仓库内的文件,无法预知后续阶段生成的制品文件。不过可以结合needs和dependencies尝试:
apply: stage: apply needs: ["plan"] dependencies: - plan rules: - if: '$CI_PIPELINE_SOURCE == "web"' exists: - ./terraform-change-flag when: manual - when: never
这个方案可靠性不高,因为启动时仓库里不存在这个标记文件,所以更推荐前两种方案,尤其是动态子流水线。
内容的提问来源于stack exchange,提问作者anfieldroad
相关产品推荐
相关产品推荐

