Come implementare una strategia di retry nella tua pipeline Jenkins
Implementare una strategia di retry e molto semplice se usi il plugin Naginator su Jenkins. Diventa piu complicato quando si ha a che fare con un job multibranch/multirepo: in quei casi non e possibile configurare il retry come post build action nella configurazione del job. Come si implementa quindi una strategia di retry via codice? In questo articolo mostro alcuni metodi usando la sintassi dichiarativa.
1. Usare solo retry()
retry(count: 3) {
sleep(60)
doSomething()
}
Pro:
- Implementazione semplice
Contro:
- Spreco di RAM. Se vogliamo riprovare dopo 1 minuto perche il progetto dipende da un altro i cui cambiamenti non sono ancora stati pubblicati, il job rimarra attivo per tutto quel tempo anche senza fare nulla
- Se piu job rimangono in attesa del retry contemporaneamente, Jenkins potrebbe superare il numero massimo di build concorrenti. Questo significa che una pipeline avviata dopo, che potrebbe far riuscire il job corrente (ad esempio compilando un progetto da cui dipende), non potra partire, rendendo il tutto inutile
- Non e possibile tenere traccia graficamente di quante volte si e riprovato prima di ottenere un risultato positivo
2. Chiamare un nuovo job
retry(count: 3) {
script {
if (params.retry) {
def jobBuild = build job: "$env.JOB_NAME", parameters: [
booleanParam(name: "retry", value: false)
], wait: true, quietPeriod: 60
params.retry = jobBuild.getResult() != "SUCCESS"
}
}
}
Pro:
- E possibile tenere traccia graficamente di quante volte si e riprovato prima di ottenere un risultato positivo
Contro:
- Stesso problema con la RAM
- Stesso problema con le build concorrenti
3. Chiamare ricorsivamente un nuovo job
Richiamo il job con un parametro che conta il numero di retry. Se viene catturato un errore, viene chiamato un altro job ricorsivamente. Grazie alla ricorsione, non e necessario attendere il completamento del job downstream.
script {
if ("${params.retriesCounter}".toInteger() < 3) {
build job: "$env.JOB_NAME", parameters: [
string(name: "retriesCounter", value: ("${params.retriesCounter}".toInteger() + 1).toString())
], wait: false, quietPeriod: 60
}
}
Pro:
- Operazione piu leggera possibile. I job non occupano RAM mentre attendono di riprovare
- Completamente asincrono: altre pipeline possono girare durante il quietPeriod di un job fallito
- E possibile tenere traccia graficamente di quante volte si e riprovato prima di ottenere un risultato positivo
Contro:
- Ogni job upstream che avvia questa pipeline perde le informazioni sullo stato del job downstream. Esempio:
up-job chiama test-pipeline(0)
test-pipeline(0) lancia e cattura un errore
test-pipeline(0) chiama test-pipeline(1)
test-pipeline(1) completata con successo
test-pipeline(0) completata con fallimento
Anche se test-pipeline e completata con successo dopo un retry, il job upstream che l'ha avviata risulta fallito.
Conclusione
In questo articolo abbiamo discusso diverse strategie per implementare un retry nelle pipeline Jenkins, illustrando pro e contro di ciascuna.