-
Improvement
-
Resolution: Duplicate
-
Major
-
None
-
Jenkins ver. 1.656, pipeline 2.0
There doesn't seem to be a safe method of catching errors that might occur while running a shell command without disrupting the normal job stopping process. I would like to be able to catch the error (as it might just be a failing test), log it, and continue running the pipeline script. My main concern is being able to still allow stopping or aborting the pipeline. This would suggest to me that I need to allow exceptions to bubble up if it is due to an abort.
Manually aborting (by pressing red stop button in the gui) will either raise an AbortException or a FlowInterruptedException depending on whether the pipeline is running a shell command or not. This makes it difficult to determine if the shell command failed or a job abort was requested. If a shell command is aborted, the AbortException will at least have a message about an exit code 143. (I think)
To further confuse things, I am wrapping some shell scripts with a timeout step. Timeout also raises FlowInterruptedException but at least the exception will have ExceededTimeout as the cause.
I thought maybe I could look at currentBuild.result but it seems to be always null. I looked at 'catchError' but that doesn't set the result to 'ABORTED' when stopping during a shell command. (It also seems to ignore when a user is trying to abort the job)
Basically, to be able to recover from errors but also allow stopping pipelines, I think I have to use this monstrosity:
onErrorMarkUnstable("sleep step") { // stopping here raises FlowInterruptedException sleep 10 } onErrorMarkUnstable("sleep shell") { node { // error here raises AbortException, stopping here raises AbortException // a script that fails.. we want to be able to log that it failed and continue testing. sh "sleep 10 && false" } } onErrorMarkUnstable("sleep shell with timeout") { // we want to log that it timed out and continue. timeout (time: 5, unit: 'SECONDS') { node { // error here raises AbortException, stopping here raises AbortException, timeout raises FlowInterruptedException sh "sleep 10 && false" } } } echo "last line, done!" def onErrorMarkUnstable(desc, Closure body) { echo "${desc}" try { body.call() } catch (org.jenkinsci.plugins.workflow.steps.FlowInterruptedException e) { def allowInterruption = true; for (int i = 0; i < e.causes.size(); i++) { // white list ExceededTimeout if (e.causes[0] instanceof org.jenkinsci.plugins.workflow.steps.TimeoutStepExecution.ExceededTimeout) { echo "${desc}: An error occured (${e.causes[0]}) marking build as failed." currentBuild.result = "UNSTABLE" allowInterruption = false; } } if (allowInterruption) { throw e; } } catch (hudson.AbortException e) { def m = e.message =~ /(?i)script returned exit code (\d+)/ if (m) { def exitcode = m.group(1).toInteger() if (exitcode >= 128) { throw e; // killed because of abort, letting through } } echo "${desc}: An error occured (${e}) marking build as failed." currentBuild.result = "UNSTABLE" } }
- duplicates
-
JENKINS-28822 Can't distinguish between durable task abort and failure in workflow plugin
- Resolved