Groovy scripts let you do way more than just click buttons in Jenkins.

Jenkins itself is built on Java, but it exposes a powerful scripting interface via Groovy. This means you can automate nearly anything Jenkins can do, from triggering builds and deploying artifacts to manipulating build history and even interacting with the Jenkins API directly. It’s like having a programmable Jenkins that you control with code.

Let’s see it in action. Imagine you have a Jenkins job that needs to deploy a WAR file to a Tomcat server. Instead of manually copying files, you can use a Groovy script within a "Script" build step to automate this.

// Jenkinsfile or Script build step
def tomcatHome = "/opt/tomcat" // Replace with your actual Tomcat path
def warFile = "/path/to/your/build/artifact.war" // Replace with your artifact path
def deployDir = "${tomcatHome}/webapps"

sh """
  cp ${warFile} ${deployDir}/
  echo "Deployment complete: ${warFile} copied to ${deployDir}"
"""

This simple script uses sh to execute shell commands directly. It copies a specified WAR file to the Tomcat webapps directory. This is the core idea: use Groovy to orchestrate shell commands, API calls, or even Java code.

The real power comes when you start interacting with Jenkins’ internal objects. Every Jenkins job, build, node, and even the global Jenkins configuration is accessible as a Groovy object.

Consider a scenario where you want to automatically clean up old build artifacts. You can write a script to iterate through jobs and delete builds older than a certain age.

// Script build step
import jenkins.model.Jenkins
import hudson.model.Job

def retentionDays = 14 // Keep builds for 14 days
def now = System.currentTimeMillis()

Jenkins.instance.getAllItems(Job.class).each { job ->
    println "Processing job: ${job.fullName}"
    job.builds.each { build ->
        if ((now - build.timeInMillis) / (1000 * 60 * 60 * 24) > retentionDays) {
            println "  Deleting build #${build.number} from ${job.fullName}"
            build.delete() // This is the magic!
        }
    }
}
println "Build cleanup complete."

Here, Jenkins.instance gives you access to the global Jenkins object. getAllItems(Job.class) retrieves all jobs. We then iterate through each job’s builds and check their age. If a build is older than retentionDays, build.delete() is called. This isn’t just a shell command; it’s directly manipulating Jenkins’ internal state.

You can also use Groovy to interact with Jenkins’ REST API. This is useful for external scripts or for getting more complex data than the standard API provides.

// Example of fetching build status via REST API (simplified)
@Field def jenkinsUrl = "http://your-jenkins-url"
@Field def jobName = "your-job-name"
@Field def buildNumber = 123

def apiUrl = "${jenkinsUrl}/job/${jobName}/${buildNumber}/api/json"

def client = new HTTPBuilder(jenkinsUrl)
client.get(path: "/job/${jobName}/${buildNumber}/api/json") { resp ->
    if (resp.status == 200) {
        def buildData = resp.data
        println "Build #${buildNumber} status: ${buildData.result}"
    } else {
        println "Error fetching build data: ${resp.status}"
    }
}

This example uses a hypothetical HTTPBuilder (you’d likely use groovy.http.HTTPBuilder or a similar library) to make an HTTP GET request to the Jenkins API and retrieve build information.

The "Script" build step in Jenkins is the most common place to run these scripts. You can also embed them directly into Jenkinsfile for Pipeline jobs, which is the modern and recommended approach for defining your CI/CD workflows.

When you write scripts, you’re essentially writing Java code with Groovy’s syntactic sugar. You have access to all Java libraries and Jenkins’ internal Java classes. This gives you immense flexibility. Need to parse an XML report? Use Groovy’s XMLSlurper. Need to send an email? Use JavaMail. Need to interact with a remote system? Use any Java networking library.

The one thing most people don’t realize is that Jenkins.instance isn’t just a singleton; it’s a dynamic proxy that resolves to the currently running Jenkins instance, allowing your script to operate within the context of that specific Jenkins master, even if the script is being executed by a different JVM (e.g., on an agent). This means you can reliably access and manipulate the master’s state from a script running anywhere, as long as it has the necessary permissions.

Once you’ve mastered basic build automation and artifact management with Groovy, the next logical step is to explore how to use Jenkins Pipeline Shared Libraries to encapsulate and reuse your Groovy code across multiple projects, making your automation even more robust and maintainable.

Want structured learning?

Take the full Jenkins course →