how to create loop inside jenkinsfile - jenkins-pipeline

i have created a jenkinsfile
inside i have created a text parameter with 10 server names.
i want to create a loop within a stage to echo each server name.
// ######################################################################### PROPERTIES ###########################################################################
properties([
parameters([
text(defaultValue: '', description: 'EXAMPLE: lsch3-123', name: 'SERVERS')])])
// ######################################################################### START PIPELINE ###########################################################################
pipeline {
agent none
options {
skipDefaultCheckout true
}
stages {
stage('GIT & PREP') {
agent {label "${params.DC}-ansible01"}
steps {
cleanWs()
run loop here
}
}
}
}

Please see below code/reference example which will loop within the stage.
// Define list which would contain all servers in an array. Initialising it as empty
def SERVERS = []
pipeline {
agent none
options {
skipDefaultCheckout true
}
parameters
{
// Adding below as example string which is passed from paramters . this can be changed based on your need
// Example: Pass server list as ; separated string in your project. This can be changed
string(name: 'SERVERS', defaultValue:'server1;server2', description: 'Enter ; separated SERVERS in your project e.g. server1;server2')
}
stages {
stage('GIT & PREP') {
agent {label "${params.DC}-ansible01"}
steps {
cleanWs()
// run loop here under script
script
{
// Update SERVERS list.Fill SERVERS list with server names by splitting the string.
SERVERS = params.SERVERS.split(";")
// Run loop below : execute below part for each server listed in SERVERS list
for (server in SERVERS)
{
println ("server is : ${server}")
}
}
}
}
}
}
Regards.

Related

Using Function in JenkinsFile Parameter Description

I am trying to add a function in JenkinsFile Declarative pipelines parameter's description but struggling to make it work.
Idea is to have a Jenkins Job specific for the environment. and would like to see the choice parameter to show environment name in the description of the variable.
My pipeline looks like this
def check_env = app_env(ENVS, env.JOB_NAME)
pipeline {
agent { label 'master' }
options {
disableConcurrentBuilds()
buildDiscarder(logRotator(numToKeepStr: '20'))
timestamps()
}
parameters{
string(name: 'myVariable', defaultValue: "/", description: 'Enter Path To App e.g / OR /dummy_path for ' {check_env} )
}
stages{
stage('Running App') {
agent {
docker {
image 'myApp:latest'
}
}
steps{
script{
sh label: 'App', script: "echo "App is running in ${check_env} "
}
}
}
}
}
}
I have tried multiple combinations for check_env e.g check_env, check_env(), ${check_env} function but none of them worked.
String Interpolation
I believe this is simply a String Interpolation issue. Notice my use of double quotes below
parameters{
string(name: 'myVariable', defaultValue: "/", description: "Enter Path To App e.g / OR /dummy_path for ${check_env}")
}
Your build page should then interpolate your variable
To test I simply set def check_env = 'live' since I do not have the code for your method

Change the parameter values in a Jenkins Pipeline

