Groovy as the Engine Behind Jenkinsfiles
Jenkins Pipeline, whether written as a Jenkinsfile using Declarative or Scripted syntax, is fundamentally a Groovy program executed inside the Jenkins Groovy CPS (Continuation-Passing Style) interpreter; Jenkins parses the file, compiles it as Groovy, and runs it step by step so that pipeline state can be serialized to disk, letting a build survive a Jenkins controller restart mid-pipeline.
Cricket analogy: Much like DRS (Decision Review System) can pause live play and later resume exactly from that ball once the third umpire rules, Jenkins Pipeline's Groovy CPS engine can pause a running build mid-step and resume it later without losing state.
Declarative vs Scripted Pipelines
Declarative pipelines wrap Groovy in a constrained pipeline { agent { } stages { stage('Build') { steps { } } } } structure that limits what you can write directly, favoring readability and validation, whereas Scripted pipelines drop you into raw Groovy inside a node { } block where you can use loops, try/catch, and arbitrary Groovy methods without the Declarative directive restrictions.
Cricket analogy: Much like T20 cricket imposes strict overs-per-bowler rules to keep the format standardized, Declarative Pipeline imposes a constrained pipeline { stages { } } structure, while Scripted Pipeline is closer to an unlimited-overs format where any Groovy logic is allowed.
Shared Libraries and Reusable Groovy Logic
Shared Libraries let teams package reusable Groovy code — global functions in vars/*.groovy and classes in src/ — that any Jenkinsfile across the organization can import with @Library('my-shared-lib') _ at the top of the file, turning common patterns like Slack notifications or Docker build steps into a single callable step such as notifySlack(status: 'SUCCESS').
Cricket analogy: Much like a national cricket board issues a standard coaching manual every franchise's academy must follow, a Jenkins Shared Library issues standard Groovy functions like notifySlack() that every team's Jenkinsfile can import via @Library.
// Jenkinsfile
@Library('my-shared-lib') _
pipeline {
agent any
environment {
APP_VERSION = "1.2.${env.BUILD_NUMBER}"
}
stages {
stage('Build') {
steps {
sh './gradlew build'
}
}
stage('Test') {
steps {
sh './gradlew test'
}
}
stage('Notify') {
steps {
notifySlack(status: 'SUCCESS', version: env.APP_VERSION)
}
}
}
post {
failure {
notifySlack(status: 'FAILURE', version: env.APP_VERSION)
}
}
}Groovy CPS Transformation and Its Limits
Because Jenkins must be able to pause and resume a pipeline at any step (for example while waiting on an input step or an agent to become available), it transforms your Groovy code using CPS, which rewrites method calls into continuations; this means certain standard Groovy idioms — like using .collect { } inside heavily nested closures, or calling non-whitelisted Java library methods, or using try/catch around CPS-transformed calls incorrectly — can throw NotSerializableException or CPS-related errors unless you wrap them in @NonCPS or restructure the code.
Cricket analogy: Much like DRS reviews are restricted to specific dismissal types and can't be invoked for every decision, CPS transformation restricts which Groovy constructs (like certain non-whitelisted Java calls) can run safely inside a serializable pipeline step.
Declarative Pipeline still allows dropping into raw Groovy via a script { } block inside any steps { } section, giving you an escape hatch for loops or conditionals without abandoning the Declarative structure entirely.
Avoid non-serializable objects (like a raw java.io.File or an open database connection) as pipeline-level variables in Scripted Pipelines — CPS needs to serialize the pipeline's state to disk at every step, and non-serializable fields cause the build to fail with a NotSerializableException.
- Jenkinsfiles are Groovy programs executed by Jenkins' CPS (Continuation-Passing Style) interpreter, which lets pipelines pause and resume.
- Declarative Pipeline enforces a
pipeline { stages { steps { } } }structure for validation and readability. - Scripted Pipeline gives raw Groovy inside
node { }, allowing arbitrary loops, conditionals, and method calls. - Shared Libraries package reusable Groovy functions (
vars/) and classes (src/) importable via@Library('name') _. - CPS transformation restricts certain Groovy idioms; use
@NonCPSfor code that can't be safely serialized. - A
script { }block inside Declarative Pipeline lets you drop into raw Groovy when directives aren't enough. - Non-serializable objects stored as pipeline variables cause
NotSerializableExceptionunder CPS.
Practice what you learned
1. What Jenkins mechanism allows a pipeline to pause mid-step and resume later?
2. What is the main structural difference between Declarative and Scripted Pipeline?
3. How do you import a Jenkins Shared Library into a Jenkinsfile?
4. Where do global pipeline step functions in a Shared Library live?
5. Why might a Groovy method call need `@NonCPS` in a Jenkins pipeline?
Was this page helpful?
You May Also Like
Groovy and Gradle
Learn how Gradle uses Groovy as its build-script DSL, covering tasks, dependencies, plugins, and multi-project builds.
Groovy Scripting for Automation
Learn how to use Groovy as a scripting language for file processing, running system commands, parsing command-line arguments, and building automation tools.
Groovy and Testing with Spock
Learn how the Spock Framework uses Groovy's syntax to write expressive, structured tests with given-when-then blocks, data tables, and built-in mocking.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics