How to set a dynamic variable as global variable in jenkins? - jenkins

I need to set a global variable with the value build_{BUILD_NUMBER}(jenkins global variable), which is dynamic. How can I set this in jenkins global properties?
How can it recognize the build number I'm referring to ?

using a declarative pipeline, you can set an environment variable based on this other environment variable (BUILD_NUMBER) like this:
pipeline {
agent { label 'docker' }
environment {
MY_BUILD_IDENTIFIER = "build_${env.BUILD_NUMBER}"
}
stages {
stage('hot_stage') {
steps {
echo "MY_BUILD_IDENTIFIER: ${env.MY_BUILD_IDENTIFIER}"
}
}
}
}
produces output like this:
[Pipeline] echo
MY_BUILD_IDENTIFIER: build_153

Here is an example script, how to alter global environment variables:
nodes = Jenkins.instance.globalNodeProperties
nodes.getAll(hudson.slaves.EnvironmentVariablesNodeProperty.class)
if ( nodes.size() != 1 ) {
println("error: unexpected number of environment variable containers: ${nodes.size()}, expected: 1")
} else {
envVars = nodes[0].envVars
envVars[args[0]] = args[1]
Jenkins.instance.save()
println("okay")
}
reference:
https://gist.github.com/johnyzed/2af71090419af2b20c5a

Related

Jenkinsfile define variable based on environment variable

