How to access jenkinsfile local environment variables from post steps? - jenkins-pipeline

I'm attempting to add a post-build step to my jenkinsfile to apply a label to a build. The Jenkins variables are resolved fine, but the environment variables I've defined globally within the file are not resolved. Here's the relevant bits:
pipeline {
environment {
VERSION_MAJOR = '1'
VERSION_MINOR = '0'
VERSION_PATCH = '0'
}
stages {
stage('Build') {
steps {
echo('Testing p4Tag')
}
}
}
post {
success {
build job: 'Copy-Installers',
parameters: [
//
string(name: 'MASTER_VERSION_MAJOR', value: '${VERSION_MAJOR}'),
string(name: 'MASTER_VERSION_MINOR', value: '${VERSION_MINOR}'),
string(name: 'MASTER_VERSION_FEATURE', value: '${VERSION_PATCH}'),
string(name: 'MASTER_BUILD_NUMBER', value: '${BUILD_NUMBER}'),
string(name: 'COMPONENT_NAME', value: 'Console')
}
}
}
The downstream build fails. Looking at the log it appears the local environment variables are not passed in:
The Build Number name is: ${VERSION_MAJOR}
The Build Number name is: ${VERSION_MINOR}
The Build Number name is: ${VERSION_PATCH}
The Build Number name is: 924
The Build environment name is: Console
Update
I've tried the following variations as well:
value: '${env.VERSION_MAJOR}' - Fails similarly to above
value: '$VERSION_MAJOR' - Fails similarly to above
value: $VERSION_MAJOR - Fails with "no such property" error
Update 2
For what it's worth, these variables can be referenced from the stage section. For instance, this works as expected:
stage('build') {
sh('./Build/build-package.sh $VERSION_MAJOR $VERSION_MINOR $VERSION_PATCH $BUILD_NUMBER')
}

Related

Jenkins pipeline - edit build name on a build triggered from another pipeline

I have a Jenkins pipeline, that runs sereval other jobs. Something like
pipeline {
...
stage('Job_1') {
build job: 'job-1', parameters: [
...
string(name: 'BUILD_NAME', value: params.BUILD_NAME),
]
}
stage('Job_2') {
build job: 'job-2', parameters: [
...
string(name: 'BUILD_NAME', value: params.BUILD_NAME),
]
}
and job-1, job-2 being matrixJobs. I would like to set the build names using parameter passed to the parent pipeline. The job-1 looking like
matrixJob('job-1') {
...
parameters {
...
stringParam('BUILD_NAME', "#${BUILD_NUMBER} - x", 'Name for the build')
}
wrappers {
...
buildName("${BUILD_NAME}")
}
steps {
...
}
It seems in matrixJob parameters cannot be used in build name, I get error
ERROR: (job_1.groovy, line 39) No such property: BUILD_NAME for class: javaposse.jobdsl.dsl.helpers.wrapper.WrapperContext
I would like to ask how is it possible to change the build name to add e.g. a product version. Or perhaps if there is another way to achieve this besides passing build name as a parameter.
EDIT:
I worked around this problem using script in parent pipeline. Something like this
stage('Job_1') {
build job: 'job-1', parameters: [
...
]
}
stage('Job_2') {
build job: 'job-2', parameters: [
...
]
}
stage('Set_names') {
def build = jenkins.model.Jenkins.instance.getItem('job-1').lastBuild
if(build.getResult() != hudson.model.Result.SUCCESS) {
build.displayName = params.BUILD_NAME
}
}
no tweaking of child jobs was needed.
I worked around this problem using script in parent pipeline. Something like this
stage('Job_1') {
build job: 'job-1', parameters: [
...
]
}
stage('Job_2') {
build job: 'job-2', parameters: [
...
]
}
stage('Set_names') {
def build = jenkins.model.Jenkins.instance.getItem('job-1').lastBuild
if(build.getResult() != hudson.model.Result.SUCCESS) {
build.displayName = params.BUILD_NAME
}
}
no tweaking of child jobs was needed.

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

environmentDashboard-Jenkinsfile

I have installed the following plugin in Jenkins environmentDashboard(https://plugins.jenkins.io/environment-dashboard/)
Need to incorporate the feature in Jenkinsfile, Sample Jenkinsfile
pipeline {
agent any
parameters {
string(name: "branch_name", defaultValue: "master", description: "Enter the branch name")
string(name: "project_name", defaultValue: "TestAutomation" , description:"BuildWorkspace")
choice(name: "mach_name", choices: ["LINUX" , "WINDOWS"], description: "OS Selection")
string(name: "build_suffix", defaultValue:"", description: "Provide a build suffix name")
}
environment{
TARBALL_PATH = ""
}
Wrappers{
environmentDashboard {
environmentName('Testing')
componentName('GCC_COMPILER')
buildNumber({BUILD_ID})
buildJob({JOB_NAME})
packageName('TARBALL')
addColumns(true)
columns('RESULT', 'PASS')
}
}
stages {
stage('TARBALL GENERATION') {
steps {
script{
buildName "${mach_name}#${BUILD_NUMBER}"
buildDescription "${mach_name} Test Execution on ${NODE_NAME}"
}
echo "Branch name is ${params.branch_name}"
echo "Preferred MACH: ${params.mach_name}"
echo "Reached Here after printing selected parameters"
sh """
#!/bin/bash
echo "Multiline shell steps execution"
printenv | sort
"""
} //steps
} //stage
}//Stages
}//pipeline
Getting the error as follows:
Running in Durability level: MAX_SURVIVABILITY
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 13: Undefined section "Wrappers" # line 13, column 5.
Wrappers{
^
1 error
at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:310)
at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1085)
at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:603)
at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:581)
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:558)
at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:298)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:268)
at groovy.lang.GroovyShell.parseClass(GroovyShell.java:688)
at groovy.lang.GroovyShell.parse(GroovyShell.java:700)
at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.doParse(CpsGroovyShell.java:142)
at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.reparse(CpsGroovyShell.java:127)
at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:561)
at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:522)
at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:327)
at hudson.model.ResourceController.execute(ResourceController.java:97)
at hudson.model.Executor.run(Executor.java:427)
Finished: FAILURE
You need to write wrappers in lowercase.
Like wrappers{}
Not Wrappers{}
For pipeline job you need to use the following code:
environmentDashboard(addColumns: false, buildJob: '', buildNumber: 'Version-1', componentName: 'WebApp-1', data: [], nameOfEnv: 'Environment-1', packageName: '') {
// some block
}
In fact, you can skip // some block and just use {}. That worked for me.

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

