问题
How do I report the stage in which a declarative pipeline failed? In the fail block, I want to get failedStage.name and report it (eventually to slack).
pipeline {
agent { label 'master'}
stages {
stage('Ok') {
steps {
echo 'do thing'
}
}
stage('NotOK') {
steps {
sh 'make fail'
}
}
}
post {
always {
echo 'ok'
}
failure {
echo 'Failed during Which Stage?'
}
}
}
回答1:
Instead of adding post
section in every stage, I found some solution that shouldn't be working in Declarative Pipeline from my point of view, but it does.
All is you need is to override stage
:
def stage(String name, Closure cl) {
echo "Stage: ${name}"
try {
cl()
} catch (Exception e) {
// I needed to save failed stage and message for parent pipeline job
// so I saved them in environment variables, otherwise it can be saved
// in global variables
if (!env.FAILED_STAGE) {
env.FAILED_STAGE = name
env.FAILED_MESSAGE = e.getMessage()
}
}
}
pipeline {
options { timestamps() }
agent { label 'master' }
stages {
stage('First stage') {
steps {
//Any steps are working
script {
sh "echo first"
}
}
}
stage('Second stage') {
steps {
echo "second"
}
}
stage('Fail stage') {
steps {
error "failed"
}
}
stage('Final stage') {
steps {
build "Other job"
}
}
}
post {
failure {
echo "Failed stage: ${env.FAILED_STAGE}"
echo "Error message: ${env.FAILED_MESSAGE}"
}
}
}
The most strange thing to me is that after stage failure other stages are skipped as they should. Here is the output:
14:05:14 Stage: First stage
[Pipeline] script
[Pipeline] {
[Pipeline] sh
14:05:14 + echo first
14:05:14 first
[Pipeline] }
[Pipeline] // script
[Pipeline] echo
14:05:14 Stage: Second stage
[Pipeline] echo
14:05:14 second
[Pipeline] echo
14:05:14 Stage: Fail stage
[Pipeline] error
[Pipeline] error
[Pipeline] echo
14:05:14 Stage: Final stage
Stage "Final stage" skipped due to earlier failure(s)
[Pipeline] echo
14:05:14 Stage: Declarative: Post Actions
[Pipeline] echo
14:05:14 Failed stage: Fail stage
[Pipeline] echo
14:05:14 Error message: failed
[Pipeline] }
[Pipeline] // timestamps
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
ERROR: failed
Finished: FAILURE
EDIT: Note, that you will lose stage view, as there will be no normal stages from Jenkins point of view.
回答2:
You can use a post
directive in each stage, to act on failure with specific actions and notifications.
It's not exactly ideal as if you want that in all stages you'd have to repeat it though, and I don't think you can access your stage name dynamically, so it's really verbos and hard-coded. You could probably refactor that to use a library though.
pipeline {
agent { label 'master'}
stages {
stage('Ok') {
steps {
echo 'do thing'
}
post {
failure {
echo 'FAILED (in stage OK - should not happen :))'
}
}
}
stage('NotOK') {
steps {
sh 'make fail'
}
post {
failure {
echo 'FAILED (in stage NotOK)'
}
}
}
}
post {
always {
echo 'COMPLETED (global)'
}
failure {
echo 'FAILED (global)'
}
}
}
来源:https://stackoverflow.com/questions/43439093/determine-failed-stage-in-jenkins-declarative-pipeline