Grouping post conditions in a Jenkins declarative pipeline - jenkins-pipeline

Is there a way to group post conditions in a Jenkins declarative pipeline ?
For instance, I want to do the same thing for statuses aborted failure and success.
Is there a shorter way to do it than the following ?
post {
aborted { sendNotification(currentBuild.result, "$LIST_NOTIFICATION_JENKINS")
failure { sendNotification(currentBuild.result, "$LIST_NOTIFICATION_JENKINS")
success { sendNotification(currentBuild.result, "$LIST_NOTIFICATION_JENKINS")
}

There is the 'always' condition:
post {
always {sendNotification(currentBuild.result, "$LIST_NOTIFICATION_JENKINS")}
}
The 'always' condition will run regardless of the stage result.
See the documentation on the post section.
If you want a set of common actions between just a few conditions, for example if you wanted to do the same thing for failure and aborted, I would recommend creating a function in your script to call from the failure and aborted post conditions.
You can also do something like the following:
always {
script{
if (currentBuild.currentResult == "ABORTED" || currentBuild.currentResult == "FAILURE")
{
echo "was aborted or failed"
}
}
}

Related

Detect shutting-down-controller in post action in declarative pipeline

I have success, failure and aborted under post in declarative pipeline, is there a way to detect
shutting down controller and perform different actions?
e.g:
post {
success {
// do some actions for successful completion
}
failure {
// do some actions for failure completion
}
aborted {
// do some actions when job gets aborted
}
controller-shutting-down {
echo "Jenkins is shutting down."
}
}
OR:
...
aborted {
if (reason == controller-shutting-down) {
echo "Jenkins is shutting down."
} else {
// do some actions when job gets aborted
}
}
...
Is there a way to acheive this?

parameterized-remote-trigger is throwing 405 exception

I am trying to trigger a job A(this is configured as trigger remote) remotely from another job B, and job B needs to hold until results come back to show success or failure, I initially tried using rest API using curl command, it perfectly works.here's the curl code:
curl -v -X POST 'https://xxx.xxx/xxx-xxx/job/xxx/job/master/buildWithParameters?config_files=./jenkins/unit-tests.json' --user xxxx:110f4dfa33ba8f8ef5d8d299beb6aa1543
I choose parameterized plugin code which installed on Jenkins server because it handles the polling mechanism internally and also has handler friendly methods. please see below code for remoteJob, but it fails with 405 error, that means method not allowed in HTTP language, looks like plugin is using GET method instead of post. I added an option for logging , but it does not seems to be showing more log.
def handle = triggerRemoteJob(
remoteJenkinsName: 'remote-master',
job: 'https://xxx.xxx.com/xxx-xxx/job/xxx/job/master/buildWithParameters',
remoteJenkinsUrl: 'https://xxx.xxx.xxx/xxx-xxx/job/xxx/job/master/buildWithParameters',
auth: TokenAuth(apiToken: hudson.util.Secret.fromString('110f4dfa33ba8f8ef5d8d299beb6aa1543'), userName: 'xxxx'),
parameters: 'config_files=./jenkins/unit-tests')
I am getting following error -
[Pipeline] triggerRemoteJob
##########################################################################
Parameterized Remote Trigger Configuration:
- job: https://xxx.xxx.xxx/xxx-xxx/job/xxx/job/master/buildWithParameters
- remoteJenkinsUrl: https://xxx.xxx.xxx/xxx-xxx/job/ius/job/master/buildWithParameters
- auth: 'Token Authentication' as user 'sseri'
- parameters: [config_files=./jenkins/unit-tests]
- blockBuildUntilComplete: true
- connectionRetryLimit: 5
- trustAllCertificates: false
##########################################################################
Connection to remote server failed [405], waiting to retry - 10 seconds until next attempt. URL: https://xxx.xxx.xxx/xxx-xxx/job/xxx/job/master/buildWithParameters/api/json, parameters:
Retry attempt #1 out of 5
Please help me in this regard!
I am not sure about the plugins you are using, but it's quite simple to implement this scenario "call a downstream job from upstream and fail upstream if the downstream fail" without any plugins.
Take a look at my example below.
let say if you have 2 jobs called jobA and jobB and your goal is to call jobB from jobA and fail the jobA if jobB fail.
**Scripted Pipeline for jobA **
node() {
try {
def jobB = build(job: jobName,parameters: [string(name:"parameterName",value: "parameterValue")])
def jobBStatus = jobB.getResult()
if(jobBStatus == "failed") {
throw new RuntimeException("Downstream job-b failed with reason ...");
}
...
}catch(Exception e) {
throw e
}
}
Declarative Pipeline for jobA
pipeline {
agent any;
stages {
stage('call jobB') {
steps {
script {
def jobB = build(job: jobName,parameters: [
string(name:"parameterName",value: "parameterValue")
])
def jobBStatus = jobB.getResult()
if(jobBStatus == "failed") {
error("Downstream job-b failed with reason ...")
}
}
}
}
}
}
Try using this Parameterized-Remote-Trigger-Plugin. It should give you what you want. I'm having some problems configuring it using authentication tokens and users using Jenkinsfile but if you are using the GUI im sure you will get the job done.

Is there a way to move the entire post {} build section in Jenkinsfile to the global pipeline library?

I'm relatively new to Jenkins pipelines, but having implemented already a few, I've realised I need to start using jenkins shared library before I go mad.
Have already figured out how to define some repetitive steps in the library and call them with less clutter from Jenkinsfile, but not sure if the same thing can be done for the entire post build section (thought I've read about to how to define the entire pipeline in the lib and similar), as this is pretty much static end of every single pipeline code:
#Library('jenkins-shared-library')_
pipeline {
agent none
stages {
stage ('System Info') { agent any
steps { printSysInfo() }
}
stage ('Init'){ agent {label 'WinZipSE'}
steps { init('SCMroot') }
}
stage('Build') { agent any
steps { doMagic() }
}
}
// This entire 'post {}' section needs to go to a shared lib
// and be called just with a simple methed call, e.g.
// doPostBuild()
post {
always {
node ('master') {
googlechatnotification (
message: '[$BUILD_STATUS] Build $JOB_NAME $BUILD_NUMBER has finished',
url: 'id:credential_id_for_Ubuntu')
step (
[$class: 'Mailer',
recipients: 'sysadmins#example.com me#example.com',
notifyEveryUnstableBuild: true,
sendToIndividuals: true]
)
}
}
success {
node ('master') {
echo 'This will run only if successful'
}
}
failure {
node ('master') {
echo 'This will run only if failed'
}
}
// and so on
}
}
I just dunno how to syntactically achieve that. For sure, I can define the entire post build section an a lib/var like: doPotBuild.groovy
def call () {
post {...}
}
but how I will eventually call it from within my Jenkinsfile outside of that defined post {} build block section (AKA stages).
I can call it within some stage('post build){doPostBuild()}, but it won't serve the way how the true post {} section is supposed to work, e.g. it won't get executed it there was failure in one of the previous stages.
Any thoughts on that and mainly working examples?
I am not entirely if this will work as I don't use declarative pipelines, so am unsure how rigid the top level structure is. But I would revert to a script block.
#Library('jenkins-shared-library')_
pipeline {
agent none
stages {
stage ('System Info') { agent any
steps { printSysInfo() }
}
stage ('Init'){ agent {label 'WinZipSE'}
steps { init('SCMroot') }
}
stage('Build') { agent any
steps { doMagic() }
}
}
// This entire 'post {}' section needs to go to a shared lib
// and be called just with a simple methed call, e.g.
// doPostBuild()
script {
doPostBuild()
}
}

exit declarative pipeline prematurely based on script output

While I am aware of this question clean way to exit declarative Jenkins pipeline as success I am to green to understand how to put it to use (from where does the skipBuild variable come?).
I have a script that determines whether the pipeline should continue or not but I am unsure how to piece it together (I am free to construct the script as needed).
pipeline {
agent {
docker { image 'python:3-alpine' }
}
stage('Should I continue') {
steps {
python should_i_continue.py
}
when { ? == true }
stages {
...
}
}
}
I am aware that the capabilities increase tenfold if I use a scripted pipeline but I wonder if it is possible to do what I want with a declarative one?
You can use any custom variable, which you will set as true|false based on some condition in the steps of your pipeline and all stages that need to be executed based on that condition have to have following format:
stage('Should Continue?') {
setBuildStatus("Build complete", "SUCCESS");
when {
expression {skipBuild == true }
}
}
In other words to provide you a bit clean picture, check this abstract example:
node {
skipBuild = false
stage('Checkout') {
...
your checkout code here
...
}
stage('Build something') {
...
some code goes here
skipBuild = true
...
}
stage('Should Continue?') {
setBuildStatus("Build complete", "SUCCESS");
when {
expression {skipBuild == true }
}
}
}

How to tell whether job failed or was aborted

I've got a Jenkins job with a try..catch structure:
try
{
[do work here]
}
catch(err)
{
}
Is there any way, from inside the catch block, that I can tell whether the build failed or was aborted by the user?
I've tried looking at err.getMessage(), err.getCause(), err.toString(), and currentBuild.result, but none of them consistently tell me whether it failed or was aborted.
AFAIK there's no consistent way to tell if a build was failed or aborted. When a user interrupts a build a java.lang.InterruptedException is thrown, so you could start with that. Be careful with other code which could throw an InterruptedException, like the input() step when aborted.
So you could do something like:
try
{
[do work here]
}
catch(err)
{
if (err instanceof InterruptedException) {
[handle error]
} else {
[handle error]
}
}
The aborted status will be setted at build.status or currentBuild.result,
according to the issue from Jenkins official Jira issue (
https://issues.jenkins-ci.org/browse/JENKINS-43339 ):
Regrettably, not much we can do here - the ABORTED status, in some cases, doesn't get set until the Pipeline finishes executing, so we can't tell from Declarative that we should be treating the build as ABORTED.

Resources