Post failure block in Jenkinsfile is not working - jenkins

I'm trying a post failure action with a parallel step but it never works.
This is my Jenkinsfile:
pipeline {
agent any
stages {
stage("test") {
steps {
withMaven(
maven: 'maven3', // Maven installation declared in the Jenkins "Global Tool Configuration"
mavenSettingsConfig: 'maven_id', // Maven settings.xml file defined with the Jenkins Config File Provider Plugin
mavenLocalRepo: '.repository')
{
// Run the maven build
sh "mvn --batch-mode release:prepare -Dmaven.deploy.skip=true" --> it will always fail
}
}
}
stage("testing") {
steps {
parallel (
phase1: { sh 'echo phase1' },
phase2: { sh "echo phase2" }
)
}
}
}
post {
failure {
echo "FAIL"
}
}
}
But the post failure action here is a bit useles... I don´t see it any place.
Thanks to all!
Regards

I've found the issue, after several hours of searching. What you are missing (and I was missing too) is the catchError section.
pipeline {
agent any
stages {
stage('Compile') {
steps {
catchError {
sh './gradlew compileJava --stacktrace'
}
}
post {
success {
echo 'Compile stage successful'
}
failure {
echo 'Compile stage failed'
}
}
}
/* ... other stages ... */
}
post {
success {
echo 'whole pipeline successful'
}
failure {
echo 'pipeline failed, at least one step failed'
}
}
You should wrap every step that can potentially fail into a catchError function. What this does is:
If an error occurs...
... set build.result to FAILURE...
... and continue the build
The last point is important: your post{ } blocks did not get called because your entire pipeline was aborted before they even had a chance to execute.

Just in case someone else also made the same stupid mistake I did, don't forget the post block needs to be inside the pipeline block.
i.e. This is apparently valid, but (obviously) won't work:
pipeline {
agent { ... }
stages { ... }
}
// WRONG!
post {
always { ... }
}
This is what's correct:
pipeline {
agent { ... }
stages { ... }
post {
always { ... }
}
}

Related

Continuous Integration pipeline

I am looking to trigger the on_failure step in my pipeline. I have a very simple script.
2 resources and 1 job. The job has a run step in which I would like to trigger failure manually. I have tried many things and they all leaded to an error.
Is there an shell script exit code that could make the task to fail and not being errored
Triggering post → failure and not failing the build is not possible:
failure
Only run the steps in post if the current Pipeline’s or stage’s run has a "failed" status, typically denoted by red in the web UI.
However, you can do the following:
def status
pipeline {
agent any
stages {
stage('Failing stage') {
steps {
script {
status = sh script: 'exit 99', returnStatus: true
}
}
}
}
post {
always {
script {
if ( status == 99 )
echo 'Script failed...'
else
echo 'Script succeeded...'
}
}
}
}
Example post -> failure
post {
always {
cleanWs()
}
success {
sendEmail('SUCCESSFUL')
}
unstable {
sendEmail('UNSTABLE')
}
failure {
sendEmail('FAILED')
}
}

Conditional post section in Jenkins pipeline

Say I have a simple Jenkins pipeline file as below:
pipeline {
agent any
stages {
stage('Test') {
steps {
sh ...
}
}
stage('Build') {
steps {
sh ...
}
}
stage('Publish') {
when {
buildingTag()
}
steps {
sh ...
send_slack_message("Built tag")
}
}
}
post {
failure {
send_slack_message("Error building tag")
}
}
}
Since there's a lot non-tag builds everyday, I don't want to send any slack message about non-tag builds. But for the tag builds, I want to send either a success message or a failure message, despite of which stage it failed.
So for the above example, I want:
When it's a tag build, and stage 'Test' failed, I shall see a "Error building tag" message. (This is a yes in the example)
When it's a tag build, and all stages succeeded, I shall see a "Built tag" message. (This is also a yes in the example)
When it's not a tag build, no slack message will ever been sent. (This is not the case in the example, for example, when the 'Test' stage fails, there's will be a "Error building tag" message)
As far as I know, there's no such thing as "conditional post section" in Jenkins pipeline syntax, which could really help me out here. So my question is, is there any other way I can do this?
post {
failure {
script {
if (isTagBuild) {
send_slack_message("Error building tag")
}
}
}
}
where isTagBuild is whatever way you have to differentiate between a tag or no tag build.
You could also apply the same logic, and move send_slack_message("Built tag") down to a success post stage.
In the postbuild step you can also use script step inside and use if. And inside this if step you can add emailext plugin.
Well, for those who just want some copy-pastable code, here's what I ended-up with based on #eez0's answer.
pipeline {
agent any
environment {
BUILDING_TAG = 'no'
}
stages {
stage('Setup') {
when {
buildingTag()
}
steps {
script {
BUILDING_TAG = 'yes'
}
}
}
stage('Test') {
steps {
sh ...
}
}
stage('Build') {
steps {
sh ...
}
}
stage('Publish') {
when {
buildingTag()
}
steps {
sh ...
}
}
}
post {
failure {
script {
if (BUILDING_TAG == 'yes') {
slackSend(color: '#dc3545', message: "Error publishing")
}
}
}
success {
script {
if (BUILDING_TAG == 'yes') {
slackSend(color: '#28a745', message: "Published")
}
}
}
}
}
As you can see, I'm really relying on Jenkins built-in buidingTag() function to help me sort things out, by using an env-var as a "bridge". I'm really not good at Jenkins pipeline, so please leave comments if you have any suggestions.

