Skip to end of metadata
Go to start of metadata

Plugin Information

View Groovy on the plugin site for more information.

Older versions of this plugin may not be safe to use. Please review the following warnings before using an older version:

This plugin adds the ability to directly execute Groovy code.

Configuration

To configure available Groovy installation on your system, go to Jenkins configuration page, find section 'Groovy' and fill the form as shown bellow.


If you doesn't configure any Groovy installation and select (Default) option, plugin will fallback into calling just groovy command, assuming you have groovy binary on the default path on given machine.

Usage

To create Groovy-based project, add new free-style project and select "Execute Groovy script" in the Build section, select previously configured Groovy installation and then type your command, or specify your script file name. In the second case path taken is relatively from the project workspace directory.


The plugin also adds the functionality of the Script Console to the project configuration page. You can schedule your system management script...


...and then observe progress in the build log.


Groovy Script vs System Groovy Script

The plain "Groovy Script" is run in a forked JVM, on the slave where the build is run. It's the basically the same as running the "groovy" command and pass in the script.

The system groovy script, OTOH, runs inside the Jenkins master's JVM. Thus it will have access to all the internal objects of Jenkins, so you can use this to alter the state of Jenkins. It is similar to the Jenkins Script Console functionality.

Security

System groovy jobs has access to whole Jenkins, therefore only users with admin rights can  add system groovy build step and configure the system groovy script. Permissions are not checked when the build is triggered (i.e. also uses without admin rights can also run the script). The idea is to allow users run some well defined (defined by admin) system tasks when they need it (e.g. put slave offline/online, when user wants to start some debugging on slave). To have Jenkins instance secure, the support for Token macro plugin has to be switched off, see section bellow.

Token macro plugin support

Groovy plugin provides support for  Token Macro Plugin. Expression is GROOVY with parameter script:

${GROOVY,script = "return hudson.model.Hudson.instance.pluginManager.plugins"}

By default, the support for token macro pressing is switched off and has to be switch on in global config page.

If token macro processing via Token Macro Plugin is allowed, the evaluation of macro is done in System Groovy, therefore any user can run arbitrary system script, regardless he has administer permission!

Examples

Retrieving parameters and triggering another build

Execute a system Groovy script like:

import hudson.model.*
import hudson.AbortException
import hudson.console.HyperlinkNote
import java.util.concurrent.CancellationException

// Retrieve parameters of the current build
def foo = build.buildVariableResolver.resolve("FOO")
println "FOO=$foo"

// Start another job
def job = Hudson.instance.getJob('MyJobName')
def anotherBuild
try {
    def params = [
      new StringParameterValue('FOO', foo),
    ]
    def future = job.scheduleBuild2(0, new Cause.UpstreamCause(build), new ParametersAction(params))
    println "Waiting for the completion of " + HyperlinkNote.encodeTo('/' + job.url, job.fullDisplayName)
    anotherBuild = future.get()
} catch (CancellationException x) {
    throw new AbortException("${job.fullDisplayName} aborted.")
}
println HyperlinkNote.encodeTo('/' + anotherBuild.url, anotherBuild.fullDisplayName) + " completed. Result was " + anotherBuild.result

// Check that it succeeded
build.result = anotherBuild.result
if (anotherBuild.result != Result.SUCCESS && anotherBuild.result != Result.UNSTABLE) {
    // We abort this build right here and now.
    throw new AbortException("${anotherBuild.fullDisplayName} failed.")
}

// Do something with the output.
// On the contrary to Parameterized Trigger Plugin, you may now do something from that other build instance.
// Like the parsing the build log (see http://javadoc.jenkins-ci.org/hudson/model/FreeStyleBuild.html )
// You probably may also wish to update the current job's environment.
build.addAction(new ParametersAction(new StringParameterValue('BAR', '3')))

Retrieve properties

To retrieve properties defined in the Properties field use:

System.getProperty('FOO')

Changelog

Release 2.0 (2017-04-10)
  • Arbitrary code execution by unprivileged user (SECURITY-292)
  • continue with code cleanup - fixed Findbugs issues
Release 1.30 (2016-11-18)
  • XSS protection
  • code cleanup
Release 1.28, 1.29 (2016-01-05)
  • code cleanup
Release 1.27 (2015-08-05)
  • Callable roles are properly checked
Release 1.26 (2015-07-27)
Release 1.25 (2015-05-11)
  • Made default choice also for System Groovy script to avoid zero height of textarea (JENKINS-25455)
  • Add help file for Groovy version (JENKINS-12988)
  • Made setting Groovy installations thread-safe (JENKINS-28287)
Release 1.24 (2014-11-09)
  • Ensure non-zero height of Groovy command text box, making it default choice when adding new build step (JENKINS-25455)
Release 1.23 (2014-10-27)
Release 1.22 (2014-09-30)
Release 1.21 (2014-09-18)
Release 1.20 (2014-07-30)
  • Unable to specify multiple jars on class path for a system groovy script (JENKINS-23997)
Release 1.19 (2014-07-07)
Release 1.18 (2014-05-13)
Release 1.17 (2014-05-09)
  • Allow whitespaces in properties (passed via -D switch) (pull13)
