Setting global variables with cps-global-libs scripts

6,795 views
Skip to first unread message

Tom Kierzkowski

unread,
Feb 3, 2016, 6:45:05 PM2/3/16
to Jenkins Users
Hello!

I've been having issues with declaring and setting variables within our /var/globals.groovy file.  I've followed the cps-global-libs suggestions and I can execute functions just fine but once it hits a function with a reference to a variable... 

groovy.lang.MissingPropertyException: No such property: beginJobEmailBody for class: groovy.lang.Binding
	at groovy.lang.Binding.getVariable(Binding.java:62)
	at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:185)
	at org.kohsuke.groovy.sandbox.impl.Checker$4.call(Checker.java:241)
	at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:238)
	at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:23)
	at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:17)
	at globals.beginBuildNotificationTestEmail(/path/to/workflowLibs/vars/globals.groovy:130)
	at WorkflowScript.run(WorkflowScript:23)
	at ___cps.transform___(Native Method)
	at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.get(PropertyishBlock.java:62)

I'm wondering how to declare these properly within the globals.groovy script.  Here are some examples of what I've tried:

beginJobEmailBody = "The ${env.JOB_NAME} job has begin on"
def beginJobEmailBody = "The ${env.JOB_NAME} job has begin on"
GString this.beginJobEmailBody = "The ${env.JOB_NAME} job has begin on";

I've also alternated between using the `this` reference to the variables to no avail:
...
/**
*  Sends an email to the team to notify of a build has begun
*/

def beginBuildNotificationTestEmail(paramMap) {
   mail body
: "${this.beginJobEmailBody} " + paramMap.STAGE + " " + paramMap.ENVIRONMENT,
 subject
: "${this.beginJobEmailSubject}" ,
 to
: "${this.emailDevOpsTeam}"
}


return this;

^ as an aside, I have the 'return this;' from when I was loading the script previously as a Closure object. Could this cause the issue as well?

Craig Rodrigues

unread,
Feb 4, 2016, 12:48:30 AM2/4/16
to Jenkins Users
I only looked at the pipeline cps-global-lib feature after reading your
e-mail.  It is some pretty advanced stuff. :)

I am not a groovy expert, but I will try to explain to the best of my
understanding and hopefully it will lead you on the right path.

When you have a Jenkinsfile or some arbitrary myscript.groovy which is
evaluated by the pipeline plugin, at runtime a class is dynamically
generated called WorkflowScript.  If your script throws an exception
which is not caught, you will see a stacktrace line like:
	at WorkflowScript.run(WorkflowScript:4)
that gives you a hint that the error occurred on line 4 of your script.


WorkflowScript is a derived class of CpsScript ( https://github.com/jenkinsci/workflow-plugin/blob/master/cps/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsScript.java ).  If you keep looking through the inheritance hierarchy,
At this point it is worth reading about Groovy Shell:

http://www.groovy-lang.org/groovysh.html

I believe the problem you are hitting with respect to global variables
Under the covers, your pipeline script is being converted into
a Java class.  As per the stackoverflow recommendation,
you should prefix your "global variables" with @Field.

So you would do something like this in your globals.groovy file:

// vars/globals.groovy

import groovy.transform.Field

@Field
String beginJobEmailBody = "The ${env.JOB_NAME} has begun"

@Field
String emailDevOpsTeam = "f...@foo.foo"

/**
*  Sends an email to the team to notify of a build has begun
*/
def beginBuildNotificationTestEmail() {
   //mail body: "${this.beginJobEmailBody} " + paramMap.STAGE + " " + paramMap.ENVIRONMENT,
   //subject: "${this.beginJobEmailSubject}" ,
   //to: "${this.emailDevOpsTeam}"

   echo "beginJobEmailBody: ${beginJobEmailBody}"
   echo "emailDevOpsTeam: ${emailDevOpsTeam}"
}

and this in your Jenkinsfile

node {
    globals.beginBuildNotificationTestEmail()
}
I'm new to groovy, so if there is a better way to do it, let me know.
However, this example does work.

--
Craig

Tom Kierzkowski

unread,
Feb 4, 2016, 7:14:45 PM2/4/16
to Jenkins Users, rod...@freebsd.org
Thank you for you help Craig!  I meant to get back earlier today but was busy refactoring code to get that all working.  Good news is, that @Field annotation worked really well.  I also realized that I hadn't been committing code back to the Jenkins managed repository and it was loading from that managed repository in Jenkins.

I've been maintaining a separate repo in version control and updating it when I want to test it it.  I'll have to write some hooks (which I haven't really done before but think it should work) to get that working in an orchestrated manner. 
Reply all
Reply to author
Forward
0 new messages