如何为 Jenkins 管道中的失败阶段实施重试选项?

Posted

技术标签:

【中文标题】如何为 Jenkins 管道中的失败阶段实施重试选项?【英文标题】:How do I implement a retry option for failed stages in Jenkins pipelines? 【发布时间】:2016-07-25 04:32:17 【问题描述】:

我有一个包含多个阶段的 Jenkinsfile,其中一个实际上是另一项工作(部署工作),在某些情况下可能会失败。

我知道我可以使用 Jenkinsfile 进行提示,但我真的不知道如何为这项工作实施重试机制。

我希望能够点击失败的阶段并选择重试。

【问题讨论】:

此整体功能请求位于 JENKINS-33846。它(令人失望)仅在JENKINS-45455 中被选择用于声明性管道。 【参考方案1】:

您应该能够结合重试 + 输入来做到这一点 类似的东西

stage('deploy-test') 
   try 
     build 'yourJob'
    catch(error) 
     echo "First build failed, let's retry if accepted"
     retry(2) 
        input "Retry the job ?"
        build 'yourJob'
     
   

如果您希望在没有人验证的情况下完成输入,您也可以对输入使用超时。 还有waitUntil可能有用但我还没用过

编辑: WaitUntil 似乎绝对是最好的,你应该玩一下,但这样的东西更干净:

stage('deploy-test') 
   waitUntil 
     try 
       build 'yourJob'
      catch(error) 
        input "Retry the job ?"
        false
     
   

顺便说一句,这里有文档所有步骤https://jenkins.io/doc/pipeline/steps

【讨论】:

会不会加重试提示?我怀疑。 哦,不,你是对的。我会更新我的答案! 是否可以只为重试部分启用超时?我可能想为这项工作设置不同的超时时间。我还没有接受答案,因为我没有找到一个好的解决方案。理想情况下,重试选项应该在作业已经完成之后。想象一下,这项工作是由 PR 上的 GitHub 挂钩触发的。我更愿意在 GitHub 上看到失败,而不是在出现错误时看到没有答案。 在构建管道步骤中使用 waitUntil 进行测试时,我发现我需要显式返回 true,因为该步骤不返回布尔类型。 不再像发布的那样工作,出现错误:未知阶段部分“waitUntil”。从 0.5 版开始,阶段中的步骤必须位于“步骤”块中。【参考方案2】:

这个有很好的增量等待

stage('deploy-test') 
 def retryAttempt = 0
 retry(2) 
    if (retryAttempt > 0) 
       sleep(1000 * 2 + 2000 * retryAttempt)
    

    retryAttempt = retryAttempt + 1
    input "Retry the job ?"
    build 'yourJob'
 

【讨论】:

sleep() 具有 default units of seconds,因此除非您希望第一次等待超过一个小时,否则请指定 sleep(..., unit:"MILLISECONDS") 或使用更少的秒数。 我认为您不能再将retry 放在stage 块的顶部:Expected one of "steps", "stages", or "parallel" for stage "Code Coverage" @ line 423, column 17. 只有在我把它放在steps 声明之后才对我有用。 如果您仅将stage('test') options retry(2) steps echo "hello" 用于声明性管道,我相信您可以将其置于步骤之外【参考方案3】:

这个要点(不是我的)也是我在尝试实现这个功能时发现的更好的选择之一。 https://gist.github.com/beercan1989/b66b7643b48434f5bdf7e1c87094acb9

将其更改为共享库中的一个方法,该方法只是根据我的需要重试或中止。还添加了最大重试次数并设置了超时变量,以便我们可以根据需要它的作业或阶段来更改它。

package com.foo.bar.jenkins

def class PipelineHelper 
    def steps

    PipelineHelper(steps) 
        this.steps = steps
    

    void retryOrAbort(final Closure<?> action, int maxAttempts, int timeoutSeconds, final int count = 0) 
        steps.echo "Trying action, attempt count is: $count"
        try 
            action.call();
         catch (final exception) 
            steps.echo "$exception.toString()"
            steps.timeout(time: timeoutSeconds, unit: 'SECONDS') 
                def userChoice = false
                try 
                    userChoice = steps.input(message: 'Retry?', ok: 'Ok', parameters: [
                            [$class: 'BooleanParameterDefinition', defaultValue: true, description: '', name: 'Check to retry from failed stage']])
                 catch (org.jenkinsci.plugins.workflow.steps.FlowInterruptedException e) 
                    userChoice = false
                
                if (userChoice) 
                    if (count <= maxAttempts) 
                        steps.echo "Retrying from failed stage."
                        return retryOrAbort(action, maxAttempts, timeoutMinutes, count + 1)
                     else 
                        steps.echo "Max attempts reached. Will not retry."
                        throw exception
                    
                 else 
                    steps.echo 'Aborting'
                    throw exception;
                
            
        
    

示例用法,最多 2 次重试,等待 60 秒输入。

def pipelineHelper = new PipelineHelper(this)

stage ('Retry Example')
    pipelineHelper.retryOrAbort(
        node
            echo 'Here is an example'
            throw new RuntimeException('This example will fail.')
        
    , 2, 60)

只要记住将节点放在闭包内,这样等待输入就不会阻塞执行器。

如果你有付费的 jenkins,企业 Cloudbees 有一个 Checkpoint 插件可以更好地处理这个问题,但不打算为开源 Jenkins (JENKINS-33846) 发布。

【讨论】:

正如其他答案所示,通常最好利用 Jenkins 构建 SDL 设施

以上是关于如何为 Jenkins 管道中的失败阶段实施重试选项?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Jenkinsfile 构建 Jenkins 管道没有失败

在 Jenkins 声明式管道中使用 waitForQualityGate

管道中的通道关闭异常

如何为詹金斯管道声明方法定义工作区体积

如何为 jenkins 构建具有多种风格的应用程序设置 dexguard?

问:Gitlab CI 谁重试旧管道