I would like to set a boolean variable to true if one of my environment variables equals a string. I only want to run my test stage if this RUN_TESTS var is true.
pipeline{
environment {
RUN_TESTS = expression { "${env.JOB_BASE_NAME}" == 'Test Pipeline' }
}
stages{
stage('test'){
when {
expression { RUN_TESTS }
}
steps{
// run my tests.......
}
}
}
The above is not working though.
How can I set a boolean variable based on the value of an environment variable that I can then use to conditionally run a pipeline stage?
It looks like you do not have to set environment variable in this case. You can evaluate expression directly in your stage:
pipeline{
stages{
stage('test'){
when {
expression { "${env.JOB_BASE_NAME}" == 'Test Pipeline' }
}
steps{
// run my tests.......
}
}
}
On the other hand if you still have to set the environment variable there are few ways to do it. Jenkins says:
Environment variable values must either be single quoted, double quoted, or function calls.
Wrap it in double quoted expression:
environment {
RUN_TESTS = "${env.JOB_BASE_NAME == 'Test Pipeline'}"
}
Wrap this expression in the function call, something like this:
def run_tests() {
return "${env.JOB_BASE_NAME}" == 'Test Pipeline'
}
pipeline{
environment {
RUN_TESTS = run_tests()
}
stages{
stage('test'){
when {
expression { RUN_TESTS }
}
steps{
// run my tests.......
}
}
}
But in general I would go for first approach

How to use env variable inside triggers section in jenkins pipeline?

Reading the properties file for the node label and triggerConfigURL, node label works, but I couldn't read and set triggerConfigURL from environment.
def propFile = "hello/world.txt" //This is present in workspace, and it works.
pipeline {
environment {
nodeProp = readProperties file: "${propFile}"
nodeLabel = "$nodeProp.NODE_LABEL"
dtcPath = "$nodeProp.DTC"
}
agent { label env.nodeLabel } // this works!! sets NODE_LABEL value from the properties file.
triggers {
gerrit dynamicTriggerConfiguration: 'true',
triggerConfigURL: env.dtcPath, // THIS DON'T WORK, tried "${env.dtcPath}" and few other notations too.
serverName: 'my-gerrit-server',
triggerOnEvents: [commentAddedContains('^fooBar$')]
}
stages {
stage('Print Env') {
steps {
script {
sh 'env' // This prints "dtcPath=https://path/of/the/dtc/file", so the dtcPath env is set.
}
}
}
After running the job, the configuration is as below:
Of the env and triggers clauses Jenkins runs one before the other, and it looks like you have experimentally proven that triggers run first and env second. It also looks like agent runs after env as well.
While I don't know why the programmers have made this specific decision, I think you are in a kind of a chicken-and-egg problem, where you want to define the pipeline using a file but can only read the file once the pipeline is defined and running.
Having said that, the following might work:
def propFile = "hello/world.txt"
def nodeProp = null
node {
nodeProp = readProperties file: propFile
}
pipeline {
environment {
nodeLabel = nodeProp.NODE_LABEL
dtcPath = nodeProp.DTC
}
agent { label env.nodeLabel }
triggers {
gerrit dynamicTriggerConfiguration: 'true',
triggerConfigURL: nodeProp.DTC,
//etc.

How to set Jenkins Declarative Pipeline environments with Global Variables?

I am trying to do this
pipeline {
agent any
environment {
LOCAL_BUILD_PATH=env.WORKSPACE+'/build/'
}
stages {
stage('Stuff'){
steps{
echo LOCAL_BUILD_PATH
}
}
}
}
Result:
null/build/
How can I use Global Environments to create my environments?
So this is method that I ended up using
pipeline {
agent {
label 'master'
}
stages {
stage ("Setting Variables"){
steps {
script{
LOCAL_BUILD_PATH = "$env.WORKSPACE/build"
}
}
}
stage('Print Varliabe'){
steps{
echo LOCAL_BUILD_PATH
}
}
}
}
You can use something like this...
LOCAL_BUILD_PATH="${env.WORKSPACE}/build/"
Remember: use "(double quote) for variable in string
I think you should use:
steps {
echo "${env.LOCAL_BUILD_PATH}"
}
as in "environment" step you're defining environmental variables which are later accessible by env.your-variable-name
This a scope issue. Declare the variable, at the top and set it to null. Something like
def var = null
You should be able to set the value in a block/closure/stage and access it in another

Conditional environment variables in Jenkins Declarative Pipeline

I'm trying to get a declarative pipeline that looks like this:
pipeline {
environment {
ENV1 = 'default'
ENV2 = 'default also'
}
}
The catch is, I'd like to be able to override the values of ENV1 or ENV2 based on an arbitrary condition. My current need is just to base it off the branch but I could imagine more complicated conditions.
Is there any sane way to implement this? I've seen some examples online that do something like:
stages {
stage('Set environment') {
steps {
script {
ENV1 = 'new1'
}
}
}
}
But I believe this isn't setting the actually environment variable, so much as it is setting a local variable which is overriding later calls to ENV1. The problem is, I need these environment variables read by a nodejs script, and those need to be real machine environment variables.
Is there any way to set environment variables to be dynamic in a jenkinsfile?
Maybe you can try Groovy's ternary-operator:
pipeline {
agent any
environment {
ENV_NAME = "${env.BRANCH_NAME == "develop" ? "staging" : "production"}"
}
}
or extract the conditional to a function:
pipeline {
agent any
environment {
ENV_NAME = getEnvName(env.BRANCH_NAME)
}
}
// ...
def getEnvName(branchName) {
if("int".equals(branchName)) {
return "int";
} else if ("production".equals(branchName)) {
return "prod";
} else {
return "dev";
}
}
But, actually, you can do whatever you want using the Groovy syntax (features that are supported by Jenkins at least)
So the most flexible option would be to play with regex and branch names...So you can fully support Git Flow if that's the way you do it at VCS level.
use withEnv to set environment variables dynamically for use in a certain part of your pipeline (when running your node script, for example). like this (replace the contents of an sh step with your node script):
pipeline {
agent { label 'docker' }
environment {
ENV1 = 'default'
}
stages {
stage('Set environment') {
steps {
sh "echo $ENV1" // prints default
// override with hardcoded value
withEnv(['ENV1=newvalue']) {
sh "echo $ENV1" // prints newvalue
}
// override with variable
script {
def newEnv1 = 'new1'
withEnv(['ENV1=' + newEnv1]) {
sh "echo $ENV1" // prints new1
}
}
}
}
}
}
Here is the correct syntax to conditionally set a variable in the environment section.
environment {
MASTER_DEPLOY_ENV = "TEST" // Likely set as a pipeline parameter
RELEASE_DEPLOY_ENV = "PROD" // Likely set as a pipeline parameter
DEPLOY_ENV = "${env.BRANCH_NAME == 'master' ? env.MASTER_DEPLOY_ENV : env.RELEASE_DEPLOY_ENV}"
CONFIG_ENV = "${env.BRANCH_NAME == 'master' ? 'MASTER' : 'RELEASE'}"
}
I managed to get this working by explicitly calling shell in the environment section, like so:
UPDATE_SITE_REMOTE_SUFFIX = sh(returnStdout: true, script: "if [ \"$GIT_BRANCH\" == \"develop\" ]; then echo \"\"; else echo \"-$GIT_BRANCH\"; fi").trim()
however I know that my Jenkins is on nix, so it's probably not that portable
Here is a way to set the environment variables with high flexibility, using maps:
stage("Environment_0") {
steps {
script {
def MY_MAP = [ME: "ASSAFP", YOU: "YOUR_NAME", HE: "HIS_NAME"]
env.var3 = "HE"
env.my_env1 = env.null_var ? "not taken" : MY_MAP."${env.var3}"
echo("env.my_env1: ${env.my_env1}")
}
}
}
This way gives a wide variety of options, and if it is not enough, map-of-maps can be used to enlarge the span even more.
Of course, the switching can be done by using input parameters, so the environment variables will be set according to the input parameters value.
pipeline {
agent none
environment {
ENV1 = 'default'
ENV2 = 'default'
}
stages {
stage('Preparation') {
steps {
script {
ENV1 = 'foo' // or variable
ENV2 = 'bar' // or variable
}
echo ENV1
echo ENV2
}
}
stage('Build') {
steps {
sh "echo ${ENV1} and ${ENV2}"
}
}
// more stages...
}
}
This method is more simple and looks better. Overridden environment variables will be applied to all other stages also.
I tried to do it in a different way, but unfortunately it does not entirely work:
pipeline {
agent any
environment {
TARGET = "${changeRequest() ? CHANGE_TARGET:BRANCH_NAME}"
}
stages {
stage('setup') {
steps {
echo "target=${TARGET}"
echo "${BRANCH_NAME}"
}
}
}
}
Strangely enough this works for my pull request builds (changeRequest() returning true and TARGET becoming my target branch name) but it does not work for my CI builds (in which case the branch name is e.g. release/201808 but the resulting TARGET evaluating to null)

Environment in Jenkins Pipeline has no variables

Because I couldn't use an environment variable that I thought should exist, I printed all the environment variables in my Jenkins Pipeline script:
node {
for(e in env) {
print "key = ${e.key}, value = ${e.value}"
}
}
This prints:
key = null, value = null
I'm very surprised by this.
Why are there no environment variables?
Seems to be a bug/limitation. If you look at the implementation, there is no support for iteration.
The following works as a workaround:
node {
for(e in env.getEnvironment()) {
print "key = ${e.key}, value = ${e.value}"
}
}

Resources