Jenkins declarative pipeline expression with boolean environment variable - jenkins

I'm using Jenkins declarative pipeline and I want to make a conditional step depending on an environment variable, which is set according the existence of a file.
So I just want to make something like that : if Dockerfile exist, perform next stage, else don't.
To perform this I tried :
pipeline {
// ...
stage {
stage('Docker') {
environment {
IS_DOCKERFILE = fileExists 'Dockerfile'
}
when {
environment name: 'IS_DOCKERFILE', value: true
}
stage('Build') {
// ...
}
}
}
}
Or :
pipeline {
// ...
stage {
stage('Docker') {
environment {
IS_DOCKERFILE = fileExists 'Dockerfile'
}
when {
expression {
env.IS_DOCKERFILE == true
}
}
stage('Build') {
// ...
}
}
}
}
In both cases, the Dockerfile exist and it is in the workspace. I also tried with strings ("true") but everytime, the pipeline continue without executing the stage 'Build'.
Any suggestions ?

This is because the exprsssion:
IS_DOCKERFILE = fileExists 'Dockerfile'
Creates the environment variable with boolean value as string:
$ set
IS_DOCKERFILE='false'
So the solution would be to use .toBoolean() like this:
environment {
IS_DOCKERFILE = fileExists 'Dockerfile'
}
stages {
stage("build docker image") {
when {
expression {
env.IS_DOCKERFILE.toBoolean()
}
}
steps {
echo 'fileExists'
}
}
stage("build libraries") {
when {
expression {
!env.IS_DOCKERFILE.toBoolean()
}
}
steps {
echo 'fileNotExists'
}
}
}

As #Sergey already posted, the problem is that you're comparing a string to a boolean. See fileExists: Verify if file exists in workspace.
Besides his answer, you can compare directly to a string:
environment {
IS_DOCKERFILE = fileExists 'Dockerfile'
}
stages {
stage("build docker image") {
when {
expression {IS_DOCKERFILE == 'true'}
}
steps {
echo 'fileExists'
}
}
stage("build libraries") {
when {
expression {IS_DOCKERFILE == 'false'}
}
steps {
echo 'fileNotExists'
}
}
}

Related

Specify agent in Jenkins Pipeline Shared Library

I am trying to customize a shared Library which run a stage in a specify agent by adding the possibility to specify the agent.
def call(String agentLabel) {
pipeline {
agent { label "$agentLabel" }
stages {
stage('Hello') { steps { echo 'Hello World' } }
}
}
}
This is OK but now I want to customize the type of agent (IE. either use label or docker agent) ?
This don't work :
def call(String agentLabel, String agentDockerImage = null) {
Closure agentRunner = null
if (agentDockerImage) {
agentRunner = {
docker {
label "$agentLabel"
image "$agentDockerImage"
}
}
} else {
agentRunner = {
label "$agentLabel"
}
}
pipeline {
agent { agentRunner.call() }
stages {
stage('Hello') { steps { echo 'Hello World' } }
}
}
}
WorkflowScript: 15: Invalid agent type "call" specified. Must be one of [any, docker, dockerfile, label, none] # line 15, column 29.
agent { agentRunner.call() }
^

Jenkinsile global variables outside "stages" section

