For loop in Jenkins Pipeline - bash

I stuck with for loop condition in Pipeline
pipeline {
agent any
stages{
stage ('Showing Working Space') {
when {
anyOf {
environment name: 'Test', value: 'ALL'
environment name: 'Test', value: 'IMAGE'
}
}
steps {
sh "echo Display ${Var1}"
script{
sh 'for service in (echo "$Var1"|sed "s/,/ /g");do echo $service; done'
}
}
}
}
}
Getting error like " syntax error near unexpected token `('"
Var1 = has multiple values
Need to execute the "For loop" to pass the values to another script
Please help on this

I believe what you want is
pipeline {
agent any
stages {
stage('Showing Working Space') {
when {
anyOf {
environment name: 'Test', value: 'ALL'
environment name: 'Test', value: 'IMAGE'
}
}
steps {
sh "echo Display ${Var1}"
script {
sh 'for service in $(echo "$Var1"|sed "s/,/ /g"); do echo $service; done'
}
}
}
}
}
In essence, replace service in (echo with service in $(echo (note the $).

Related

Jenkins declarative pipeline get environment variable at post stage

I am getting runtime value in build stage stage which I stored in an environment variable . I saved that to env.cfg file under WORKSPACE .
Now I am trying to get that value in post pipeline step to be used in email communication. I tried load method but it did not work
Any help ?
post {
always {
echo $SNAPSHOT / /this always comes null
}
}
This is the way you can access an environment variable across the pipeline
pipeline {
agent any;
environment {
MESSAGE="Hello World"
}
stages {
stage('one') {
steps {
echo "${env.MESSAGE}"
sh "echo $MESSAGE"
script {
print env.MESSAGE
}
}
}
}
post {
success {
echo "${env.MESSAGE}"
script {
print env.MESSAGE
}
}
failure {
echo "${env.MESSAGE}"
script {
print env.MESSAGE
}
}
}
}
but as per your scenario let say I have a file called .env with the content below in the current Jenkins job WORKSPACE and I want to read and make this env variable in the pipeline.
.env
export SNAPSHOT=1.0.0
export MESSAGE='Hello World'
export MESSAGE_FROM_ENV_FILE='Hello From .env file'
your pipeline should look like
scripted pipeline
node {
stage('one') {
sh """
source $WORKSPACE/.env
echo \$SNAPSHOT
echo \$MESSAGE
echo \$MESSAGE_FROM_ENV_FILE
"""
}
}
declarative pipeline
pipeline {
agent any;
stages {
stage('build') {
steps {
sh """
source $WORKSPACE/.env
echo \$SNAPSHOT
echo \$MESSAGE
echo \$MESSAGE_FROM_ENV_FILE
"""
}
}
}
post {
success {
sh """
source $WORKSPACE/.env
echo \$SNAPSHOT
echo \$MESSAGE
echo \$MESSAGE_FROM_ENV_FILE
"""
}
}
}
You need a global variable:
SNAPSHOT = ""
println "SNAPSHOT is ${SNAPSHOT}"
pipeline {
agent any
stages {
stage('Build') {
steps {
script {
println "SNAPSHOT is ${SNAPSHOT}"
SNAPSHOT = "Modified"
println "SNAPSHOT is now ${SNAPSHOT}"
}
}
}
}
post {
always {
echo "${SNAPSHOT}"
}
}
}

Jenkinsfile setting stageResult variable based on conditions

I'm trying to script a Jenkinsfile in Declarative Syntax, requirement here is if set environment variables are not a match then pipeline stage should be depict as "Aborted" but the build status could be either Aborted or unstable, on Jenkins online documentation and from Snippet Generator did see the following style
catchError(buildResult: 'ABORTED', stageResult: 'ABORTED') {
// some block
}
catchError does not serve my purpose as it is appropriate for use when the script inside the stage does not return true or if there is an execution error, although default when condition in Jenkins Declarative Syntax is appropriate, Jenkins does not allow setting stage result to 'ABORTED'
when {
expression {
SCM_BRANCH_NAME ==~ /(master|QA)/
}
expression{
ENVIRONMENT ==~ /(QA)/
}
allOf{
environment ignoreCase: true,name: 'PRODUCT_NAME' , value: 'PRODUCT-1'
}
}
Please view the Sample Jenkinsfile below using if and else format
Sample Jenkinsfile
pipeline {
agent {
node {
label 'master'
}
}
environment{
ENVIRONMENT = "QA"
PRODUCT_NAME = "PRODUCT-1"
SCM_BRANCH_NAME = "master"
}
stages{
stage('Testing-1') {
when{
expression{
ENVIRONMENT ==~ /(QA)/
}
}
steps {
script {
if (PRODUCT_NAME == PRODUCT-1){
sh """
echo "Reached Here ${ENVIRONMENT} - ${PRODUCT_NAME} - ${SCM_BRANCH_NAME}"
// do testing for product 1
"""
}
else{
stageResult = 'ABORTED'
echo "PRODUCT not Available for Testing"
}
}
}
}
stage('Testing-2'){
steps{
sh '''
echo "Reached Second Stage"
'''
}
}
}
}
Any suggestions of how to implement the scenario that if conditions are not met set the stageResult as Abort, any suggestions either with a plugin or with a sample notation script is greatly appreciated
Thanks
Below snippet worked for me. You can use catch error block and throw the error from that block when some condition met. You can also catch the exception in the post stage failure section.
pipeline {
agent {
node {
label 'master'
}
}
environment{
ENVIRONMENT = "QA"
PRODUCT_NAME = "PRODUCT-1"
SCM_BRANCH_NAME = "master"
}
stages{
stage('Testing-1') {
when{
expression{
ENVIRONMENT ==~ /(QA)/
}
}
steps {
script {
catchError(buildResult: 'FAILURE', stageResult: 'ABORTED'){
if (PRODUCT_NAME != PRODUCT-1) {
error ("PRODUCT not Available for Testing")
}
sh """
echo "Reached Here ${ENVIRONMENT} - ${PRODUCT_NAME} - ${SCM_BRANCH_NAME}"
// do testing for product 1
"""
}
}
}
post {
failure {
echo "Something Failed and error has been catched"
}
}
}
stage('Testing-2'){
steps{
sh '''
echo "Reached Second Stage"
'''
}
}
}

Jenkins Pipeline, use an Env Var within emailext plugin

My Pipeline is generating a dynamic recipient list based on each Job execution.I'm trying to use that list which I set it as a Variable, to use in the 'To' section of the emailext plugin, the Problem is that the Content of the variable is not resolved once using the mailext part.
pipeline {
agent {
label 'master'
}
options {
timeout(time: 20, unit: 'HOURS')
}
stages {
stage('Find old Projects') {
steps {
sh '''
find $JENKINS_HOME/jobs/* -type f -name "nextBuildNumber" -mtime +1550|egrep -v "configurations|workspace|modules|promotions|BITBUCKET"|awk -F/ '{print $6}'|sort -u >results.txt
'''
}
}
stage('Generate recipient List') {
steps {
sh '''
for Project in `cat results.txt`
do
grep "mail.com" $JENKINS_HOME/jobs/$Project/config.xml|grep -iv "Ansprechpartner" | awk -F'>' '{print $2}'|awk -F'<' '{print $1}'>> recipientList.txt
done
recipientList=`sort -u recipientList.txt`
echo $recipientList
'''
}
}
stage('Generate list to Shelve or Delete') {
steps {
sh '''
for Project in `cat results.txt`
do
if [ -f "$JENKINS_HOME/jobs/$Project/nextBuildNumber" ]; then
nextBuildNumber=`cat $JENKINS_HOME/jobs/$Project/nextBuildNumber`
if [ $nextBuildNumber == '1' ]; then
echo "$JENKINS_HOME/jobs/$Project" >> jobs2Delete.txt
echo "$Project" >> jobList2Delete.txt
else
echo "$JENKINS_URL/job/$Project/shelve/shelveProject" >> Projects2Shelve.txt
echo "$Project" >> ProjectsList2Shelve.txt
fi
fi
done
'''
}
}
stage('Send email') {
steps {
emailext to: 'admin#mail.com',
from: 'jenkins#mail.com',
attachmentsPattern: 'ProjectsList2Shelve.txt,jobList2Delete.txt',
subject: "This is a subject",
body: "Hello\n\nAttached two lists of Jobs, to archive or delete,\nPlease Aprove or Abort the Shelving / Delition of the Projects:\n${env.JOB_URL}\n\nBlue Ocean:\n${env.RUN_DISPLAY_URL}\n\nyour Team"
}
}
stage('Aprove or Abort') {
steps {
input message: 'OK to Shelve and Delete projects? \n Review the jobs list (Projects2Shelve.txt, jobs2Delete.txt) sent to your email', submitter: 'someone'
}
}
stage('Shelve or Delete') {
parallel {
stage('Shelve Project') {
steps {
withCredentials([usernamePassword(credentialsId: 'XYZ', passwordVariable: 'PA', usernameVariable: 'US')]) {
sh '''
for job2Shelve in `cat Projects2Shelve.txt`
do
curl -u $US:$PA $job2Shelve
done
'''
}
}
}
stage('Delete Project') {
steps {
sh '''
for job2Del in `cat jobs2Delete.txt`
do
echo "Removing $job2Del"
done
'''
}
}
}
}
}
post {
success {
emailext to: "$recipientListTest",
from: 'jenkins#mail.com',
attachmentsPattern: 'Projects2Shelve.txt,jobs2Delete.txt',
subject: "This is a sbject",
body: "Hallo\n\nAttached two lists of Jobs which archived or deleted due to inactivity of more the 400 days\n\n\nyour Team"
}
}
}
I figured out that the only way would be to add a script part as part of the post section, together with a variable Definition outside of the Pipeline block:
post {
success {
script {
RECIPIENTLIST = sh(returnStdout: true, script: 'cat recipientListTest.txt')
}
emailext to: "${RECIPIENTLIST}",
from: 'jenkins#mail.com',
attachmentsPattern: 'Projects2Shelve.txt,jobs2Delete.txt',
subject: "MY SUBJECT",
body: "MY BODY"
}
when you execute a sh command, you cannot reuse the variables that you set within that command. You need to do something like this:
on top you your pipeline file to make this variable global
def recipientsList
then execute your shell command and retrieve the output
recipientsList = sh (
script: '''for Project in `cat results.txt`
do
grep "mail.com" $JENKINS_HOME/jobs/$Project/config.xml|grep -iv "Ansprechpartner" | awk -F'>' '{print $2}'|awk -F'<' '{print $1}'>> recipientList.txt
done
recipientList2=`sort -u recipientList.txt`
echo $recipientList2
''',
returnStdout: true
).trim()
Now in your email you can use the variable $recipientList...
I renamed your bash variable to recipientList2 to avoid confusion.
EDIT: I don't know what you want to obtain, but consider using some default recipients provided by emailext:
recipientProviders: [ developers(), culprits(), requestor(), brokenBuildSuspects(), brokenTestsSuspects() ],

How to skip a stage in Jenkinsfile pipeline when pipeline name ends with deliver?

I have 2 pipelines one for review and one for deploy. So when the pipeline ends with review, I want to skip Jenkinsfile execution. However, when it ends with deploy, it should execute the stage or the Jenkinsfile.
I tried to use if, but this is a declarative pipeline, so when should be used. I want to avoid execution of stage using when condition if I encounter deploy pipeline end.
#!/usr/bin/env groovy
final boolean Deploy = (env.JOB_NAME as String).endsWith("-deploy")
pipeline {
agent any
parameters {
choice(
choices: ['greeting' , 'silence'],
description: '',
name: 'REQUESTED_ACTION')
}
stages {
//how to ouse when here to use deploy vairable to avoide execution of stage below
stage ('Speak') {
steps {
echo "Hello, bitwiseman!"
}
}
}
}
You can skip stages in declarative pipelines using when, so the following should work.
stages {
stage('Deploy') {
when { equals expected: true, actual: Deploy }
steps {
// ...
}
}
}
An alternative to #StephenKing’s answer, which is also correct, you can rewrite the when block when evaluating Booleans as follows:
stages {
stage('Deploy') {
when {
expression {
return Deploy
}
}
steps {
echo "Hello, bitwiseman!" // Step executes only when Deploy is true
}
}
}
This will execute the stage Deploy only when the variable Deploy evaluates to true, else the stage will be skipped.
I've got quite a hard time to find it too, but finally:
stage('Speak') {
when {
expression { params.REQUESTED_ACTION != 'SILENCE' }
}
steps {
echo "Hello, bitwiseman!"
}
}
Jenkins docs with examples here: https://jenkins.io/doc/book/pipeline/syntax/#when-example
Here is an example for a Jenkins scripted pipeline:
stage('Input of Scratch instance and Access token') {
timeout(time: 60, unit: 'SECONDS') {
script {
try {
env.SCRATCH_INSTANCE_URL = input message: 'Please enter the SCRATCH_INSTANCE_URL',
parameters: [string(defaultValue: '',
description: '',
name: 'SCRATCH_INSTANCE_URL')]
env.SCRATCH_ACCESS_TOKEN = input message: 'Please enter the SCRATCH_ACCESS_TOKEN',
parameters: [string(defaultValue: '',
description: '',
name: 'SCRATCH_ACCESS_TOKEN')]
} catch (Throwable e) {
echo "Caught ${e.toString()}"
currentBuild.result = "SUCCESS"
}
}
}
}
// -------------------------------------------------------------------------
// Logout from Dev Hub.
// -------------------------------------------------------------------------
stage('Logout from DevHub') {
if (env.SCRATCH_INSTANCE_URL == null) {
rc = command '''export SFDX_USE_GENERIC_UNIX_KEYCHAIN=true
sfdx force:auth:logout --targetusername ${DEV_HUB_USERNAME} -p
echo ${SCRATCH_INSTANCE_URL}
echo ${SCRATCH_ACCESS_TOKEN}
'''
} else {
echo "Skipping this stage"
}
}
Even you can skip some parts of the steps using below code. Let's say REQUIRED_UPLOAD_INSTALL is a parameter.
stage('Checking Mail List') {
steps {
script {
if(!(env.REQUIRED_UPLOAD_INSTALL.toBoolean())) {
env.mail_list = 'test#testg.com'
}
}
}
}
But it doesn't support in post steps, not even in the when syntax.

Jenkins: How to use choice parameter in declarative pipeline?

My example:
pipeline {
agent any
parameters {
choice(
name: 'myParameter',
choices: "Option1\Option2",
description: 'interesting stuff' )
}
}
outputs with error:
" unexpected char: '\' " on the line with "choices" "
Following these instructions: https://github.com/jenkinsci/pipeline-model-definition-plugin/wiki/Parametrized-pipelines
Any idea or advice on what I do wrong?
The documentation for declarative jenkins pipelines says:
A choice parameter, for example:
pipeline {
.....
parameters {
choice(name: 'CHOICES', choices: ['one', 'two', 'three'], description: '') }
First one is the default value
You need to use \n instead of \.
See this code:
pipeline {
agent any
parameters {
choice(
name: 'myParameter',
choices: "Option1\nOption2",
description: 'interesting stuff' )
}
}
The arguably most elegant way to separate choices is by using an array like so:
pipeline {
agent any
parameters {
choice(
name: 'Env',
choices: ['DEV', 'QA', 'UAT', 'PROD'],
description: 'Passing the Environment'
)
}
stages {
stage('Environment') {
steps {
echo " The environment is ${params.Env}"
}
}
}
}

Resources