Jenkins declarative pipeline - User input parameters

I've looked for some example of user input parameters using Jenkins declarative pipeline, however all the examples are using the scripted pipelines. Here is a sample of code I'm trying to get working:
pipeline {
agent any
stages {
stage('Stage 1') {
steps {
input id: 'test', message: 'Hello', parameters: [string(defaultValue: '', description: '', name: 'myparam')]
sh "echo ${env}"
}
}
}
}
I can't seem to work out how I can access the myparam variable, it would be great if someone could help me out.
Thanks
When using input, it is very important to use agent none on the global pipeline level, and assign agents to individual stages. Put the input procedures in a separate stage that also uses agent none. If you allocate an agent node for the input stage, that agent executor will remain reserved by this build until a user continues or aborts the build process.
This example should help with using the Input:
def approvalMap // collect data from approval step
pipeline {
agent none
stages {
stage('Stage 1') {
agent none
steps {
timeout(60) { // timeout waiting for input after 60 minutes
script {
// capture the approval details in approvalMap.
approvalMap = input
id: 'test',
message: 'Hello',
ok: 'Proceed?',
parameters: [
choice(
choices: 'apple\npear\norange',
description: 'Select a fruit for this build',
name: 'FRUIT'
),
string(
defaultValue: '',
description: '',
name: 'myparam'
)
],
submitter: 'user1,user2,group1',
submitterParameter: 'APPROVER'
}
}
}
}
stage('Stage 2') {
agent any
steps {
// print the details gathered from the approval
echo "This build was approved by: ${approvalMap['APPROVER']}"
echo "This build is brought to you today by the fruit: ${approvalMap['FRUIT']}"
echo "This is myparam: ${approvalMap['myparam']}"
}
}
}
}
When the input function returns, if it only has a single parameter to return, it returns that value directly. If there are multiple parameters in the input, it returns a map (hash, dictionary), of the values. To capture this value we have to drop to groovy scripting.
It is good practice to wrap your input code in a timeout step so that build don't remain in an unresolved state for an extended time.

Resources