How to perform actions for failed builds in Jenkinsfile - groovy

Is there a way to perform cleanup (or rollback) if the build in Jenkinsfile failed?
I would like to inform our Atlassian Stash instance that the build failed (by doing a curl at the correct URL).
Basically it would be a post step when build status is set to fail.
Should I use try {} catch ()? If so, what exception type should I catch?

Since 2017-02-03, Declarative Pipeline Syntax 1.0 can be used to achieve this post build step functionality.
It is a new syntax for constructing Pipelines, that extends Pipeline with a pre-defined structure and some new steps that enable users to define agents, post actions, environment settings, credentials and stages.
Here is a sample Jenkinsfile with declarative syntax:
pipeline {
agent label:'has-docker', dockerfile: true
environment {
GIT_COMMITTER_NAME = "jenkins"
GIT_COMMITTER_EMAIL = "jenkins#jenkins.io"
}
stages {
stage("Build") {
steps {
sh 'mvn clean install -Dmaven.test.failure.ignore=true'
}
}
stage("Archive"){
steps {
archive "*/target/**/*"
junit '*/target/surefire-reports/*.xml'
}
}
}
post {
always {
deleteDir()
}
success {
mail to:"me#example.com", subject:"SUCCESS: ${currentBuild.fullDisplayName}", body: "Yay, we passed."
}
failure {
mail to:"me#example.com", subject:"FAILURE: ${currentBuild.fullDisplayName}", body: "Boo, we failed."
}
}
}
The post code block is what handles that post step action
Declarative Pipeline Syntax reference is here

I'm currently also searching for a solution to this problem. So far the best I could come up with is to create a wrapper function that runs the pipeline code in a try catch block. If you also want to notify on success you can store the Exception in a variable and move the notification code to a finally block. Also note that you have to rethrow the exception so Jenkins considers the build as failed. Maybe some reader finds a more elegant approach to this problem.
pipeline('linux') {
stage 'Pull'
stage 'Deploy'
echo "Deploying"
throw new FileNotFoundException("Nothing to pull")
// ...
}
def pipeline(String label, Closure body) {
node(label) {
wrap([$class: 'TimestamperBuildWrapper']) {
try {
body.call()
} catch (Exception e) {
emailext subject: "${env.JOB_NAME} - Build # ${env.BUILD_NUMBER} - FAILURE (${e.message})!", to: "me#me.com",body: "..."
throw e; // rethrow so the build is considered failed
}
}
}
}

I manage to solve it by using try:finally. In case of this stage raises an error the stage will be red and finally run the code but if the stage is okay, the stage will be green and finally will run too.
stage('Tests'){
script{
try{
sh """#!/bin/bash -ex
docker stop \$(docker ps -a -q)
docker rm \$(docker ps -a -q)
export DOCKER_TAG=${DOCKER_TAG}
docker-compose -p ${VISUAL_TESTING_PROJECT_TAG} build test
docker-compose -p ${VISUAL_TESTING_PROJECT_TAG} up --abort-on-container-exit --exit-code-from test
"""
}
finally{
sh """#!/bin/bash -ex
export DOCKER_TAG=${DOCKER_TAG}
docker-compose -p ${VISUAL_TESTING_PROJECT_TAG} down
"""
}
}
}

Related

How to get session data in jenkins delarative piepline

I dont want to used from CurrentBuild or CurrentUser because this return the user information that who build the job , but i wnat to get the user information that login to jenkins.
for example the job X run by timer and the one user will aborted this , i want to found that which user aborted this job .
you can use the below code. pay attention when you want to execute this code you have to permit to run these methods by go to " manage Jenkins/in process script Approval" and approve them to be executable. by using this code you can get whom aborted Jenkins pipeline not only in manually running job also in running by timer.
pipeline {
agent any
triggers{cron("*/1 * * * *")}
stages {
stage('Hello') {
steps {
sleep(20000)
echo 'Hello World'
}
}
}
post{
aborted{
script{
def causee = ''
def actions = currentBuild.getRawBuild().getActions(jenkins.model.InterruptedBuildAction)
for (action in actions) {
def causes = action.getCauses()
// on cancellation, report who cancelled the build
for (cause in causes) {
causee = cause.getUser().getDisplayName()
cause = null
}
causes = null
action = null
}
actions = null
echo causee
}
}
}
}

