Jenkins pipeline - how to load a Jenkinsfile without first calling node()?

喜夏-厌秋 提交于 2021-01-28 09:00:40

问题


I have a somewhat unique setup where I need to be able to dynamically load Jenkinsfiles that live outside of the src I'm building. The Jenkinsfiles themselves usually call node() and then some build steps. This causes multiple executors to be eaten up unnecessarily because I need to have already called node() in order to use the load step to run a Jenkinsfile, or to execute the groovy if I read the Jenkinsfile as a string and execute it.

What I have in the job UI today:

@Library(value='myGlobalLib@head', changelog=fase) _

node{
    load "${JENKINSFILES_ROOT}/${PROJECT_NAME}/Jenkinsfile"
}

The Jenkinsfile that's loaded usually also calls node(). For example:

node('agent-type-foo'){
    someBuildFlavor{
        buildProperty = "some value unique to this build"
        someConfig = ["VALUE1", "VALUE2", "VALUE3"]
        runTestTarget = true
    }
}

This causes 2 executors to be consumed during the pipeline run. Ideally, I load the Jenkinsfiles without first calling node(), but whenever I try, I get an error message stating:

"Required context class hudson.FilePath is missing
Perhaps you forgot to surround the code with a step that provides this, such as: node"

Is there any way to load a Jenkinsfile or execute groovy without first having hudson.FilePath context? I can't seem to find anything in the doc. I'm at the point where I'm going to preprocess the Jenkinsfiles to remove their initial call to node() and call node() with the value the Jenkinsfile was using, then load the rest of the file, but, that's somewhat too brittle for me to be happy with.


回答1:


When using load step Jenkins evaluates the file. You can wrap your Jenkinsfile's logics into a function (named run() in my example) so that it will load but not run automatically.

def run() {
    node('agent-type-foo'){
        someBuildFlavor{
            buildProperty = "some value unique to this build"
            someConfig = ["VALUE1", "VALUE2", "VALUE3"]
            runTestTarget = true
        }
    }
}

// This return statement is important in the end of Jenkinsfile
return this 

Call it from your job script like this:

def jenkinsfile
node{
    jenkinsfile = load "${JENKINSFILES_ROOT}/${PROJECT_NAME}/Jenkinsfile"
}
jenkinsfile.run()

This way there is no more nested node blocks because the first gets closed before run() function is called.



来源:https://stackoverflow.com/questions/53950119/jenkins-pipeline-how-to-load-a-jenkinsfile-without-first-calling-node

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!