Как реализовать опцию повтора для неудачных этапов в трубопроводах Дженкинса?
У меня есть файл Jenkins с несколькими этапами, и один из них на самом деле является другим заданием (развернуть его), которое может в некоторых случаях потерпеть неудачу.
Я знаю, что могу делать подсказки с помощью Jenkinsfile, но я действительно не знаю, как реализовать механизм повтора для этой работы.
Я хочу, чтобы можно было нажать на неудавшийся этап и выбрать повторить попытку.
![jenkins-pipelines-with-steps]()
Ответы
Ответ 1
Вы должны иметь возможность комбинировать попытку + ввод, чтобы сделать это
Что-то вроде этого
stage('deploy-test') {
try {
build 'yourJob'
} catch(error) {
echo "First build failed, let 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
Ответ 2
Этот gist (не мой) был одним из лучших вариантов, которые я нашел, пытаясь реализовать эту функциональность тоже. 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).