ChrisP
ChrisP

Reputation: 137

Jenkinsfile won't update variable's value

I'm trying to set a variable on a switch statement. I created a simple function to do this, but it won't actually update the value. here is the function I created:

def VAR1 = 'this is not the real value';

stage('Set Variables') {
    steps {
        script{
            SetVariables()
        }
    }
}

def SetVariables() {
    sh 'echo $BRANCH_NAME'
    switch(BRANCH_NAME){
        case 'BranchA':
            sh 'echo We are in the right branch'
            VAR1 = "This is the correct String"
            sh 'echo $VAR1 is the variable's value'
            break
    }
}

Both of the echos are showing, but the value of VAR1 remains 'this is not the real value'

If I move this code into a steps/script block it works perfectly fine.

stage('Set Variables') {
            steps {
                script{
                    switch(BRANCH_NAME){
                        case 'BranchA':
                            sh 'echo We are in the right branch'
                            VAR1 = "This is the correct String"
                            sh 'echo $VAR1 is the variable's value'
                            break
                    }
                }
            }
        }

This bit of code will expand as I add more variables and cases and I'd like to have it stored at the bottom in a function to keep things clean and readable. What am I missing here that is preventing the variable from being updated properly in a function?

Upvotes: 1

Views: 1594

Answers (2)

MaratC
MaratC

Reputation: 6869

One of Groovy quirks is that if you want a global, you have to define it without def:

VAR1 = 'this is not the real value';
// the rest unchanged

I believe your code will work as expected then.

Upvotes: 2

Vivere
Vivere

Reputation: 2270

I believe this issue is about scoping.

Let's understand the behaviour. Taking into account this pipeline:

def MY_VAR = 'hello world'
fun()

pipeline {
    agent any

    stages {
        stage('Hello') {
            steps {
                script {
                    println("Pipeline Before: ${MY_VAR}")
                    fun()
                    println("Pipeline After : ${MY_VAR}")
                }
            }
        }
    }
}

def fun() {
    println("Fun before: ${MY_VAR}")
    VAR1 = 'hello world, in fun'
    println("Fun after : ${MY_VAR}")
}

If we run this we get the following error:

groovy.lang.MissingPropertyException: No such property: MY_VAR for class: groovy.lang.Binding

Let's delete the fun() call in the second line. We get the following output

Pipeline Before: hello world

groovy.lang.MissingPropertyException: No such property: MY_VAR for class: groovy.lang.Binding

Let's delete the first println("Fun before: ${MY_VAR}") from the function. We get:

Pipeline Before: hello world
[Pipeline] echo
Fun after : hello world, in fun
[Pipeline] echo
Pipeline After : hello world

We can see the value is unaltered. To combat these issue, we can use the attach our variable to the env object as env.MY_VAR

The pipeline will look as follows

env.MY_VAR = 'hello world'
fun()

pipeline {
    agent any

    stages {
        stage('Hello') {
            steps {
                script {
                    println("Pipeline Before: ${env.MY_VAR}")
                    fun()
                    println("Pipeline After : ${env.MY_VAR}")
                }
            }
        }
    }
}

def fun() {
    println("Fun before: ${env.MY_VAR}")
    env.VAR1 = 'hello world, in fun'
    println("Fun after : ${env.MY_VAR}")
}

We will get:

[Pipeline] echo
Fun before: hello world
[Pipeline] echo
Fun after : hello world, in fun
[Pipeline] echo
Pipeline Before: hello world, in fun
[Pipeline] echo
Fun before: hello world, in fun
[Pipeline] echo
Fun after : hello world, in fun
[Pipeline] echo
Pipeline After : hello world, in fun

Which is the desired output. You could argue about the use of the env object, maybe you could parameterize your function. I would do it like this since if I would need the variable in a bash/powershell/etc script, I could access it via the environment variables.

Upvotes: 3

Related Questions