Release 1.16 (2014-04-07)
Release 1.15 (2014-01-31)
  • Syntax highlighting
  • Syntax validation button
  • Prepare for Jenkins core upgrade to Groovy 2.x (pull9)
Release 1.14 (2013-07-02)
  • Right to run the System Groovy script changed from ADMINISTER to RUN_SCRIPTS (pull7)
Release 1.13 (2013-03-01)
  • Added build context (build, launcher, listener) into system groovy build step (pull6)
Release 1.12 (2012-03-08)
  • Fixed configuration of Token macro (pull5)
Release 1.11 (2012-02-26)
  • Enabled env. variables expansion class path, groovy and script parameters
Release 1.10 (2012-02-09)
  • Fixed possible job configuration corruption when user isn't admin (JENKINS-12080)
  • Avoid NPE, add fallback if groovy executable is misoncifured (JENKINS-11652)
Release 1.9 (2011-09-14)
Release 1.8 (2011-05-13)
  • Fixed a configuration persistence problem that can create huge config.xml
Release 1.7 (2011-03-09)
Release 1.6 (2011-02-08)
  • Fixed security issue
Release 1.5 (2010-11-10)
Release 1.4 (2009-12-29)
  • Improve error message for missing groovy executable
  • Update uses of deprecated APIs
Release 1.2
  • Added possibility to specify properties and script parameters.
  • Added script source choice (file/command) for system groovy scripts.
  • Used .exe instead of .bat on Windows (as suggested by Scott Armit).
  • Added configuration option for classpath and initial variable bindings for
    system groovy scripts.

Known bugs

  • Configuring more builders at once actually doesn't absolutely work. If you need more groovy builders in your project, you have to configure them one by one and always save project configuration before you add new one.