I would like to set the variable that will be available to all stages. Variable that depends on chosen parameter, something like this:
parameters {
choice(name: 'Environment', choices: ['Dev', 'Stage'], description: 'Deploy to chosen environment')
}
environment {
//set the config file which depends on params.Environment e.g.
//case params.Environment of
// Dev -> CONFIG_FILE="deploy/file_1.conf"
// Stage -> CONFIG_FILE="deploy/other_file.conf"
}
stages {
stage('check-params') {
steps {
sh "echo \"config file: ${CONFIG_FILE}\""
}
}
stage('build-frontend') {
steps {
sh "build-fronted.sh ${CONFIG_FILE}"
}
}
stage('deploy-backend') {
steps {
sh "deploy-backend.sh ${CONFIG_FILE}"
}
}
but according to the Pipeline Syntax it is not allowed (I get ERROR: Expected name=value pairs).
Does anyone know how can I achieve this without using scripts { ... } in every stage->step as described in this post?
You can have a init stage which will set correct variable depending on parameter, something like this:
parameters {
choice(name: 'Environment', choices: ['Dev', 'Stage'], description: 'Deploy to chosen environment')
}
environment {
//set the config file which depends on params.Environment e.g.
//case params.Environment of
// Dev -> CONFIG_FILE="deploy/file_1.conf"
// Stage -> CONFIG_FILE="deploy/other_file.conf"
}
stages {
// ----------------------------
stage('init-env-variables') {
steps {
script {
switch(params.Environment) {
case "Dev":
env.setProperty('CONFIG_FILE', 'deploy/file_1.conf')
break;
case "Stage":
env.setProperty('CONFIG_FILE', 'deploy/other_file.conf')
break;
}
}
}
}
// -----------------------
stage('check-params') {
steps {
sh "echo \"config file: ${CONFIG_FILE}\""
}
}
stage('build-frontend') {
steps {
sh "build-fronted.sh ${CONFIG_FILE}"
}
}
stage('deploy-backend') {
steps {
sh "deploy-backend.sh ${CONFIG_FILE}"
}
}

Jenkins Pipeline stage skip based on groovy variable defined in pipeline

I'm trying to skip a stage based a groovy variable and that variable value will be calculated in another stage.
In the below example, Validate stage is conditionally skipped based Environment variable VALIDATION_REQUIRED which I will pass while building/triggering the Job. --- This is working as expected.
Whereas the Build stage always runs even though isValidationSuccess variable is set as false.
I tried changing the when condition expression like { return "${isValidationSuccess}" == true ; } or { return "${isValidationSuccess}" == 'true' ; } but none worked.
When printing the variable it shows as 'false'
def isValidationSuccess = true
pipeline {
agent any
stages(checkout) {
// GIT checkout here
}
stage("Validate") {
when {
environment name: 'VALIDATION_REQUIRED', value: 'true'
}
steps {
if(some_condition){
isValidationSuccess = false;
}
}
}
stage("Build") {
when {
expression { return "${isValidationSuccess}"; }
}
steps {
sh "echo isValidationSuccess:${isValidationSuccess}"
}
}
}
At what phase does the when condition will be evaluated.
Is it possible to skip the stage based on the variable using when?
Based on a few SO answers, I can think of adding conditional block as below, But when options look clean approach. Also, the stage view shows nicely when that particular stage is skipped.
script {
if(isValidationSuccess){
// Do the build
}else {
try {
currentBuild.result = 'ABORTED'
} catch(Exception err) {
currentBuild.result = 'FAILURE'
}
error('Build not happened')
}
}
References:
https://jenkins.io/blog/2017/01/19/converting-conditional-to-pipeline/
stage("Build") {
when {
expression { isValidationSuccess == true }
}
steps {
// do stuff
}
}
when validates boolean values so this should be evaluate to true or false.
Source

Jenkins Pipeline Conditional Environmental Variables

I have a set of static environmental variables in the environmental directive section of a declarative pipeline. These values are available to every stage in the pipeline.
I want the values to change based on an arbitrary condition.
Is there a way to do this?
pipeline {
agent any
environment {
if ${params.condition} {
var1 = '123'
var2 = abc
} else {
var1 = '456'
var2 = def
}
}
stages {
stage('One') {
steps {
script {
...
echo env.var1
echo env.var2
...
}
}
}
}
stag('Two'){
steps {
script {
...
echo env.var1
echo env.var2
...
}
}
}
Looking for the same thing I found a nice answer in other question:
Basically is to use the ternary conditional operator
pipeline {
agent any
environment {
var1 = "${params.condition == true ? "123" : "456"}"
var2 = "${params.condition == true ? abc : def}"
}
}
Note: keep in mind that in the way you wrote your question (and I did my answer) the numbers are Strings and the letters are variables.
I would suggest you to create a stage "Environment" and declare your variable according to the condition you want, something like below:-
pipeline {
agent any
environment {
// Declare variables which will remain same throughout the build
}
stages {
stage('Environment') {
agent { node { label 'master' } }
steps {
script {
//Write condition for the variables which need to change
if ${params.condition} {
env.var1 = '123'
env.var2 = abc
} else {
env.var1 = '456'
env.var2 = def
}
sh "printenv"
}
}
}
stage('One') {
steps {
script {
...
echo env.var1
echo env.var2
...
}
}
}
stage('Two'){
steps {
script {
...
echo env.var1
echo env.var2
...
}
}
}
}
}
Suppose we want to use optional params for downstream job if it is called from upsteam job, and default params if downsteam job is called by itself.
But we don't want to have "holder" params with default value in downstream for some reason.
This could be done via groovy function:
upstream Jenkinsfile - param CREDENTIALS_ID is passed downsteam
pipeline {
stage {
steps {
build job: "my_downsteam_job_name",
parameters [string(name: 'CREDENTIALS_ID', value: 'other_credentials_id')]
}
}
}
downstream Jenkinsfile - if param CREDENTIALS_ID not passed from upsteam, function returns default value
def getCredentialsId() {
if(params.CREDENTIALS_ID) {
return params.CREDENTIALS_ID;
} else {
return "default_credentials_id";
}
}
pipeline {
environment{
TEST_PASSWORD = credentials("${getCredentialsId()}")
}
}
you can get another level of flexibility, using maps:
stage("set_env_vars") {
steps {
script {
def MY_MAP1 = [A: "123", B: "456", C: "789"]
def MY_MAP2 = [A: "abc", B: "def", C: "ghi"]
env.var1 = MY_MAP1."${env.switching_var}"
env.var2 = MY_MAP2."${env.switching_var}"
}
}
}
This way, more choices are possible.

Jenkins pipeline trigger on file

I need to run jenkins pipeline every 5 minutes and trigger stages only if /tmp/*.json exists. How to do that ?
I have the skeleton :
pipeline {
agent any
environment {
def JSON_PATH = '/tmp/*.json'
}
triggers {
cron('*/5 * * * *')
}
stages {
[...]
}
}
You're on the right track. To check file existence, you can use ls and read the exit status.
stage('Check file existence') {
steps {
script {
fileExists = sh(returnStatus: true, script: 'ls /tmp/*.json') == 0
}
}
}
stage('Do actions') {
when {
expression { fileExists }
}
steps {
<insert desired steps here>
}
}

Resources