If condition is not getting executed in my Jenkinsfile - jenkins

properties([parameters([choice(choices: ['c ', 'a', 'd'], name: 'Run_For', description: 'Selecet \'c\' for clone and upload the cloned repos to S3 \n Slecet \'a\' for archive the repos . \n Select \'d\' for the deletion of the Repos')])])
gagan = params.Run_For
node {
stage('Example') {
choice = "c"
echo Run_For
println Run_for.getClass() // its string only
// someObject.getClass()
if (Run_For.equals('c')) {
println(" into the if ") // if is not accessiable i am not sure why
echo " yaya "
}
if (choice == "c") {
println(" into the 2nd if ") // this is accessible
echo " yaya 2 "
}
}
}
I am not sure what I am missing. I need to figure out why my first if block is not accessible.

Try the following condition.
if (params.Run_For.trim().equals("c")) {
println(" into the if ") // if is not accessiable i am not sure why
echo " yaya "
}

Related

loop array of items in declarative pipeline using groovy script

I am new to Jenkins pipeline can you please provide below out by using groovy declarative pipeline and -D should be appended for every key.
Input request should be string '''name= ram id = 123 role = IT''' and output needed as -Dname=ram -Did=123 -Drole=IT
pipeline{
agent any
parameters {
text defaultValue: '''name = ram id = 123 role = IT]''', description: 'employee details', name : 'details'
}
environment {
emp_details = "${env.details}"
}
stage('build') {
steps{
script{
echo "dislay details, ${emp_details }"
for(e in emp_details){
print e + ":" + emp_details[e])
}
}
}
}
}
Final output: -Dname=ram -Did=123 -Drole=IT
error: No Such property: [ for class: java.lang.String
if passing input is not right, how can we pass it?
You are getting a String not an array, so first, you need to create an iterable list and modify each key by iterating.
pipeline {
agent any
parameters {
text defaultValue: '''[name = ram, id = 123, role = IT]''', description: 'employee details', name : 'details'
}
environment {
emp_details = "${env.details}"
}
stages {
stage('Hello') {
steps{
script{
echo "dislay details, ${params.details}"
def appendedString = ""
// SInce it's a string we need get rid of [ and ] characters and then the spaces.
def lst = params.details.replaceAll("[^0-9a-zA-Z=,]+","").split(',')
println lst
for(e in lst){
print(e)
appendedString += "-D" + e + " ";
}
println "Final String: " + appendedString;
}
}
}
}
}
Update
Update the split logic to support the new string. '''name = ram id = 123 role = IT'''
def lst = params.details.replaceAll("\\s=\\s", "=").split("\\s")

Jenkinsfile exit a parallel stage when parameter is empty

I have the belo Jenkinsfile where I take user input for one and/or two parallel steps/stages. If the user input is empty, how can I exit that step/stage?
For example, if the user didn't enter any value for firstTask_build_number I need to echo "firstTask_build_number is empty - aborting firstTask!" and exit that. How can I exit safely?
pipeline {
agent any
parameters {
string(name: 'firstTask_build_number', defaultValue: '', description: 'Build ID of firstTask')
string(name: 'secondTask_build_number', defaultValue: '', description: 'Build ID of secondTask')
}
stage("Parallel") {
steps {
parallel (
"firstTask" : {
if (firstTask_build_number.size() == 0) {
echo "firstTask_build_number is empty - aborting firstTask!"
}
else {
//do some stuff
}
},
"secondTask" : {
if (secondTask_build_number.size() == 0) {
echo "secondTask_build_number is empty - aborting secondTask!"
}
else {
//do some stuff
}
}
)
}
}
}
You can just return out of it.
parallel (
"firstTask" : {
if (firstTask_build_number.size() == 0) {
echo "firstTask_build_number is empty - aborting firstTask!"
return
}
else {
//do some stuff
}
}
)

Jenkins pipeline - "cannot invoke method on null object" on function outside the pipeline

i get the error above when trying to run my pipeline
tried to run it inside and outside the groovy sandBox.
also tried debugging and it's fails on this method call "last_build_number(lastBuildToGenerateNumber)"
before adding try, catch and recursion this code was working well outside the pipeline. don't get me wrong - this code can not run inside the pipeline so i did not try it.
/*
SEIIc DPS_NIGHTLY_BUILD JenkinsFile
*/
def buildDescription // for setting the build name, based on the downstream jobs name
def last_build_number(build) {
println 'the display name is' + build.displayName
return build.displayName
if (build != null) {
if(build.displayName!=null){
println 'the display name is' + build.displayName
return build.displayName
}
}
else {
return '0.0.0.0'
}
return '0.0.0.0'
}
def autoIncBuildNightlyNumber(build) {
def debugEnable = 1
println 'build is: ' + build.displayName
def lastBuildToGenerateNumber = build; //a build variable
def last_build_number; //last build number i.e: "52.88.0.7" or "#43"
build_number=0;
try{
println 'last build to genreate from ' + lastBuildToGenerateNumber.displayName
last_build_number = last_build_number(lastBuildToGenerateNumber);
if (debugEnable == 1) println 'last successfull build: ' + last_successfull_build
def tokens = last_build_number.tokenize('.')
if (debugEnable == 1) println 'tokens: ' + tokens
// update global variable - if it's not a legit number the crash will be catched
build_number = tokens[3].toInteger() + 1
if (debugEnable == 1) println 'new build number: ' + build_number
return build_number
} catch (e){
if (debugEnable == 1) println 'error is ' + e
if (debugEnable == 1) println 'build number: ' + build_number + ' is not valid. recurse now to find a valid number'
build_number = autoIncBuildNightlyNumber(lastBuildToGenerateNumber.getPreviousBuild());
println 'genrate ' + lastBuildToGenerateNumber
return build_number
}
}
// Declarative Pipeline
pipeline {
/*
maximum time for this job
*/
options { //maximum time for this job
timeout(time: 1, unit: 'HOURS')
}
environment {
AUTO_BUILD_NUMBER = autoIncBuildNightlyNumber(currentBuild.getPreviousBuild())
PLASTICSCM_TARGET_SERVER = "g-plasticscm-server.gilat.com:8087"
PLASTICSCM_TARGET_REPOSITORY = "SEIIc_DPS"
PLASTICSCM_WORKSPACE_NAME = "${env.JOB_BASE_NAME}_${env.BUILD_NUMBER}"
AUTOMATION_FOLDER = "${env.PLASTICSCM_WORKSPACE_NAME}\\Tools\\Automation"
Branch = "/main"
TEST_BRANCH = "/QualiTest for SW Automation"
QUALITEST_FOLDER = "${env.PLASTICSCM_WORKSPACE_NAME}\\QualiTest for SW Automation"
PLASTICSCM_TEST_REPOSITORY="SW_Utiles"
PLASTICSCM_TEST_WORKSPACE = "TEST_${env.JOB_BASE_NAME}_${env.BUILD_NUMBER}"
}
// Select target host for building this pipeline
agent { node { label "SEIIc_DPS" } }
// Stages to run for this pipeline
stages {
/*
Checkout files from source control. In this case the pipeline use PlasticSCM plugin to checkout a branch with given parameter "Branch".
When this stage run, it will checkout the branch in the parameter string from the defined repository and server.
It will not
*/
stage('SCM Checkout') {
steps {
cm branch: env.Branch, changelog: true, repository: env.PLASTICSCM_TARGET_REPOSITORY, server: env.PLASTICSCM_TARGET_SERVER, useUpdate: false, workspaceName: env.PLASTICSCM_WORKSPACE_NAME
//checkOut QualiTest
cm branch: env.TEST_BRANCH, changelog: false, repository: 'SW_Utiles', server: env.PLASTICSCM_TARGET_SERVER, useUpdate: false, workspaceName: env.PLASTICSCM_TEST_WORKSPACE
}
}
}//stages
}//pipeline

Jenkins declarative pipeline: find out triggering job

We have a Jenkins job that uses a declarative pipeline.
This job can be triggered by different other builds.
In the declarative pipeline how can I find out which build has triggered the pipeline?
Code sample below
pipeline {
agent any
stages {
stage('find upstream job') {
steps {
script {
def causes = currentBuild.rawBuild.getCauses()
for(cause in causes) {
if (cause.class.toString().contains("UpstreamCause")) {
println "This job was caused by job " + cause.upstreamProject
} else {
println "Root cause : " + cause.toString()
}
}
}
}
}
}
}
You can check the job's REST API to get extra information like below
{
"_class" : "org.jenkinsci.plugins.workflow.job.WorkflowRun",
"actions" : [
{
"_class" : "hudson.model.ParametersAction",
"parameters" : [
]
},
{
"_class" : "hudson.model.CauseAction",
"causes" : [
{
"_class" : "hudson.model.Cause$UpstreamCause",
"shortDescription" : "Started by upstream project \"larrycai-sto-46908390\" build number 7",
"upstreamBuild" : 7,
"upstreamProject" : "larrycai-sto-46908390",
"upstreamUrl" : "job/larrycai-sto-46908390/"
}
]
},
Reference:
https://jenkins.io/doc/pipeline/examples/#get-build-cause
Get Jenkins upstream jobs
I realize that this is a couple years old, but the previous response required some additional security setup in my Jenkins instance. After a bit of research, I found that there was a new feature request completed in 11/2018 that addresses this need and exposes build causes in currentBuild. Here is a little lib I wrote that returns the cause with the string "JOB/" prepended if the build was triggered by another build:
def call(body) {
if (body == null) {body = {DEBUG = false}}
def myParams= [:]
body.resolveStrategy = Closure.DELEGATE_FIRST
body.delegate = myParams
body()
def causes = currentBuild.getBuildCauses()
if (myParams.DEBUG) {
echo "causes count: " + causes.size().toString()
echo "causes text : " + causes.toString()
}
for(cause in causes) {
// echo cause
if (cause._class.toString().contains("UpstreamCause")) {
return "JOB/" + cause.upstreamProject
} else {
return cause.toString()
}
}
}
To use this, I place it in a library in a file named "buildCause.groovy". Then I reference the library at the top of my Jenkinsfile:
library identifier: 'lib#master', retriever: modernSCM(
[$class: 'GitSCMSource', remote: '<LIBRARY_REPO_URL>',
credentialsId: '<LIBRARY_REPO_CRED_ID', includes: '*'])
Then I can call it as needed within my pipeline:
def cause=buildCause()
echo cause
if (!cause.contains('JOB/')) {
echo "started by user"
} else {
echo "triggered by job"
}
Larry's answer didn't quite work for me.
But, after I've modified it slightly with the help of these docs and this version works:
def causes = currentBuild.getBuildCauses()
for(cause in causes) {
if (cause._class.toString().contains("UpstreamCause")) {
println "This job was caused by job " + cause.upstreamProject
} else {
println "Root cause : " + cause.toString()
}
}
P.S. Actually, Daniel's answer mentions this method, but there's too much clutter, I only noticed it after I wrote my solution.

How to check jenkins node connection status using jenkins-cli

I'm trying to check specific Jenkins node is connected using Jenkins CLI
. To get the node details I can use get-node command and it returns details as this xml
<?xml version="1.0" encoding="UTF-8"?>
<slave>
<name>20170602_jenkins_slave_002</name>
<description>10.49.82.46</description>
<remoteFS>c:\\jenkins_root</remoteFS>
<numExecutors>1</numExecutors>
<mode>EXCLUSIVE</mode>
<retentionStrategy class="hudson.slaves.RetentionStrategy$Always"/>
<launcher class="hudson.slaves.JNLPLauncher"/>
<label>20170602_jenkins_slave_002</label>
<nodeProperties/>
<userId>admin</userId>
</slave>
But it does not includes the node status. Anyone has idea how to check the node status by Jenkins cli
As I'm not aware of a method using jenkins-cli, my suggestion is to use the REST API:
http://jenkins.example.com/computer/:name/api/json
returns JSON data including an offline field.
You can get an overview over all agents (called computer here) on the following URL:
http://jenkins.example.com/computer/api/json?pretty=true
We can implement this using pipeline. I did using the groovy script for the windows VDI machines, Below is the script.
pipeline {
agent none
stages {
stage('Agent Health check step') {
options {
timeout(time:5, unit: 'MINUTES')
}
agent {
label "master"
}
steps {
script {
def agStatusList = []
def agentsMap = [VDI1:"XYZ#gmail.com", VDI2:"XYZ2#gmail.com", VDI3:"XYZ#gmail.com", VDI4:"himesh.patel#gmail.com"]
String agEmlTo=''
for (agSlave in hudson.model.Hudson.instance.slaves) {
def agName=agSlave.name
def agOwner=agentsMap.get(agName)
def agStatus=agSlave.getComputer().isOnline()
if (agStatus != true ){
echo "Node is offline"
echo " "
agStatusList += agName + " node is offline" + " and owner is " + agOwner
if(agStatus != true && agOwner != null){
if (agEmlTo == null || agEmlTo.trim().isEmpty()){
agEmlTo = agOwner
} else{
agEmlTo += (','+agOwner)
}
}
}else{
echo "Node is online"
echo " "
agStatusList += agName + " node is online" + " and owner is " + agOwner
}
}
println agStatusList
println agEmlTo
if (agEmlTo != null && !agEmlTo.trim().isEmpty()) {
echo "Sending email to the owners of offline Nodes"
string agEmlCc='123#gmail.com'
string agEmlFrom='JenkinsServer#gmail.com'
String agEmlHdr='[Notification] Your Windows VDI agent is offline'
String agEmlBody='Hello, \n \nThe Windlows VDI agent assigned to you seems offline now. Please check the Windows VDI machine and get it connected ASAP.\n \n *This E-mail is from Automated process. Please do not respond directly to this e-mail as the originating e-mail account is not monitored*'
emailext body: "${agEmlBody}",
to: "${agEmlTo}",
subject: "${agEmlHdr}"
from: "JenkinsServer#gmail.com"
}
}
}
}
}
}

Resources