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

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

我知道我可以使用 Jenkinsfile 做提示,但是我真的不知道如何实现这个工作的重试机制。

我希望能够点击失败的阶段,并选择重试。 jenkins-pipelines-with-stages

86603 次浏览

You should be able to combine retry + input to do that Something like that

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'
}
}
}

you could also use timeout for the input if you want it to finish if nobody validates. There is also waitUntil that might be useful but i haven't used it yet

Edit : WaitUntil seems definitely the best, you should play with it a bit but something like that is cleaner :

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

By the way, there is doc all of the steps here https://jenkins.io/doc/pipeline/steps

This gist (not mine) was one of the better options that I found while trying to implement this functionality too. https://gist.github.com/beercan1989/b66b7643b48434f5bdf7e1c87094acb9

Changed it to a method in a shared library that just did retry or abort for my needs. Also added a max retries and made the timeout variable so that we could change it depending on the job or stage that needs it.

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;
}
}
}
}
}

Example usage with a max of 2 retries that waits for 60s for input.

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)
}

Just remember to put nodes inside of the closure so that waiting for an input doesn't block an executor.

If you have the paid jenkins enterprise Cloudbees has a Checkpoint plugin that can better handle this, but it is not planned to be release for open source Jenkins (JENKINS-33846).

This one with a nice incremental wait

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'
}
}