Post directive at pipeline level of jenkins declarative pipeline does not get executed on failure

Below is the skeleton of my Jenkinsfile. The post directive is executed on success but not in case of failure. Is this the expected behavior of jenkins?
Thanks
#!/usr/bin/env groovy
pipeline {
agent {
node { label 'ent_linux_node' }
}
stages {
stage('Prepare'){
steps {
//some steps
}
}
stage('Build') {
steps {
//Fails at this stage
}
}
stage('ArtifactoryUploads') {
steps {
//skips since previous stage failed
}
}
}
post {
always {
//Doesn't get executed but I am expecting it to execute
}
}
}

Declarative pipeline to check the build step = Failure then trigger next build step, but not fail the job.

I am trying to fail a build step in Jenkinsfile with failed results = failure. Once the step is failed it triggers my rollback job. Tried many different things, but had no luck. Any help would be greatly appreciated.
pipeline {
agent any
stages {
stage('Git Checkout') {
steps {
script {
git 'somegit-repo'
sh'''
mvn package
'''
echo currentBuild.result
catchError {
build 'rollback'
}
}
}
}
}
One way is to use a shell script and with exit 1 statement
e.g.
sh "exit 1"
Or you can use error step
error('Failing build because...')
See https://jenkins.io/doc/pipeline/steps/workflow-basic-steps/#error-error-signal
Use a try catch block
node {
stage("Run scripts") {
try {
<some command/script>
} catch (error) {
<rollback command/script>
}
}
}
Thank you so much. This seems to work!
stages {
stage("some test") {
steps{
script {
git 'mygitrepo.git'
try {
sh''' mvn test '''
} catch (error) {
script {
def job = build job: 'rollback-job'
}
}
}
}
}
If you check the cleaning and notifications page
You can do a post step and get rid of all the try/catch stuff and get a cleaner Jenkinsfile
pipeline {
agent any
stages {
stage('No-op') {
steps {
sh 'ls'
}
}
}
post {
always {
echo 'One way or another, I have finished'
deleteDir() /* clean up our workspace */
}
success {
echo 'I succeeeded!'
}
unstable {
echo 'I am unstable :/'
}
failure {
echo 'I failed :('
}
changed {
echo 'Things were different before...'
}
}
}

How can I catch any pipeline error in Jenkins?

I have a Jenkins pipeline script that for the most part works fine and I surround most things that will fire a fatal error with try catches. However from time to time really unexpected things happen and I'd like to be able to have a safe catch-all available to do some final reporting before failing the build.
Is there no final default 'stage' I can define that runs whenever an error isn't caught?
Although already been answered for a scripted pipeline I would like to point out that for a declarative pipeline this is done with a post section:
pipeline {
agent any
stages {
stage('No-op') {
steps {
sh 'ls'
}
}
}
post {
always {
echo 'One way or another, I have finished'
deleteDir() /* clean up our workspace */
}
success {
echo 'I succeeeded!'
}
unstable {
echo 'I am unstable :/'
}
failure {
echo 'I failed :('
}
changed {
echo 'Things were different before...'
}
}
}
Each stage can also have it's own section when required.
You can do it by wrapping all your build stages in a big try/catch/finally {} block, for example:
node('yournode') {
try {
stage('stage1') {
// build steps here...
}
stage('stage2') {
// ....
}
} catch (e) {
// error handling, if needed
// throw the exception to jenkins
throw e
} finally {
// some common final reporting in all cases (success or failure)
}
}

Resources