get error code from called devenv.exe in jenkins pipeline

I just try to erase all Freestyle Jobs from our Jenkins Server. Therefore I call our VS builds directly from the Pipeline job:
bat """chcp 1252 & "PATHTOVS\\devenv.com" /rebuild Release^|$buildBranch $WORKSPACE\\SOLUTION.sln >> ${buildBranch}_$CPNUM_PARAM.txt"""
Now I am wondering how to differentieate between the three Build States (SUCCESS/UNSTABLE/FAILED). Until now I am using a try/catch block. But this isnt very clean and also does not provides the UNStABLE state.
try{
#buildcall
state = 'SUCCESS'
}catch(e){
state = 'FAILED'
}
Unfortuantely I am not sure which error codes from devenv.exe can be retrieved and how to perform this.
Solved it the following way:
try{
//do something
}
}catch(e){
String error = "${e}"
println error
}

Stage final after fail the pipeline-jenkins

I have a pipeline-jenkins also I use a jenkinsfile with several stage, How can I do If in a stage the pipeline fail after that a stage is exacuted? For instance to stop and remove several docker container.
Thanks
try/catch to get the error, finally block to do the "final" stage ?
try {
stage name: "something":
} catch (err) {
// handle errors here ?
} finally {
stage name: "cleanup"
}

try/catch/finally masks Jenkinsfile problems in case of groovy compiler exceptions

I have code similar to the one below in my Jenkinsfile:
node {
checkout scm
// do some stuff
try {
// do some maven magic
} catch (error) {
stage "Cleanup after fail"
emailext attachLog: true, body: "Build failed (see ${env.BUILD_URL}): ${error}", subject: "[JENKINS] ${env.JOB_NAME} failed", to: 'someone#example.com'
throw error
} finally {
step $class: 'JUnitResultArchiver', testResults: '**/TEST-*.xml'
}
}
If the above code fails because of some jenkins-pipeline related errors in the try { } (e.g. using unapproved static method) the script fails silently. When I remove the try/catch/finally I can see the errors.
Am I doing something wrong? Shouldn't rethrowing error make the pipeline errors appear in the log?
EDIT:
I've managed to nail down the problem to groovy syntax, when e.g. I use a variable that hasn't been assigned yet.
Example:
echo foo
If foo is not declared/assigned anywhere Jenkins will fail the build and won't show the reason if it is inside the try/catch/finally which rethrows the exception.
This happens when an additional exception is thrown inside the finally block or before the re-throw inside catch. In these cases the RejectedAccessException is swallowed and script-security does not catch it.

Gradle: Why Exec-derived tasks does not see custom project properties?

Say, we have following property set in build.gradle:
ext.PING = "PONG"
Now we create to tasks:
task ping(type: Exec) {
commandLine 'echo', project.hasProperty('PING')
}
task pong() {
doLast {
println project.hasProperty('PING')
}
}
If will run gradle pong we'll see true printed, if we'll run gradle ping we won't.
The question is: How can we resolve such propeties at the moment we are forming commandLine command? The thing is that in doLast or doFirst we'll see evaluated properties but this does not help - commandLine should be formed earlier.
Since the forming of command line arguments happens during the configuration phase, you have to check, whether your ext.PING = "PONG" goes before the ping task. For example, I've tested it with simple build script like:
ext.PING = "PONG"
task ping(type: Exec) {
commandLine 'echo', project.hasProperty('PING')
}
The result of echo is true, but for:
task ping(type: Exec) {
commandLine 'echo', project.hasProperty('PING')
}
ext.PING = "PONG"
Result is false.
You have to check, have you set this property before the ping task configuration. As for doFirst and doLast, they are executed during execution phase, that means, that all configurations are done and property exists.

Resources