如何确保MR合并时,即使deploy步骤失败on_stop仍能执行?
解决GitLab流水线MR合并时环境销毁失败的边缘场景问题
问题根源
GitLab的on_stop触发逻辑依赖环境处于活跃(active)状态:只有当最后一次部署环境的流水线成功完成,环境标记为active时,MR合并事件才会自动触发on_stop对应的销毁步骤。如果最后一次推送的deploy步骤失败,环境状态会变为failed,此时合并事件不会触发自动销毁。
解决方案
方案1:给销毁步骤添加独立的MR合并触发规则
直接让stop-mr-env步骤在MR合并时强制执行,不依赖on_stop的自动触发逻辑,是最直接有效的方案。
修改stop-mr-env步骤的配置:
stop-mr-env: rules: # 保留原有的on_stop自动触发规则 - if: $CI_ENVIRONMENT_STOP # 新增规则:MR合并时直接触发销毁步骤 - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_STATE == "merged"' exists: - helm/config/values-sandbox.yml extends: - .stop-mr-env-base environment: name: ${MR_ENVIRONMENT} action: stop
无论最后一次deploy步骤是否失败,只要MR完成合并,该规则就会触发环境销毁操作。
方案2:强制deploy失败时环境保持活跃状态
调整deploy-mr-env的配置,让即使部署失败,环境依然标记为active,确保on_stop在合并时能正常触发:
deploy-mr-env: rules: - if: $CI_PIPELINE_SOURCE == 'merge_request_event' exists: - helm/config/values-sandbox.yml extends: - .deploy-mr-env-base variables: HELM_SANDBOX_CONFIGS: >- -f helm/config/values-sandbox.yml -f helm/config/secrets-sandbox.yml environment: name: ${MR_ENVIRONMENT} url: https://${CI_PROJECT_NAME}-mr${CI_MERGE_REQUEST_IID}.sandbox.com on_stop: stop-mr-env state: active # 强制标记环境为活跃状态 allow_failure: true # 允许步骤失败,不终止流水线
注意:该方案需结合GitLab版本验证,部分版本中state: active需配合allow_failure使用,确保流水线不会因deploy失败中断,同时环境保持active状态。
方案3:合并后通过API手动触发环境销毁
如果上述方案不适用,可在合并后的默认分支流水线中添加步骤,调用GitLab API销毁MR环境:
stop-mr-env-post-merge: rules: - if: '$CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' exists: - helm/config/values-sandbox.yml script: # 从合并提交信息中提取MR编号 - export MR_IID=$(echo $CI_COMMIT_MESSAGE | grep -o 'Merge !\d\+' | grep -o '\d\+') - export MR_ENVIRONMENT="mr-${MR_IID}" # 调用GitLab API停止环境 - curl --request POST --header "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/environments/${MR_ENVIRONMENT}/stop"
需提前在项目变量中配置GITLAB_API_TOKEN(需拥有环境操作权限)。
推荐方案
优先选择方案1,无需依赖API或调整deploy的失败处理逻辑,仅通过规则扩展就能覆盖边缘场景,实现最可靠的环境销毁触发。
内容的提问来源于stack exchange,提问作者jimjim
相关产品推荐
相关产品推荐