How to map the parameter values to a different value and then execute it inside the pipeline.
parameters {
choice(name: 'SIMULATION_ID',
choices: 'GatlingDemoblaze\nFrontlineSampleBasic\nGatlingDemoStoreNormalLoadTest',
description: 'Simulations')
}
How to map the value of 'GatlingDemoblaze' to '438740439023874' so that the it will be the latter which goes inside the ${params.SIMULATION_ID}? Can we do this with a simple groovy code?
gatlingFrontLineLauncherStep credentialId: '', simulationId:"${params.SIMULATION_ID}"
Thanks for the help.
As suggested in the comments the best approach will be to use the Extensible Choice Parameter Plugin and define the needed key-value pairs, however if you don't want to use the plugin you can create the mapping using groovy in the pipeline script and use it.
For that you have several options:
If you need it for a single stage you can define the map inside a script block and use it in that stage:
pipeline {
agent any
parameters {
choice(name: 'SIMULATION_ID', description: 'Simulations',
choices: ['GatlingDemoblaze', 'FrontlineSampleBasic', 'GatlingDemoStoreNormalLoadTest'])
}
stages {
stage('Build') {
steps {
script {
def mappings = ['GatlingDemoblaze': '111', 'FrontlineSampleBasic': '222', 'GatlingDemoStoreNormalLoadTest': '333']
gatlingFrontLineLauncherStep credentialId: '', simulationId: mappings[params.SIMULATION_ID]
}
}
}
}
}
You can also define it as a global parameter that will be available in all stages (and then you don't need the script directive):
mappings = ['GatlingDemoblaze': '111', 'FrontlineSampleBasic': '222', 'GatlingDemoStoreNormalLoadTest': '333']
pipeline {
agent any
parameters {
choice(name: 'SIMULATION_ID', description: 'Simulations',
choices: ['GatlingDemoblaze', 'FrontlineSampleBasic', 'GatlingDemoStoreNormalLoadTest'])
}
stages {
stage('Build') {
steps {
gatlingFrontLineLauncherStep credentialId: '', simulationId: mappings[params.SIMULATION_ID]
}
}
}
}
and another options is to set these values in the environment directive:
pipeline {
agent any
parameters {
choice(name: 'SIMULATION_ID', description: 'Simulations',
choices: ['GatlingDemoblaze', 'FrontlineSampleBasic', 'GatlingDemoStoreNormalLoadTest'])
}
environment{
GatlingDemoblaze = '111'
FrontlineSampleBasic = '222'
GatlingDemoStoreNormalLoadTest = '333'
}
stages {
stage('Build') {
steps {
gatlingFrontLineLauncherStep credentialId: '', simulationId: env[params.SIMULATION_ID]
}
}
}
}

How to trigger a multiple run in a single pipeline job of jenkins?

I have a pipeline job which run with below pipeline groovy script,
pipeline {
parameters{
string(name: 'Unique_Number', defaultValue: '', description: 'Enter Unique Number')
}
stages {
stage('Build') {
agent { node { label 'Build' } }
steps {
script {
sh build.sh
}
}
stage('Deploy') {
agent { node { label 'Deploy' } }
steps {
script {
sh deploy.sh
}
}
stage('Test') {
agent { node { label 'Test' } }
steps {
script {
sh test.sh
}
}
}
}
I just trigger this job multiple times with different unique ID number as input parameter. So as a result i will have multiple run/build for this job at different stages.
With this, i need to trigger a multiple run/build to be promote to next stage (i.e., from build to deploy or from deploy to test) in this pipeline job as a one single build instead of triggering each and every single run/build to next stage. Is there any possibility?
I was also trying to do the same thing and found no relevant answers. May this help to someone.
This will read a file that contains the Jenkins Job name and run them iteratively from one single job.
Please change below code accordingly in your Jenkins.
pipeline {
agent any
stages {
stage('Hello') {
steps {
script{
git branch: 'Your Branch name', credentialsId: 'Your crendiatails', url: ' Your BitBucket Repo URL '
##To read file from workspace which will contain the Jenkins Job Name ###
def filePath = readFile "${WORKSPACE}/ Your File Location"
##To read file line by line ###
def lines = filePath.readLines()
##To iterate and run Jenkins Jobs one by one ####
for (line in lines) {
build(job: "$line/branchName",
parameters:
[string(name: 'vertical', value: "${params.vertical}"),
string(name: 'environment', value: "${params.environment}"),
string(name: 'branch', value: "${params.aerdevops_branch}"),
string(name: 'project', value: "${params.host_project}")
]
)
}
}
}
}
}
}
You can start multiple jobs from one pipeline if you run something as:
build job:"One", wait: false
build job:"Two", wait: false
Your main job starts children pipelines and children pipelines will run in parallel.
You can read PipeLine Build Step documentation for more information.
Also, you can read about the parallel run in declarative pipeline
Here you can find a lot of examples for parallel running

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.

Fetch credentials depending on environment

I can take credentials like explained in the example taken from here - https://jenkins.io/doc/book/pipeline/syntax/#environment
stage('Example') {
environment {
CREDS = credentials('MY_CREDS_DEV')
}
steps {
sh 'echo hello'
}
}
But what I want to do is to get credentials based on some condition.
For example I have MY_CREDS_DEV and MY_CREDS_QA defined in Jenkins credentials. And I have a property ENV=dev defined in Jenkins 'Prepare an environment for the run' section.
I'd like to access credentials based on my environment, i.e. ENV property.
I tried to use CREDS = credentials('MY_CREDS_' + ${ENV}) and tried to extract strings concatenation to a separate function and call it like CREDS = credentials(concatenate(${ENV})) but I got Internal function call parameters must be strings.
So seems I can put only a string to credentials() function which basically means to hardcode it. But how can I choose which credentials to use - dev or qa?
Use CREDS = credentials('MY_CREDS_' + ENV) or CREDS = credentials("MY_CREDS_${ENV}"). ${ENV} will not become 'dev'but ${'dev'} and therefore is no string.
For completeness:
In fact - after playing aroung with the groovy console - it looks like ${ENV} will try to call a function called $ with the closure parameter {ENV} which in turn would return 'dev'. It would give the same result as ENV if you would have defined a function like:
def $(Closure closure) {
closure()
}
But most probably that's not what you wanted to do.
Got this working in Jenkins:2.190.2 with a little groovy. Haven't tested on earlier versions. Just happens to be the one I'm on now. Works fine with multiple stages.
pipeline {
agent {
label "xxxxx"
}
environment {
ROLE = getRole()
}
stages{
stage("write to s3 etc") {
environment {
AWS = credentials("${ROLE}")
}
steps {
script {
sh"""
aws s3 sync build/ "s3://xxxxxxxxxxxx"
"""
}
}
}
}
}
def getRole() {
def branchName = "${env.BRANCH_NAME}"
if (branchName == "xxxxxx") {
return 'some_credential_string'
}
else {
return 'some_other_credential_string'
}
}
If you would like to use different credentials based on the condition, this could be done with the following example:
stage ("Example") {
steps {
script {
if ( params.TEST_PARAMETER == "test_value1" ) {
withCredentials([string(credentialsId: env.CREDENTIALS_1, variable: 'SOME_VARIABLE')]) {
yourFunction()
}
}
else {
withCredentials([string(credentialsId: env.CREDENTIALS_2, variable: 'SOME_VARIABLE')]) {
yourFunction()
}
}
}
}
}
You would need to define yourFunction in the end of your jenkinsfile. In this case, when TEST_PARAMETER is test_value1 in the job, CREDENTIALS_1 will be used from Jenkins credentials list. When TEST_PARAMETER is different, CREDENTIALS_2 credentials will be used. You could have more options by modifying this to the case loop.
Hope this helps.

Resources