All skills
Skillintermediate
Scripted Pipeline Syntax Reference
Complete reference for Jenkins Scripted Pipeline syntax using Groovy.
Claude Code Knowledge Pack7/10/2026
Overview
Scripted Pipeline Syntax Reference
Complete reference for Jenkins Scripted Pipeline syntax using Groovy.
Overview
Scripted Pipeline is written using Groovy, providing maximum flexibility and power. Unlike Declarative Pipeline, Scripted Pipeline uses imperative programming and has few structural restrictions.
Basic Structure
node {
stage('Build') {
echo 'Building...'
}
stage('Test') {
echo 'Testing...'
}
stage('Deploy') {
echo 'Deploying...'
}
}
node Block
The node block allocates an executor (agent) for the pipeline.
// Run on any available agent
node {
// steps here
}
// Run on specific labeled agent
node('linux') {
// steps here
}
// Run on Docker agent
node('docker') {
// steps here
}
// Run on specific node
node('master') {
// steps here
}
// Run on agent matching expression
node('linux && java11') {
// steps here
}
stage Block
Stages organize pipeline into logical sections (mainly for visualization).
node {
stage('Checkout') {
checkout scm
}
stage('Build') {
sh 'make build'
}
stage('Test') {
sh 'make test'
}
}
Variables and Data Types
Variable Declaration
// Using def (recommended for local scope)
def myString = 'Hello'
def myNumber = 42
def myBoolean = true
def myList = [1, 2, 3]
def myMap = [key1: 'value1', key2: 'value2']
// Without def (global scope - use cautiously)
globalVar = 'accessible everywhere'
// Typed variables
String name = 'Jenkins'
Integer count = 10
Boolean flag = false
List items = ['a', 'b', 'c']
Map<String, String> config = [env: 'prod', version: '1.0']
String Interpolation
def name = 'World'
// Double quotes for interpolation
def greeting = "Hello, ${name}!"
// Single quotes for literal strings
def literal = 'Hello, ${name}!' // Won't interpolate
// Multi-line strings
def multiLine = """
This is a
multi-line string
with ${name}
"""
// Multi-line without interpolation
def multiLineLiteral = '''
This is a
literal multi-line string
with ${name}
'''
Control Structures
if-else
node {
def environment = 'production'
if (environment == 'production') {
echo 'Deploying to production'
} else if (environment == 'staging') {
echo 'Deploying to staging'
} else {
echo 'Deploying to development'
}
// Ternary operator
def message = (environment == 'production') ? 'PROD' : 'NON-PROD'
}
for Loops
node {
// Iterate over list
def items = ['build', 'test', 'deploy']
for (item in items) {
echo "Step: ${item}"
}
// Iterate with index
for (int i = 0; i < items.size(); i++) {
echo "${i}: ${items[i]}"
}
// Range iteration
for (i in 0..5) {
echo "Number: ${i}"
}
// Each method
items.each { item ->
echo "Processing ${item}"
}
// Each with index
items.eachWithIndex { item, index ->
echo "${index}: ${item}"
}
}
while Loops
node {
def counter = 0
while (counter < 5) {
echo "Counter: ${counter}"
counter++
}
}
switch Statement
node {
def environment = 'staging'
switch(environment) {
case 'development':
echo 'Dev environment'
break
case 'staging':
echo 'Staging environment'
break
case 'production':
echo 'Production environment'
break
default:
error 'Unknown environment'
}
}
Error Handling
try-catch-finally
node {
try {
sh 'make build'
sh 'make test'
} catch (Exception e) {
echo "Build failed: ${e.message}"
currentBuild.result = 'FAILURE'
throw e // Re-throw if needed
} finally {
echo 'Cleaning up...'
sh 'make clean'
}
}
try-catch with Different Exception Types
node {
try {
sh 'risky-command'
} catch (hudson.AbortException e) {
echo "Process was aborted: ${e.message}"
} catch (Exception e) {
echo "General error: ${e.message}"
currentBuild.result = 'FAILURE'
}
}
Catching Specific Errors
node {
try {
def result = sh(script: 'test-command', returnStatus: true)
if (result != 0) {
error "Command failed with exit code ${result}"
}
} catch (Exception e) {
echo "Handling error: ${e}"
// Continue or fail
}
}
Methods and Functions
Defining Methods
// Method definition
def buildApplication() {
echo 'Building application...'
sh 'mvn clean package'
}
// Method with parameters
def deploy(String environment, String version) {
echo "Deploying version ${version} to ${environment}"
sh "kubectl set image deployment/app app=${version}"
}
// Method with return value
def getVersion() {
return sh(script: 'git describe --tags', returnStdout: true).trim()
}
// Usage
node {
buildApplication()
def version = getVersion()
deploy('production', version)
}
@NonCPS Methods
Methods that should not use Continuation Passing Style (for complex Groovy operations).
@NonCPS
def parseJson(String json) {
def jsonSlurper = new groovy.json.JsonSlurper()
return jsonSlurper.parseText(json)
}
@NonCPS
def processData(data) {
// Complex Groovy logic that doesn't involve pipeline steps
return data.collect { it.toUpperCase() }
}
node {
def json = '{"name": "Jenkins", "version": "2.0"}'
def parsed = parseJson(json)
echo "Name: ${parsed.name}"
// WARNING: Cannot use pipeline steps (sh, echo, etc.) in @NonCPS methods
}
Parallel Execution
Basic Parallel
node {
stage('Parallel Tests') {
parallel(
'Unit Tests': {
node('linux') {
sh 'make unit-test'
}
},
'Integration Tests': {
node('linux') {
sh 'make integration-test'
}
},
'Smoke Tests': {
node('linux') {
sh 'make smoke-test'
}
}
)
}
}
Parallel with failFast
node {
stage('Deploy to Regions') {
parallel(
failFast: true, // Stop all if one fails
'Region US-EAST': {
sh 'deploy-us-east.sh'
},
'Region US-WEST': {
sh 'deploy-us-west.sh'
},
'Region EU': {
sh 'deploy-eu.sh'
}
)
}
}
Dynamic Parallel Execution
node {
def branches = [:]
def environments = ['dev', 'qa', 'staging']
for (int i = 0; i < environments.size(); i++) {
def env = environments[i] // Important: capture variable
branches["Deploy to ${env}"] = {
node {
echo "Deploying to ${env}"
sh "deploy.sh ${env}"
}
}
}
parallel branches
}
Working with Credentials
Username and Password
node {
withCredentials([usernamePassword(
credentialsId: 'my-credentials',
usernameVariable: 'USERNAME',
passwordVariable: 'PASSWORD'
)]) {
sh '''
echo "Username: $USERNAME"
# Use $PASSWORD in commands
'''
}
}
Secret Text
node {
withCredentials([string(
credentialsId: 'api-token',
variable: 'API_TOKEN'
)]) {
sh 'curl -H "Authorization: Bearer $API_TOKEN" https://api.example.com'
}
}
SSH Key
node {
withCredentials([sshUserPrivateKey(
credentialsId: 'ssh-key',
keyFileVariable: 'SSH_KEY',
usernameVariable: 'SSH_USER'
)]) {
sh '''
ssh -i $SSH_KEY $SSH_USER@server.example.com 'deploy.sh'
'''
}
}
Multiple Credentials
node {
withCredentials([
usernamePassword(credentialsId: 'docker-hub', usernameVariable: 'DOCKER_USER', passwordVariable: 'DOCKER_PASS'),
string(credentialsId: 'api-key', variable: 'API_KEY')
]) {
sh 'docker login -u $DOCKER_USER -p $DOCKER_PASS'
sh 'curl -H "X-API-Key: $API_KEY" https://api.example.com'
}
}
Environment Variables
Setting Environment Variables
node {
// Using withEnv
withEnv(['ENV=production', 'VERSION=1.0']) {
sh 'echo "Environment: $ENV, Version: $VERSION"'
}
// Direct assignment
env.MY_VAR = 'value'
sh 'echo $MY_VAR'
// From shell command
env.GIT_COMMIT_SHORT = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim()
}
Accessing Environment Variables
node {
echo "Build number: ${env.BUILD_NUMBER}"
echo "Job name: ${env.JOB_NAME}"
echo "Workspace: ${env.WORKSPACE}"
def branch = env.BRANCH_NAME ?: 'main'
echo "Branch: ${branch}"
}
Common Wrappers
Timestamps
timestamps {
node {
echo 'This output will have timestamps'
sh 'sleep 5'
echo 'Done'
}
}
Timeout
timeout(time: 30, unit: 'MINUTES') {
node {
sh 'long-running-command'
}
}
// With activity timeout
timeout(time: 5, unit: 'MINUTES', activity: true) {
node {
// Timeout if no console output for 5 minutes
sh 'command-with-output'
}
}
Retry
retry(3) {
node {
sh 'flaky-test-command'
}
}
// With custom condition
retry(3) {
try {
sh 'test-command'
} catch (Exception e) {
if (e.message.contains('timeout')) {
throw e // Retry
} else {
return // Don't retry
}
}
}
Lock
lock(resource: 'deployment-lock', inversePrecedence: true) {
node {
echo 'Only one build can deploy at a time'
sh 'deploy.sh'
}
}
AnsiColor
ansiColor('xterm') {
node {
sh 'ls --color=always'
}
}
Working with Docker
Using Docker Images
node {
docker.image('maven:3.8.1-adoptopenjdk-11').inside {
sh 'mvn --version'
sh 'mvn clean package'
}
// With additional arguments
docker.image('maven:3.8.1').inside('-v /tmp:/tmp -e MAVEN_OPTS="-Xmx1024m"') {
sh 'mvn clean install'
}
}
Building Docker Images
node {
def image = docker.build("my-app:${env.BUILD_NUMBER}")
// With custom Dockerfile
def image2 = docker.build("my-app:latest", "-f Dockerfile.prod .")
// Push to registry
docker.withRegistry('https://registry.example.com', 'registry-credentials') {
image.push()
image.push('latest')
}
}
Running Docker Containers
node {
def container = docker.image('nginx:latest').run('-p 8080:80')
try {
// Run tests against container
sh 'curl http://localhost:8080'
} finally {
container.stop()
}
}
Working with Git
Basic Checkout
node {
checkout scm
// Or explicit checkout
checkout([
$class: 'GitSCM',
branches: [[name: '*/main']],
userRemoteConfigs: [[
url: 'https://github.com/user/repo.git',
credentialsId: 'github-credentials'
]]
])
}
Git Operations
node {
// Get commit info
def commit = sh(script: 'git rev-parse HEAD', returnStdout: true).trim()
def shortCommit = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim()
def branch = sh(script: 'git rev-parse --abbrev-ref HEAD', returnStdout: true).trim()
echo "Commit: ${commit}"
echo "Short: ${shortCommit}"
echo "Branch: ${branch}"
// Tag
sh "git tag -a v${env.BUILD_NUMBER} -m 'Build ${env.BUILD_NUMBER}'"
sh 'git push origin --tags'
}
Stash and Unstash
node('build-agent') {
stage('Build') {
sh 'make build'
stash name: 'build-artifacts', includes: 'target/*.jar'
}
}
node('deploy-agent') {
stage('Deploy') {
unstash 'build-artifacts'
sh 'deploy.sh target/*.jar'
}
}
Input and Approval
node {
stage('Build') {
sh 'make build'
}
stage('Approval') {
def userInput = input(
message: 'Deploy to production?',
parameters: [
choice(name: 'ENVIRONMENT', choices: ['staging', 'production'], description: 'Target environment'),
string(name: 'VERSION', defaultValue: '1.0', description: 'Version to deploy')
],
submitter: 'admin,ops'
)
echo "Deploying ${userInput.VERSION} to ${userInput.ENVIRONMENT}"
}
stage('Deploy') {
sh "deploy.sh ${userInput.ENVIRONMENT} ${userInput.VERSION}"
}
}
Build Parameters
properties([
parameters([
string(name: 'DEPLOY_ENV', defaultValue: 'staging', description: 'Deployment environment'),
choice(name: 'VERSION', choices: ['1.0', '1.1', '2.0'], description: 'Version'),
booleanParam(name: 'RUN_TESTS', defaultValue: true, description: 'Run tests')
])
])
node {
echo "Environment: ${params.DEPLOY_ENV}"
echo "Version: ${params.VERSION}"
if (params.RUN_TESTS) {
sh 'make test'
}
}
Accessing Build Information
node {
// Current build
echo "Build number: ${currentBuild.number}"
echo "Build result: ${currentBuild.result}" // SUCCESS, FAILURE, UNSTABLE, ABORTED
echo "Display name: ${currentBuild.displayName}"
echo "Duration: ${currentBuild.duration}"
// Set build properties
currentBuild.displayName = "#${env.BUILD_NUMBER} - ${env.BRANCH_NAME}"
currentBuild.description = "Deployed version ${version}"
currentBuild.result = 'SUCCESS'
// Previous build
if (currentBuild.previousBuild) {
echo "Previous result: ${currentBuild.previousBuild.result}"
}
}
Complete Example
@Library('shared-library@master') _
// Build properties
properties([
buildDiscarder(logRotator(numToKeepStr: '10')),
disableConcurrentBuilds(),
parameters([
choice(name: 'ENVIRONMENT', choices: ['dev', 'staging', 'production'], description: 'Target environment'),
booleanParam(name: 'SKIP_TESTS', defaultValue: false, description: 'Skip tests')
])
])
// Variables
def version
def dockerImage
// Helper methods
def buildApp() {
sh 'mvn clean package'
}
@NonCPS
def parseVersion(String pomXml) {
def matcher = (pomXml =~ /<version>(.+)<\\/version>/)
return matcher[0][1]
}
// Main pipeline
timestamps {