Jenkins构建管道 - 在阶段重新启动

thr*_*eez 29 jenkins jenkins-workflow jenkins-pipeline

我将以下构建管道设置为作业:

Stage 1 - verify all dependencies exist
Stage 2 - build the new jar
Stage 3 - Run integration tests
Stage 4 - Deploy to staging environment (manual step)
Stage 5 - Deploy to production environment (manual step)
Run Code Online (Sandbox Code Playgroud)

我正在寻找一种方法,以便在发生瞬态故障时从特定阶段启动构建管道.例如,假设用户单击以部署到生产时出现网络问题.我不认为从第1阶段启动管道是有意义的......我想再次尝试这一步并继续从那里开始.我没有在Build Pipeline Plugin中看到这样的任何功能.

谢谢!!

tar*_*oga 13

我认为checkpoint这就是你要找的.不幸的是,它仅适用于CloudBees Jenkins Enterprise套件,而不是免费版本.

让我们希望它成为开源版本,因为它似乎是一个非常常见的用例.


ole*_*enz 9

同时,许多其他答案已过时,因为Jenkins提供了内置的解决方案,可让您从任何阶段重新启动作业:https : //jenkins.io/doc/book/pipeline/running-pipelines/适用于声明式仅通过管道

  • 这很好,但似乎没有为脚本管道启用,仅声明性 (5认同)

ole*_*enz 8

一个更好的解决方案是类似于我在这个问题中建议的解决方案:

编写一个在单个阶段周围有"if"保护的流水线脚本,如下所示:

stage "s1"
if (theStage in ["s1"]) {
    sleep 2
}

stage "s2"
if (theStage in ["s1", "s2"]) {
    sleep 2
}

stage "s3"
if (theStage in ["s1", "s2", "s3"]) {
    sleep 2
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以创建一个使用此脚本的"主"作业,并通过将参数"theStage"设置为"s1"来立即运行所有阶段.这项工作将在所有阶段一次运行时收集统计数据,并为您提供有用的估算时间.

此外,您可以创建一个使用此脚本的"部分运行"作业,并使用您要开始的阶段进行参数化.但估计不会很有用.


Ste*_*ing 6

您可以将代码包装在一个retry步骤中:

stage "Deployment"
retry(3) {
  sh "deploy.."
}
Run Code Online (Sandbox Code Playgroud)

编辑:这可能对 Jenkins 的免费版本有所帮助。CloudBees Enterprise的用户,请参阅@tarantoga的回答。


Mar*_* Ba 5

这是另一个有条件地运行阶段而不破坏舞台视图插件历史记录的草图。

他们说的那样:

动态阶段:一般来说,如果要可视化动态变化的阶段,请有条件地执行阶段内容,而不是有条件地包含阶段

这是我到目前为止所想到的。似乎大部分工作:(只需忽略其他虚拟步骤)

我们定义了一个小conditionalStage辅助函数,它巧妙地封装了JP_STAGEJenkins Job 参数的阶段名称检查。

请注意如何conditionalStage 首先打开stage然后stageIsActive在阶段内进行检查,只是跳过所有步骤。这样,舞台视图插件就可以看到所有阶段,因此不会混乱,但阶段的步骤仍然会被跳过。

def stageSelect = JP_STAGE.toLowerCase()

// test if stage or any of sub-stages is active
def stageIsActive(theStage, theStages) { 
    // echo "pass: $theStages"
    // ARGL: https://issues.jenkins-ci.org/browse/JENKINS-26481
    // def lcStages = theStages.collect {it.toLowerCase()}
    def lcStages = []
    for (def s : theStages) { lcStages += s.toLowerCase() }
    def lcAllStages = lcStages + ['all']
    // echo "check: $lcAllStages"
    // echo JP_STAGE.toLowerCase()
    if (JP_STAGE.toLowerCase() in lcAllStages) {
        echo "Run: Stage '$theStage' is active through '$JP_STAGE'."
        return true
    } else {
        echo "Skip: Stage '$theStage' is NOT active through '$JP_STAGE'."
        return false
    }
}

// 1st element should be the stage, optionally followed by all sub-stages
def conditionalStage(names, stageBody) {
  stage(names[0]) { if (stageIsActive(names[0], names)) {
    stageBody()
  }}  
}

timestamps {
// --S--

conditionalStage(['Intro']) { 
    echo 'Outside Node'

    build job: 'FreeX', wait: true
    sleep 3
}

// --S--
conditionalStage(['AtNode', 'Hello', 'Done']) {
    node {
        // Cloudbees Enterprise Only: checkpoint 'Now'
        conditionalStage(['Hello']) {
            echo 'Hello World @ Node'
            sleep 4
        }
        conditionalStage(['Done']) {
            dir('C:/local') {
                echo pwd()
            }
        }
    }
}

}//timestamps
Run Code Online (Sandbox Code Playgroud)