41 Comments

  1. Thanks for this plugin. I've found one issue however (Windows server); if the path to a groovy script passes args, then the full string is quoted. For example, in the "Groovy script file" field, you may have, "build.groovy one two" ('one' and 'two' being args).

    The call to groovy.bat will look like, C:\Groovy-1.5.4\bin\groovy.bat "c:\hudson\jobs\groovy\workspace\build.groovy one two"

    The result is an exception because groovy.bat processes everything in quotes as one long filename:
    Caught: java.io.FileNotFoundException: C:\hudson\jobs\groovy\workspace\build.groovy one two (C:\hudson\jobs\groovy\workspace\build.groovy one two

    There is a hacky workound, after your build script name, put double quotes. In my example, build.groovy" one two . This closes the first double-quote, and the last added one gets ignored.

    Thanks

  2. Yep, the file field isn't intended for script parameters. Next version should let you specify parameters without any hacks.

    1. Ok, thank you for the information. One other thing I found if you're interested. Apparently 'groovy.bat' does not handle return codes well. So if you System.exit(1) for instance out of your 'groovy' code, Hudson will still report SUCCESS. It's not Hudson's fault, but groovy.bat. Some notes on the groovy web site mention that using the native launcher fixes this (groovy.exe versus groovy.bat). I downloaded your src and changed ".bat" to ".exe" and built the 'hpi' and it works such that my return codes are not ignored.

      Regards and thanks again for this plugin!

      1. Thanks, I don't use Windows so I don't have much chance to catch these problems. I updated the code to use groovy.exe.

        1. Wow, thanks for the fast fix. I'm mostly a linux guy, but have to support some Windows stuff. Speaking of, I tried out the plugin on linux, and tried my "hack" to pass parameters, but linux being stricter about quotes, the hack doesn't work. So I added a scriptArgs textbox under the scriptFile textbox and it works great. I tested giving the path to a groovy file with spaces in it on windows, and it quoted properly: e.g. <path-to-groovy.exe> "C:\Documents and Settings\user\build.groovy" -option1 -option2

          The code is a little hacky as it's my first attempt at the plugin code, but I can get it to you if you're interested. Thanks again.

  3. Unknown User (jvizueta)

     I want to access a project's parameters from the "This build is parameterized" option in the project configuration page, how can I get this done?

     Thank you

    Regards

  4. Unknown User (ali.raza@macrovision.com)

    How can I configure groovy in hudson. My groovy installation is on a windows.

    My install location is
    C:\Program Files\Groovy\Groovy-1.6.4

    I have a SystemVariable in windows called GROOVY_HOME set to C:\Program Files\Groovy\Groovy-1.6.4
    I have added this to the path as %GROOVY_HOME%\bin

    In Hudson manage I am trying to specify the
    groovy installation name as 'Groovy1.6.4'
    GROOVY_HOME as C:\Program Files\Groovy\Groovy-1.6.4

    as soon as I type this I get

    HTTP Status 404 -

    type Status report

    message

    description The requested resource () is not available.

    Apache Tomcat/5.5.27

    Also select 'execute groovy script' does not show the text box where I can specify the groovy script.

    What am I doing wrong.

    Thanks for your help.

  5. Unknown User (mindcrime)

    Great plugin, thanks!  A couple of questions though... Is running a groovy script different from running a groovy "system command" in terms of what "stuff" is exposed to the groovy code? That is, the example listed above doesn't work for me when run as a Groovy script.. can I not get access to the hudson internals when running a Groovy script?  What can you access when running Groovy scripts? Do you have visibility into any of the Hudson information about the project, build, etc?  If so, how is it exposed to the Groovy code?

    Thanks in advance for any and all help!

  6. Unknown User (vladimir d)

    Phillip Rhodes - If you create a "System Groovy Script" you can access the hudson instance like so:

        Hudson.instance
    

    I'm using it to find all my jobs (other than the one that's executing this script, which has a null SCM) like this:

        branchJobs = Hudson.instance.items.findAll { item -> item.scm.class != NullSCM }
    

    But, I'm having a bear of a time figuring out how to get  groovy access to the environment variables, specifically from the "this build is parameterized" variable that I've defined. 

    If anybody has any clues to how this is done I'd appreciate it.

    //Vlad

    1. EDIT:

      Ok after reading your comment a second time I don't think that the link will solve the problem you have. It seams to be the same problem I had but I found a workaround yesterday (its not so nice but it is working):

      import hudson.model.*
      
      def job = Hudson.instance.getItem("JobName")
      
      def runs = job.getBuilds()
      def currentBuild = runs[0]
      def vr = currentBuild.getBuildVariableResolver()
      
      println "Current build params are:"
      println "ParamName = " + vr.resolve("ParamName")

      This will get you the values the user entered for the latest build of the given job, if this is the currently running job you will get the parameter for currently running job (tested with hudson 1.351).

      Have a look at http://wiki.jenkins-ci.org/display/HUDSON/Display+job+parameters this should do what you want

      greetings
      vkodocha

      1. After spending way too much time figuring this out, I found the following solution, which works fairly well for me (no need to submit <jobname>!)

        import hudson.model.*
        import hudson.util.*
        
        /**
         *  SPECIFIED VARIABLES (including axises -- which won't be in Build Variables)
         */
        
        def thr = Thread.currentThread()
        def build = thr?.executable
        def buildMap = build.getBuildVariables()
        
        buildMap.keySet().each { var -> println var + ": " + buildMap.get(var) }
        
        println "-" * 80
        
        /**
         *  BUILD VARIABLES
         */
        
        def envVarsMap = build.parent?.lastBuild.properties.get("envVars")
        
        envVarsMap.keySet().each { var -> println var + ": " + envVarsMap.get(var) }
        
        println "-" * 80
        

        This should produce something like the following:

        JOB_NAME: jbpm3-db/database=PostgreSQL,postgresql84
        BUILD_ID: 2011-06-09_12-02-36
        JENKINS_SERVER_COOKIE: 83xxxxxx09gjg
        HUDSON_SERVER_COOKIE: 83xxxxxx09gjg
        BUILD_TAG: jenkins-database=PostgreSQL,postgresql84-32
        JBPM_VERSION: 3.2.x
        BUILD_NUMBER: 32
        database: PostgreSQL,postgresql84
        --------------------------------------------------------------------------------
        _: /usr/lib/jvm/java-1.6.0-sun.x86_64/bin/java
        BUILD_ID: 2011-06-09_12-02-36
        BUILD_NUMBER: 32
        BUILD_TAG: jenkins-database=PostgreSQL,postgresql84-32
        BUILD_URL: http://..../hudson/job/jbpm3-db/./database=PostgreSQL,postgresql84/32/
        CLASSPATH:
        EXECUTOR_NUMBER: 0
        G_BROKEN_FILENAMES: 1
        HISTSIZE: 1000
        HOME: /...
        HOSTNAME: ...
        HUDSON_CONFIG_DIR: ...
        HUDSON_HOME: ...
        HUDSON_SERVER_COOKIE: 83xxxxxx09gjg
        HUDSON_URL: http://.../hudson/
        INPUTRC: /etc/inputrc
        JAVA_HOME: /usr/lib/jvm/java-1.6.0-sun.x86_64
        JAVA_OPTS: -Dprogram.name=run.sh -server ....
        JBOSS_HOME: /var/lib/jbossas
        JBPM_VERSION: 3.2.x
        JENKINS_HOME: ...
        JENKINS_SERVER_COOKIE: 83xxxxxx09gjg
        JENKINS_URL: ...
        JOB_NAME: jbpm3-db/database=PostgreSQL,postgresql84
        JOB_URL: ....
        LANG: en_US.UTF-8
        LD_LIBRARY_PATH: /usr/lib/jvm/java-1.6.0-sun-1.6.0.22.x86_64/jre/lib/amd64/server:...
        LESSOPEN: |/usr/bin/lesspipe.sh %s
        LOGNAME: ...
        MAIL: /var/spool/mail/...
        NLSPATH: /usr/dt/lib/nls/msg/%L/%N.cat
        NODE_LABELS: ...
        NODE_NAME:
        PATH: /usr/local/bin:/bin:/usr/bin:...
        PWD: /var/lib/jbossas/bin
        SHELL: /bin/sh
        SHLVL: 2
        SVN_REVISION_1: 6952
        SVN_REVISION_2: 17261
        SVN_URL_1: ...
        SVN_URL_2: ...
        TERM: xterm
        TEST_PARAM: tags/stable
        USER: ...
        WORKSPACE: <http://.../hudson/job/jbpm3-db/./database=PostgreSQL,postgresql84/ws/>
        XFILESEARCHPATH: /usr/dt/app-defaults/%L/Dt
        

        There is some overlap between the two, but matrix/axises can only be found in the "specified" parameters/properties.

  7. Is it possible to access the properties set by a parametrized build form within a "Execute System Groovy script" (file or when directly entered in the text box). I can access the properties in an external groovy script ("Execute Groovy script") by going over the System.getenv() path. But when trying the same inside a system one the properties are not set in the environment.

    I tried to add the properties with the "Variable bindings" by specifying testName=$NameOfParameter but this is also not working. Basically the plugin is not resolving $NameOfParameter to the value of this field.

    I think the simplest solution would just be to add the properties from the parametrized build to the environment of the groovy script.

    1. Same problem.  Bindings work good with strings, but they don't seem to expand build parameters...is this the way it's supposed to work?

      1. By the way, how about using a spellchecker for your help section chief :)

        "Define varibale bingings (in the properties file format). Spefified variables can be addressed from the script."

  8. Unknown User (vladimir d)

    I finally got my script to fetch the parameterized build value, here's how:

     

    def job = Hudson.instance.getItem("JobName");   
    def envVars= job.lastBuild.properties.get("envVars");  // this is actually the currently running build, if the script is executed in "JobName"
    println envVars["MyParameterName"];
    

    hope this helps.

    1. You are my hero, thanks, that works!

    2. added Parameterized System Groovy script page, here is a less hacky recipe :

      def build = Thread.currentThread().executable
      
      def resolver = build.buildVariableResolver
      def myfooparam = resolver.resolve("MYFOOPARAM")
      println "MYFOOPARAM=${myfooparam}"
      

      gives (provided my build was started with MYFOOPARAM=foobar)

      Started by user dnozay
      MYFOOPARAM=foobar
      Finished: SUCCESS
  9. Since this script show me user and password on Console Script it doesn't works within a "system groovy script", it show SYSTEM/SYSTEM.
    Any one knows who to know the user's credentials within a task?

    Thanks! (smile)

    /* CODE */
    import org.acegisecurity.Authentication;
    import org.acegisecurity.context.SecurityContextHolder;
    println("Usuario: "+(String)hudson.model.User.current());
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    String g=auth.getCredentials();
    println("Password: "+ g);
    /* CODE */

    1. Unknown User (dbaret)

      I don't anderstand what is this problem.

      I tried this :
      println(hudson.model.User.current().getFullName());

      it works under the admin script consol but not in an execute system script groovy command : I get SYSTEM and not my user name.

      It's a bug?

  10. How would I get the workspace of my current build?

    1. via Thread.currentThread().executable.

      1. Sorry to ask, but how is Thread.currentThread().executable working for concurrent builds and multiple nodes/slaves?

  11. I wonder whether the "forked JVM/script" part of this plugin is particular useful?

    Cause I can archive the very same by running a shell script like (as build job) like

    #!/bin/bash
    exec /path/to/groovy /path/to/script.groovy
    

    To comfort various groovy installations, I could setup env variables like GROOVY_BIN_1, GROOVY_BIN_2 and so on and change script above into

    #!/bin/bash
    exec ${GROOVY_BIN_5} /path/to/script.groovy
    

    So, why providing something which is already there?

  12. After having playing around with this plugin, I consider it a waste of time - to put it mildly.

    As an example, Jenkins variables are resolved in <scriptSource /> but NOT in </scriptParameters />.

    <hudson.plugins.groovy.Groovy>
              <scriptSource>
                <scriptFile>${SCRIPT_dir}/hello.groovy</scriptFile>
              </scriptSource>
              <scriptParameters>${MESSAGE}</scriptParameters>
    </hudson.plugins.groovy.Groovy>
    
  13. Anyone know how to use the variable bindings for system groovy scrpits?

    1. First you'll need to access the build instance, see Parameterized System Groovy script

      Then supposing it's a standard free style job, see http://javadoc.jenkins-ci.org/hudson/model/FreeStyleBuild.html

  14. m l

    I'd like to invoke (i.e. submit to the build queue) a parameterised job with two parameters, A and B. I'd like to invoke the job using the default value for A and supply an overridden value for B. I'd also like to wait for the submitted job to complete. Can anyone provide explicit code for doing this? Thanks.

    1. A system Groovy script may help, see scheduleBuild2 may be the safest choice. Something like:

      hudson.model.Hudson.instance.getJob('My Job Name').scheduleBuild2(0, Cause.UserIdCause, ...)
      
  15. Generic system script that can be used to fail the current build of other builds are not successful

    /**
     * Fails the current build if any of the specified builds are failing
     * 
     * Required a Variable Bindings
     * projectNames     - A comma delimited list of projects to check
     * 
     * Optional Variable Bindings
     * requireOnlyMostRecent    - If true only the most recent build among the list of projects must be successful
     */
    
    try {
      requireOnlyMostRecent;
    }
    catch (MissingPropertyException e) {
      requireOnlyMostRecent = false;
    }
    
    def mostRecentSuccess = null;
    def mostRecentFailure = null;
    
    for (projectName in projectNames.split(",")) {
        def proj = hudson.model.Hudson.instance.getItem(projectName);
    
        if (proj == null) {
            println projectName + " DOES NOT EXIST, failing build";
            return false;
        }
        else if (proj.lastBuild == null) {
            if (!requireOnlyMostRecent) {
                println projectName + ": has no builds, failing build";
                return false;
            }
        }
        else if (proj.lastBuild.result != hudson.model.Result.SUCCESS) {
            if (!requireOnlyMostRecent) {
                println projectName + ": the last build was not successful, failing build";
                return false;
            }
            
            if (mostRecentFailure == null || mostRecentFailure < proj.lastBuild.time) {
                println projectName + ": the last build was not successful, recording mostRecentFailure";
                mostRecentFailure = proj.lastBuild.time;
            }
            else {
                println projectName + ": the last build was not successful, but is not mostRecentFailure";
            }
        }
        else {
            println projectName + ": the last build was successful";
            
            if (mostRecentSuccess == null || mostRecentSuccess < proj.lastBuild.time) {
                mostRecentSuccess = proj.lastBuild.time;
            }
        }
    }
    
    if (!requireOnlyMostRecent) {
        //All builds must be successful, continue with build
        return true;
    }
    
    println "mostRecentSuccess: " + mostRecentSuccess;
    println "mostRecentFailure: " + mostRecentFailure;
    return mostRecentSuccess != null && (mostRecentFailure == null || mostRecentSuccess > mostRecentFailure);
    
  16. Does anyone know how to define parameters or environment variables for the current build in a System Groovy script?

    Reason: System Groovy runs on master, but can access other builds info and trigger builds. Normal Groovy runs on the node. How to transmit info between both?

    1. To set properties using the System Groovy Script:

      import hudson.model.*
      
      def pa = new ParametersAction([
      new StringParameterValue("foo1", "bar1"),
      new StringParameterValue("foo2", "bar2")
      ])
      
      // add variable to current job
      Thread.currentThread().executable.addAction(pa)
      

      Hope that helps.

      If you need to run it as a normal Groovy script, you'll probably need to do the following: http://stackoverflow.com/questions/9996315/jenkins-packages-on-groovy-classpath

      1. Or even...

        import hudson.*
        import hudson.model.*
        def build = Thread.currentThread().executable
        build.getEnvironments().add(Environment.create(new EnvVars(["key1":"val1","key2":"val2"])))
        
  17. Don't want to lost my script, may be somebody will need it. Lot of things this can do (most of copypaste part from another scripts some of them already on this page).

    We have build jobs which only build code (job ends with "-build" suffix) and depoy jobs (the same name as build job, but "-CI" suffix).

    Task was to determine does code already built (and skip build step which save time and resources because don't need to rerun build job again) otherwise to trigger build job, and then retrieve component version and trigger deployment tool (to pass arguments which WAR to deploy). 

    build job system groovy script:

    • Determines COMPONENT_VERSION from Maven, OR (!) if you specifu POM_XML=relativepath/pom.xml if will parse XML, in some cases it is correct way) - this step is merging of 2 separate scripts, which was before, now if option POM_XML injected via envinjector plugin - groovy runs xml parsin algorithm, otherwise just takes mavenVer from maven build result
    • Detetmines MAX_SVN_REVISION - It is already exist SVN_REVISION = SVN_REVISION_1 & SVN_REVISION_2,3,4 and so on, to make things simplier script compares all SVN_REVISION_N variables and choose the highest (may be to summarize them is more correct, but all works fine for now).
    • Determines does it release or *-SNAPSHOT version and set RELEASE=true/false accordingly. Needed only to skip Sonar which is always fails if release (releases goes with Artifactory plugin), so Sonar configured to skip itself if RELEASE=true
    // basic classes
    import hudson.*
    import hudson.model.*
    import hudson.util.*
    
    def thr = Thread.currentThread();
    def currentBuild = thr?.executable;
    def workspace = currentBuild.getModuleRoot().absolutize().toString();
    
    
    //////START///// DETERMINE MAX SVN REVISION ///////////
    def SVN_REVISION = currentBuild.getEnvironment()["SVN_REVISION"]
    def SVN_REVISION_1 = currentBuild.getEnvironment()["SVN_REVISION_1"]
    def SVN_REVISION_2 = currentBuild.getEnvironment()["SVN_REVISION_2"]
    if ( SVN_REVISION < SVN_REVISION_1 ) { SVN_REVISION = SVN_REVISION_1; }
    if ( SVN_REVISION < SVN_REVISION_2 ) { SVN_REVISION = SVN_REVISION_2; }
    println "[TSS] MAX_SVN_REVISION="+SVN_REVISION
    //currentBuild.getEnvironments().add(Environment.create(new EnvVars(["MAX_SVN_REVISION":SVN_REVISION])))
    currentBuild.addAction(new ParametersAction(new StringParameterValue("MAX_SVN_REVISION", SVN_REVISION)));
    //////END///// DETERMINE MAX SVN REVISION ///////////
    
    //////START///// PARSE XML OR GET MAVENVER ///////////
    if ( currentBuild.getEnvironment().containsKey("POM_XML") ) {
     POM_XML = currentBuild.getEnvironment()["POM_XML"]
     println "[TSS] POM_XML=${POM_XML} (hard coded -> XML needs to be parsed)"
     def project = new XmlSlurper().parse(new File("$workspace/$POM_XML"));
     mavenVer = project.version.toString();
    } else {
     println '[TSS] Automatically retrieve component version from Maven build.'
     println '[TSS] If it is wrong (usually it is ok, and this message just info), you can parse pom file with XML.'
     println '[TSS] For this please specify environment variable POM_XML=relative_path_to/pom.xml (usually the same as specified for in maven "Root POM" section)'
     mavenVer = currentBuild.getParent().getModules().toArray()[0].getVersion();
    }
    //////END///// PARSE XML OR GET MAVENVER ///////////
    
    println '[TSS] COMPONENT_VERSION='+mavenVer
    
    def newParamAction = new hudson.model.ParametersAction(new hudson.model.StringParameterValue("COMPONENT_VERSION", mavenVer));
    currentBuild.addAction(newParamAction);
    
    // Determine if RELEASE=true => Sonar will skip code checks, otherwise it fails
    if ( mavenVer.matches(".*SNAPSHOT") ) {
        currentBuild.addAction(new hudson.model.ParametersAction(new hudson.model.BooleanParameterValue("RELEASE", false)));
        println '[TSS] RELEASE=false';
    } else {
        currentBuild.addAction(new hudson.model.ParametersAction(new hudson.model.BooleanParameterValue("RELEASE", true)));
        println '[TSS] RELEASE=true';
    }
    

    deploy job system groovy script:

    • Suggest build job name simply replacing -CI to -build suffix, but you have option to specify it manually (if build job is different from autosuggestion) -> just inject variable BUILD_JOB_NAME=buildjobname and script will use it.
    • Get COMPONENT_VERSION from last build job, which is setted up with prevous script.
    • Determines MAX_SVN_REVISION (see above) and compares it with the same from the last build job -> if this the same it don't triggers build job, because don't need to waste time to compile the same code twice (othewise it triggering build job)
    // base classes
    import hudson.*
    import hudson.model.*
    import hudson.util.*
    // classes for triggering another job
    import hudson.AbortException
    import hudson.console.HyperlinkNote
    import java.util.concurrent.CancellationException
    
    // GET INFO ABOUT CI JOB (which is current job)
    def thr = Thread.currentThread();
    def currentBuild = thr?.executable;
    def CI_JOB_NAME = currentBuild.getEnvironment()["JOB_NAME"]
    
    //////START///// DETERMINE BUILD JOB NAME ///////////
    if ( currentBuild.getEnvironment().containsKey("BUILD_JOB_NAME") ) {
     BUILD_JOB_NAME = currentBuild.getEnvironment()["BUILD_JOB_NAME"]
     println "[TSS] BUILD_JOB_NAME=${BUILD_JOB_NAME} (hard coded)"
    } else {
     BUILD_JOB_NAME = (CI_JOB_NAME =~ /-CI/).replaceFirst("-build")
     println "[TSS] BUILD_JOB_NAME=${BUILD_JOB_NAME} (auto suggestion)"
     println '[TSS] If it is wrong (usually it is ok, and this message just info), you can setup it manually.'
     println '[TSS] For this please specify environment variable "BUILD_JOB_NAME=Build-Job-Name"'
    }
    //////END///// DETERMINE BUILD JOB NAME ///////////
    
    
    def BUILD_JOB = Hudson.instance.getJob(BUILD_JOB_NAME)
    
    
    //////START///// DETERMINE CI MAX SVN REVISION ///////////
    def CI_SVN_REVISION = currentBuild.getEnvironment()["SVN_REVISION"]
    def CI_SVN_REVISION_1 = currentBuild.getEnvironment()["SVN_REVISION_1"]
    def CI_SVN_REVISION_2 = currentBuild.getEnvironment()["SVN_REVISION_2"]
    if ( CI_SVN_REVISION < CI_SVN_REVISION_1 ) { CI_SVN_REVISION = CI_SVN_REVISION_1; }
    if ( CI_SVN_REVISION < CI_SVN_REVISION_2 ) { CI_SVN_REVISION = CI_SVN_REVISION_2; }
    println '[TSS] '+CI_SVN_REVISION+' = SVN REVISION OF JOB '+CI_JOB_NAME
    //////END///// DETERMINE CI MAX SVN REVISION ///////////
    
    
    //////START///// DETERMINE BUILD MAX SVN REVISION ///////////
    def BUILD_SVN_REVISION =  BUILD_JOB.getLastBuild().getEnvironment()["MAX_SVN_REVISION"]
    //def BUILD_SVN_REVISION_1 =  BUILD_JOB.getLastBuild().getEnvironment()["SVN_REVISION_1"]
    //def BUILD_SVN_REVISION_2 =  BUILD_JOB.getLastBuild().getEnvironment()["SVN_REVISION_2"]
    //if ( BUILD_SVN_REVISION < BUILD_SVN_REVISION_1 ) { BUILD_SVN_REVISION = BUILD_SVN_REVISION_1; }
    //if ( BUILD_SVN_REVISION < BUILD_SVN_REVISION_2 ) { BUILD_SVN_REVISION = BUILD_SVN_REVISION_2; }
    println '[TSS] '+BUILD_SVN_REVISION+' = SVN REVISION OF JOB '+BUILD_JOB_NAME
    //////END///// DETERMINE BUILD MAX SVN REVISION ///////////
    
    
    //////START///// COMPARING REVISIONS AND TRIGGER BUILD JOB IF NEED
    if ( BUILD_SVN_REVISION != CI_SVN_REVISION ) {
      println "[TSS] Versions are not the same -> need to trigger build job"
      // don't need this var, but leave it as example of setup up env (not sys) var
      currentBuild.getEnvironments().add(Environment.create(new EnvVars(["BUILD_TRIGGER":"true"])))
      //////START///// TRIGGER BUILD JOB BLOCK /////////// (see examples on https://wiki.jenkins-ci.org/display/JENKINS/Groovy+plugin )
      def job = Hudson.instance.getJob(BUILD_JOB_NAME)
      def anotherBuild
      try {
        def params = [
        // UNCOMMENT/ and MODIFY THIS IF NEED TO PASS ANY ARGS TO BUILD JOB
        //  new StringParameterValue('FOO', foo),
        ]
        def future = job.scheduleBuild2(0, new Cause.UpstreamCause(currentBuild), new ParametersAction(params))
        println "Waiting for the completion of " + HyperlinkNote.encodeTo('/' + job.url, job.fullDisplayName)
        anotherBuild = future.get()
      } catch (CancellationException x) {
        throw new AbortException("${job.fullDisplayName} aborted.")
      }
      println HyperlinkNote.encodeTo('/' + anotherBuild.url, anotherBuild.fullDisplayName) + " completed. Result was " + anotherBuild.result
    
      // Check that it succeeded
      currentBuild.result = anotherBuild.result
      def anotherBuildResult = anotherBuild.result.toString()
    
      if (anotherBuildResult != 'SUCCESS' && anotherBuildResult != 'UNSTABLE') {
          // We abort this build right here and now.
          throw new AbortException("${anotherBuild.fullDisplayName} failed.")
      }
      ////// END ///// TRIGGER BUILD JOB BLOCK ///////////
    } else {
      println '[TSS] Build job SVN revision is current which means that current code already build -> NOT TRIGGERING BUILD JOB'
      currentBuild.getEnvironments().add(Environment.create(new EnvVars(["BUILD_TRIGGER":"false"])))
    }
    //////END///// COMPARING REVISIONS AND TRIGGER BUILD JOB IF NEED
    
    
    /////START//// RETRIEVE LATEST COMPONENT_VERSION AND SVN REVISION
    // THIS WORKS ONLY IF MAVEN BUILD SUCCESFULL
    //def BUILD_JOB_COMPONENT_VERSION = BUILD_JOB.getLastBuild().getParent().getModules().toArray()[0].getVersion();
    // THIS WORKS ONLY WHEN WE CREATE THIS VARIABLE ON BUILD JOB SIDE
    def BUILD_JOB_COMPONENT_VERSION =  BUILD_JOB.getLastBuild().getEnvironment()["COMPONENT_VERSION"]
    // NOT IMPORTANT AND WORKS ONLY IF PROPER GROOVY SCRIPT EXIST ON BUILD JOB SIDE, OTHERWISE JOB WILL RETURN NONE
    // SET UP AS ENV VAR (not system) -> otherwise will break nolio
    def LATEST_BUILD_SVN_REVISION =  BUILD_JOB.getLastBuild().getEnvironment()["MAX_SVN_REVISION"]
    if ( LATEST_BUILD_SVN_REVISION ) {
      currentBuild.getEnvironments().add(Environment.create(new EnvVars(["MAX_SVN_REVISION":LATEST_BUILD_SVN_REVISION])))
      println '[TSS] Last Build job svn_revision = '+LATEST_BUILD_SVN_REVISION
    } else {
      currentBuild.getEnvironments().add(Environment.create(new EnvVars(["MAX_SVN_REVISION":"NONE"])))
    }
    // Nolio can use only System variables
    currentBuild.addAction(new ParametersAction(new StringParameterValue("COMPONENT_VERSION", BUILD_JOB_COMPONENT_VERSION)));
    /////END//// RETRIEVE LATEST COMPONENT_VERSION AND SVN REVISION
    
  18. Does anyone have a problem specifying classpath for a script using the class path edit box build option targeting Windows?  

    When I specify multiple jar files in the edit box, the script cannot import a Java class specified with 'import' statement.  If I use -cp "jarfile1.jar;jarfile2.jar;jarfile3.jar" in the Groovy Parameters edit box, the script can import the specified class.  

    So it seems to me that quote around classpath is required on Windows, because using the class path edit box does work on Unices.

    Thanks,

  19. I had the need to create system groovy script to modify build parameters. I was unable to find a direct answer to my question through googling, so I thought I would deposit my solution here in hopes that it will find another who is in need.

    In this case, I have one string type parameter that I want to programmatically alter. I don’t want to monkey with any of the other parameters .

    import hudson.model.*
    
    // get the original parameters as they were submitted
    current_param_actions = build.getAction(ParametersAction.class)
    def current_params = current_param_actions.getParameters()
    
    // create a new empty set of parameters that will eventually contain our substituting value
    Collection<? extends ParameterValue> new_params = new ArrayList<>();
    
    // copy all the submitted parameters, except the one that we are altering
    current_params.each() {
    	if ( ! it.getName().equals("NAME_OF_PARAM_TO_ALTER") ) {
    		new_params.add( it )
    	}
    }
    
    // determine new value of the parameter we wish to override and add it to our set of parameters
    new_value = func_to_find_value()
    new_params.add( new StringParameterValue("NAME_OF_PARAM_TO_ALTER", new_value ) )
    
    // replace the submitted set of values with our altered set of values
    build.actions.remove(current_param_actions)
    new_param_actions = current_param_actions.createUpdated(new_params)
    build.actions.add(new_param_actions)
    
    // some debugging output for sanity checking when examining console output
    build.getAction(ParametersAction.class).getParameters().each {
    	println "[info] parameter ${it.name}:"
    	println "[info] " + it.dump()
    	println "-" * 80
    }
    

    h/t to these two questions, which helped me arrive at my answer:

    http://stackoverflow.com/questions/10882515/how-to-retrieve-jenkins-build-parameters-using-the-groovy-api

    https://groups.google.com/forum/#\!topic/jenkinsci-users/szhuDfCvpiE

  20. I too would love to know how to use the classpath field on the execute system groovy script step. The non-system groovy script will let me use @Grab and do something like this:

    @Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.7.2' )

    However, the system groovy script, which runs in the Jenkins JRE does not have ivy available to do that. I've heard that you could load the ivy jar into the Jenkins war to make this work, but it isn't a very viable option as you'll need to do it after each upgrade.

    I've tried adding something like "/tmp/ivy-2.4.0-rc1.jar" to the classpath field but it doesn't make any difference. Looking through the plugin source code, it seems to apply this variable here in the SystemGroovy.java

    CompilerConfiguration compilerConfig = new CompilerConfiguration();        
    if (classpath != null) {            
    	compilerConfig.setClasspath(classpath);        
    }
    

    So it looks like it is used, but it appears to make no difference as I still get "java.lang.NoClassDefFoundError: org/apache/ivy/Ivy" when running a script with a @Grab

    What I'm really looking for is a way of running any arbitrary groovy script (using other libraries), but in the context of the Jenkins master so I can get access to jobs and config.

    Any ideas anyone?

    Thanks!

  21. I keep running into Caused by: java.lang.ClassNotFoundException: org.codehaus.groovy.tools.GroovyStarter

    when executing a Groovy script from a job. When I paste the command from the console into a prompt on the slave, it works fine. As I read on the net this migt be caused by setting GROOVY_HOME, but I don't do that (and setting it doesn't solve it)

  22. It seems the provided example

    build.addAction(new ParametersAction(new StringParameterValue('BAR', '3')))

    does not work (anymore) with Jenkins 2.5. On an attempt to execute this code the following message is logged in the Jenkins console log:

    May 19, 2016 11:10:24 AM hudson.model.ParametersAction filter
    WARNING: Skipped parameter `BAR` as it is undefined on `test`. Set `-Dhudson.model.ParametersAction.keepUndefinedParameters`=true to allow undefined parameters to be injected as environment variables or `-Dhudson.model.ParametersAction.safeParameters=[comma-separated list]` to whitelist specific parameter names, even though it represents a security breach

    I tried to invoke

    def newEnv = new EnvVars ( "BAR", "3" )
    def paramAction = new ParametersAction()
    paramAction.buildEnvVars( build, newEnv )

    Then there is no warning message in the log, but the attempt to refer (later in the job definition) the variable in a shell script reveals an empty value, i.e. the variable is not transferred to the build (defined outside the Groovy script)
    Is there any workaround for this problem?

    1. The answer to your question is in the error message you posted. This is related to a security update, that by default will block all parameters you create through groovy.

      You can pass in these arguments inside the jenkins.xml

      Set `-Dhudson.model.ParametersAction.keepUndefinedParameters`=true to allow undefined parameters
      to be injected as environment variables or `-Dhudson.model.ParametersAction.safeParameters=[comma-separated list]`
      to whitelist specific parameter names, even though it represents a security breach
      
  23. Thanks for the plugin, it is helping us a lot. We have a groovy script which will execute as a post build step(system groovy script) in all our Jenkins jobs(300+). This groovy script requires few additional jar files to be available in classpath. So if we have any change in external jars versions, it is hard for us to configure these jars in all the jobs from plugin configuration. Can we have a option to add classpath jars at global level(manage jenkins) configuration?