如何在Jenkinsfile中重新触发指定阶段,处理不可逆关键操作场景
可行实现方案
核心思路是结合幂等校验和Jenkins原生的阶段重跑能力,既避免不可逆操作重复执行带来的风险,也满足分阶段重试的需求:
前置配置
- 确保Jenkins安装了
Pipeline: Stage View插件,默认支持从指定阶段重新启动流水线的能力 - 所有不可逆操作前必须加校验逻辑,避免重复执行产生异常
具体实现步骤
1. 阶段1(推送Docker镜像到Artifactory)逻辑改造
推送前先做幂等校验,判断目标路径下是否已存在同tag镜像:
- 镜像已存在:直接跳过推送步骤,标记阶段1执行成功
- 镜像不存在:执行正常推送逻辑
示例代码片段:
stage('推送镜像到Artifactory') { steps { script { def targetImage = "artifactory.xxx.com/your-repo/image:${GIT_COMMIT}" // 校验镜像是否已存在 def imageExist = sh( script: "curl -u ${ARTI_CRED} -s -w '%{http_code}' https://${targetImage.replace(':','/')}/manifest.json -o /dev/null", returnStatus: true ) == 200 if (imageExist) { echo "镜像已存在,跳过推送步骤" } else { echo "开始推送镜像" sh "docker push ${targetImage}" } env.STAGE1_SUCCESS = "true" } } post { failure { echo "阶段1执行失败,可直接重跑当前阶段" } } }
2. 阶段2(合入变更到GitLab master)逻辑改造
执行合并前先校验当前提交是否已合入master分支:
- 提交已存在:直接跳过合并步骤,标记阶段2执行成功
- 提交不存在:执行正常的合并推送逻辑
同时加执行前置判断,只有阶段1成功时才会执行当前阶段:
stage('合入变更到master') { when { expression { env.STAGE1_SUCCESS == "true" } } steps { script { // 校验当前commit是否已在master分支 def commitMerged = sh( script: "git fetch origin master && git branch -r --contains ${GIT_COMMIT} | grep origin/master", returnStatus: true ) == 0 if (commitMerged) { echo "当前提交已合入master,跳过合并步骤" } else { echo "开始合并变更到master" sh """ git checkout master git merge ${GIT_COMMIT} git push origin master """ } } } post { failure { echo "阶段2执行失败,可直接重跑当前阶段,无需重新执行阶段1" } } }
3. 流水线选项配置
在pipeline块中添加preserveStashes()配置,重跑阶段时会保留之前运行生成的环境变量,不需要重新执行前面的阶段就能获取到阶段1的成功标记。
重试逻辑说明
- 阶段1因网络等问题失败:直接在Jenkins界面选择「重跑阶段1」即可,幂等校验会避免重复推送已存在的镜像,成功后自动进入阶段2
- 阶段1成功、阶段2失败:直接选择「重跑阶段2」即可,Jenkins会保留阶段1的成功标记,不会触发阶段1重新执行,幂等校验也会避免重复合并已合入的代码
额外风险防控建议
- 可以在两个阶段执行前各加一个
input人工确认步骤,由负责人确认后再执行不可逆操作,避免误触发 - 镜像tag必须绑定唯一标识(比如commit哈希、构建ID),避免不同构建复用同一个tag导致幂等校验失效
- Artifactory对应仓库开启镜像不可覆盖权限,避免重复推送覆盖旧镜像
内容的提问来源于stack exchange,提问作者Aayush
相关产品推荐
相关产品推荐

