Declarative vs Scripted
Jenkins pipelines come in two syntaxes: declarative (structured and recommended) and scripted (full Groovy flexibility).
Jenkins supports two ways to write a pipeline.
Declarative pipeline
The declarative syntax is newer, structured, and recommended for most users. It starts with pipeline { } and enforces a clear layout of agent, stages, and steps. It is easier to read and catches errors early.
Scripted pipeline
The scripted syntax is the original. It starts with node { } and is essentially a Groovy program, giving you total flexibility with loops, functions, and complex logic — but with more room to make mistakes.
Which to choose?
- Start with declarative — it covers the vast majority of needs.
- Drop into scripted (via a
script { }block inside declarative) only for advanced logic.
Example
// DECLARATIVE (recommended)
pipeline {
agent any
stages {
stage('Build') {
steps { sh 'make' }
}
}
}
// SCRIPTED (Groovy)
node {
stage('Build') {
sh 'make'
}
}When to use it
- A team adopts declarative syntax so new engineers can read and modify the pipeline without deep Groovy knowledge.
- A senior engineer drops into a scripted pipeline block inside declarative syntax to handle a complex conditional loop.
- An organization standardises on declarative pipelines so the built-in linting and Blue Ocean UI work reliably for every project.
More examples
Declarative pipeline skeleton
Shows the mandatory pipeline {} wrapper and stages {} block that define declarative syntax.
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'mvn package'
}
}
}
post {
always { cleanWs() }
}
}Scripted pipeline skeleton
The scripted pipeline starts with a node() block and is pure Groovy with no required wrapper structure.
node('linux') {
stage('Checkout') { checkout scm }
stage('Build') {
sh 'mvn package'
}
stage('Test') {
sh 'mvn test'
}
}script block inside declarative
Uses a script {} block within declarative syntax to run a Groovy loop that cannot be expressed with declarative steps alone.
pipeline {
agent any
stages {
stage('Dynamic') {
steps {
script {
// Groovy scripted code inside declarative
def targets = ['staging', 'canary']
targets.each { env ->
sh "./deploy.sh ${env}"
}
}
}
}
}
}
Discussion