问题
I have a shared global function on PublishGitHub.groovy looks like this:
#!/usr/bin/env groovy
def call(body)
{
def config = [:]
body.resolveStrategy = Closure.DELEGATE_FIRST
body.delegate = config
echo "\u001B[32mINFO: Publishing...\u001B[m"
body()
echo "\u001B[32mINFO: End Publish...\u001B[m"
}
And a code on my JenkinsFile:
environment {
VERSION = "v1.3.${env.BUILD_NUMBER}"
}
stages {
stage ('Publish WebAPI'){
steps{
echo "\u001B[32mINFO: Start Publish...\u001B[m"
PublishGitHub{
echo "This is a body with version: ${env.VERSION}"
}
}
}
}
And this is my output:
[Pipeline] echo
INFO: Start Publish...
[Pipeline] echo
INFO: Publishing...
[Pipeline] }
And follow next error:
java.lang.NullPointerException: Cannot get property 'VERSION' on null object
Because inside the body I do not have access to the environment variables?
回答1:
Your shared library code runs outside of the workflow CPS context, that is why closure you pass to the vars script does not recognize env
property. You can fix this problem by passing a reference to the workflow script. If you call your function like this
PublishGitHub(this) {
echo "This is a body with version: ${env.VERSION}"
}
and you apply a small modification to vars/PublishGitHub.groovy
script like:
#!/usr/bin/env groovy
def call(config, body) {
body.resolveStrategy = Closure.DELEGATE_FIRST
body.delegate = config
echo "\u001B[32mINFO: Publishing...\u001B[m"
body()
echo "\u001B[32mINFO: End Publish...\u001B[m"
}
then you will run your pipeline successfully:
[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Publish WebAPI)
[Pipeline] echo
[32mINFO: Start Publish...[m
[Pipeline] echo
[32mINFO: Publishing...[m
[Pipeline] echo
This is a body with version: v1.3.537
[Pipeline] echo
[32mINFO: End Publish...[m
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
If you want to limit the scope for the shared library, you can always simply pass env
instead of this
and change vars/PublishGitHub.groovy
to something like this:
#!/usr/bin/env groovy
def call(env, body) {
def config = [
env: env
]
body.resolveStrategy = Closure.DELEGATE_FIRST
body.delegate = config
echo "\u001B[32mINFO: Publishing...\u001B[m"
body()
echo "\u001B[32mINFO: End Publish...\u001B[m"
}
In this scenario you give your shared library an access to environment variables only.
回答2:
In order to make the environment variables that you have defined in your Jenkinsfile available in your shared library code you have to pass a this parameter on the call to your shared library method.
For example (below is a partial extract only of a full pipeline file):
// JENKINS-42730
@Library('pipeline-shared-library')_
import org.blah.MySharedLibraryClass
// END JENKINS_42730
pipeline {
agent { any }
environment {
FOO = (new MySharedLibraryClass(config, this)).myMethod("StringVar1", "StringVar2")
}
}
My Shared Library:
package org.blah
import groovy.text.SimpleTemplateEngine
public class MySharedLibraryClass implements Serializable {
def engine = new SimpleTemplateEngine()
def config
def steps
def ArtifactoryHelper(config, steps) {
this.config = config
this.steps = steps
}
def log(msg){
//Allows me to print to Jenkins console
steps.println(msg)
}
def myMethod(var1, var2) {
....
}
The this parameter I referred to above maps to steps in the shared library code. You should then be able to resolve "VERSION=${steps.env.VERSION}"
in your shared library code.
Also see this post.
Notes:
pipeline-shared-library
is the ID I gave the library in Manage Jenkins > Configure System
回答3:
Szymon's answer works. I added "p.env = env"
def toParam(final Closure body) {
final def p = [:]
p.env = env
body.resolveStrategy = Closure.DELEGATE_FIRST
body.delegate = p
body()
return p
}
来源:https://stackoverflow.com/questions/52043397/jenkins-get-environment-variables-in-the-body-of-a-global-function