J'ai un Jenkinsfile avec plusieurs étapes et l'un d'eux est en fait un autre travail (le déploiement) qui peut échouer dans certains cas.
Je sais que je peux créer des invites à l'aide de Jenkinsfile, mais je ne sais pas vraiment comment implémenter un mécanisme de nouvelle tentative pour ce travail.
Je veux pouvoir cliquer sur l'étape en échec et choisir de la réessayer.
Vous devriez être capable de combiner les tentatives et les tentatives pour le faire. Quelque chose comme ça
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'
}
}
}
vous pouvez également utiliser timeout pour l'entrée si vous souhaitez que celle-ci se termine si personne ne le valide. Il y a aussi waitUntil qui pourrait être utile mais je ne l'ai pas encore utilisé
Edit: WaitUntil semble définitivement le meilleur, vous devriez jouer avec, mais quelque chose comme ça est plus propre:
stage('deploy-test') {
waitUntil {
try {
build 'yourJob'
} catch(error) {
input "Retry the job ?"
false
}
}
}
A propos, il y a doc toutes les étapes ici https://jenkins.io/doc/pipeline/steps
Ce Gist (pas le mien) était l’une des meilleures options que j’ai trouvées en essayant de mettre en œuvre cette fonctionnalité aussi. https://Gist.github.com/beercan1989/b66b7643b48434f5bdf7e1c87094acb9
Changé en une méthode dans une bibliothèque partagée qui venait juste de réessayer ou d’abandonner pour mes besoins. Nous avons également ajouté un nombre maximal d'essais et créé la variable de délai d'attente afin qu'elle puisse être modifiée en fonction du travail ou de l'étape qui en a besoin.
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;
}
}
}
}
}
Exemple d'utilisation avec un maximum de 2 tentatives en attente d'une attente de 60 secondes.
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)
}
Rappelez-vous simplement de mettre les nœuds à l'intérieur de la fermeture pour que l'attente d'une entrée ne bloque pas un exécuteur.
Si vous avez l'entreprise Jenkins payée, Cloudbees a un plugin Checkpoint qui peut mieux gérer cela, mais il n'est pas prévu de le publier pour Jenkins en open source ( JENKINS-33846 ).
Celui-ci avec une belle attente incrémentale
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'
}
}