Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I need keyword `this` while using `env` or `param` in DSL closure in Jenkinsfile

I have code based on "structured DSL" concept.

// vars/buildStuff.groovy
def call(body) {

    def config = [:]
    body.resolveStrategy = Closure.DELEGATE_FIRST
    body.delegate = config
    body()

    node {
        assert env
        assert params
        doStuff()
    }
} 

In this code I can access env and params directly, as expected.

However in the top level Jenkinsfile:

buildStuff {
    someParam=params.SOME_PARAM
    buildId=env.BUILD_ID
}

Causes java.lang.NullPointerException: Cannot get property 'SOME_PARAM' on null object. I have to work around that by writing this as:

buildStuff {
    someParam=this.params.SOME_PARAM
    buildId=this.env.BUILD_ID
}

Why is that the case? According to all examples in Pipelines documentation I should be able to access env and params directly. What am I doing wrong?

like image 993
vartec Avatar asked May 20 '17 00:05

vartec


People also ask

How do you access environment variables in Jenkins pipeline?

Indeed just use ${env. JOB_NAME} to access a known variable. However if you need to access environment variable where name is given by another variable (dynamic access), just use env["your-env-variable"] .

What is env in Jenkins file?

Jenkins Environment Variable is a global variable exposed through the env variable and used anywhere in the Jenkinsfile . Any value stored in the env variable gets stored as a String type. Environment Variables can be set either at the pipeline top level, at the specific stage level, or inside the script block.

How do you pass a parameter in Jenkins pipeline script?

Using build parameters, we can pass any data we want: git branch name, secret credentials, hostnames and ports, and so on. Any Jenkins job or pipeline can be parameterized. All we need to do is check the box on the General settings tab, “This project is parameterized”: Then we click the Add Parameter button.


1 Answers

It's an issue with the resolveStrategy.

def config = [:]
body.resolveStrategy = Closure.DELEGATE_FIRST
body.delegate = config

The config you provide resolves any property to its value or null, thus the owner is not queried for it. In you example the owner is just this. That's why it works.

Depending on what you're actually trying to achieve, OWNER_FIRST might be a better strategy. If you cannot change this, better use a data structure without defaults for properties.

like image 118
tynn Avatar answered Nov 08 '22 11:11

tynn