76 lines
1.6 KiB
Groovy
76 lines
1.6 KiB
Groovy
import groovy.transform.Field
|
|
|
|
public static @Field GLOBAL_RETRIES_ENABLED = false
|
|
public static @Field MAX_GLOBAL_RETRIES = 1
|
|
public static @Field CURRENT_GLOBAL_RETRIES = 0
|
|
public static @Field FLAKY_FAILURES = []
|
|
|
|
def setMax(max) {
|
|
retryable.MAX_GLOBAL_RETRIES = max
|
|
}
|
|
|
|
def enable() {
|
|
retryable.GLOBAL_RETRIES_ENABLED = true
|
|
}
|
|
|
|
def enable(max) {
|
|
enable()
|
|
setMax(max)
|
|
}
|
|
|
|
def haveReachedMaxRetries() {
|
|
return retryable.CURRENT_GLOBAL_RETRIES >= retryable.MAX_GLOBAL_RETRIES
|
|
}
|
|
|
|
def getFlakyFailures() {
|
|
return retryable.FLAKY_FAILURES
|
|
}
|
|
|
|
def printFlakyFailures() {
|
|
catchError {
|
|
def failures = getFlakyFailures()
|
|
|
|
if (failures && failures.size() > 0) {
|
|
print "This build had the following flaky failures:"
|
|
failures.each {
|
|
print "\n${it.label}"
|
|
buildUtils.printStacktrace(it.exception)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
def call(label, Closure closure) {
|
|
if (!retryable.GLOBAL_RETRIES_ENABLED) {
|
|
closure()
|
|
return
|
|
}
|
|
|
|
try {
|
|
closure()
|
|
} catch (ex) {
|
|
if (haveReachedMaxRetries()) {
|
|
print "Couldn't retry '${label}', have already reached the max number of retries for this build."
|
|
throw ex
|
|
}
|
|
|
|
retryable.CURRENT_GLOBAL_RETRIES++
|
|
buildUtils.printStacktrace(ex)
|
|
unstable "${label} failed but is retryable, trying a second time..."
|
|
|
|
def JOB = env.JOB ? "${env.JOB}-retry" : ""
|
|
withEnv([
|
|
"JOB=${JOB}",
|
|
]) {
|
|
closure()
|
|
}
|
|
|
|
retryable.FLAKY_FAILURES << [
|
|
label: label,
|
|
exception: ex,
|
|
]
|
|
|
|
unstable "${label} failed on the first attempt, but succeeded on the second. Marking it as flaky."
|
|
}
|
|
}
|