You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jenkins:当流水线被Milestone中止时将构建状态改为SUCCESS

解决Jenkins构建因Milestone标记为NOT_BUILT的问题

我完全理解你的痛点:那些停在INT阶段的构建明明测试全过、部署成功,却因为后续执行的milestone()被标记为灰色(NOT_BUILT),确实会让团队成员困惑。下面是针对你的场景的具体解决方案:

核心思路

问题的根源在于milestone()的默认行为:当新构建到达某个里程碑时,所有未到达该里程碑的未完成旧构建会被自动中止并标记为NOT_BUILT。你的流水线中milestone()放在PRE审批之后,导致停留在审批阶段的构建(未到达该里程碑)会被后续构建影响。

我们可以通过两个关键调整解决这个问题:

  1. 将里程碑前置到INT部署完成后,确保所有完成INT部署的构建都通过第一个里程碑,后续构建不会影响它们的状态。
  2. 在审批被中止/超时时,主动将构建状态设置为SUCCESS并结束流水线,避免构建处于“未完成”状态。

具体代码修改

1. 调整里程碑位置(INT部署后)

首先,在完成INT部署后添加第一个里程碑,确保所有成功部署到INT的构建都标记为“已通过该阶段”:

stage('Deploy to INT') {
    steps {
        echo 'Executing INT deployment...'
        // 这里是你的INT部署逻辑
    }
    post {
        success {
            // 只有INT部署成功才标记里程碑
            milestone(label: 'INT Deployment Completed')
        }
    }
}

2. 修改PRE审批阶段代码

在审批被中止或超时时,主动设置构建状态为SUCCESS,并结束流水线:

/************** PRE **************/
stage('Approval for PRE') {
    def approvalGranted = false
    try {
        timeout(time: approvalTime, unit: approvalTimeUnit) {
            input message: 'Do you approve the deployment to PRE?', ok: 'Approve'
            approvalGranted = true
        }
    } catch (Exception ex) {
        echo "PRE approval skipped: ${ex.getMessage()}"
        // 标记构建为SUCCESS,因为INT部署已完成且测试通过
        currentBuild.result = 'SUCCESS'
        // 自定义构建名称,方便团队识别是仅INT部署的构建
        currentBuild.displayName = "${currentBuild.displayName} (INT Only)"
        return
    }

    if (!approvalGranted) {
        currentBuild.result = 'SUCCESS'
        currentBuild.displayName = "${currentBuild.displayName} (INT Only)"
        return
    }
}

// 仅审批通过才执行后续PRE部署步骤
if (approvalGranted) {
    stage('Deploy to PRE') {
        steps {
            echo 'Executing PRE deployment...'
            // 你的PRE部署逻辑
        }
        post {
            success {
                milestone(label: 'PRE Deployment Completed')
            }
        }
    }
}

3. PROD审批阶段同理

PROD审批和部署可以复用同样的逻辑,确保未通过审批的构建也保持SUCCESS状态:

stage('Approval for PROD') {
    def approvalGranted = false
    try {
        timeout(time: approvalTime, unit: approvalTimeUnit) {
            input message: 'Do you approve the deployment to PROD?', ok: 'Approve'
            approvalGranted = true
        }
    } catch (Exception ex) {
        echo "PROD approval skipped: ${ex.getMessage()}"
        currentBuild.result = 'SUCCESS'
        currentBuild.displayName = "${currentBuild.displayName} (PRE Only)"
        return
    }

    if (!approvalGranted) {
        currentBuild.result = 'SUCCESS'
        currentBuild.displayName = "${currentBuild.displayName} (PRE Only)"
        return
    }
}

if (approvalGranted) {
    stage('Deploy to PROD') {
        steps {
            echo 'Executing PROD deployment...'
            // 你的PROD部署逻辑
        }
        post {
            success {
                milestone(label: 'PROD Deployment Completed')
            }
        }
    }
}

为什么这个方案有效?

  • 里程碑前置:完成INT部署的构建会通过第一个里程碑,后续构建执行到该里程碑时,只会中止正在执行INT部署的未完成构建,不会影响已经完成INT部署的构建。
  • 主动设置状态:审批被中止时,我们手动将构建状态设为SUCCESS并结束流水线,避免构建处于“未完成”状态,彻底杜绝后续里程碑修改其状态的可能。
  • 自定义构建名称:通过displayName标记仅部署到INT/PRE的构建,让团队一眼就能识别构建的范围,减少困惑。

内容的提问来源于stack exchange,提问作者Patrick T

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:35:51