Skip to main content

Creating Scripted Pipelines

1. Understanding Groovy Syntax

Jenkins Pipeline scripts are written in Groovy, a dynamic language that runs on the Java Virtual Machine (JVM). Understanding basic Groovy syntax is essential for writing effective Jenkins pipelines.

Concept Description Example
Variables Declared with def keyword or inferred type
def projectName = 'MyProject'
def buildNumber = 123
Functions Defined using def keyword followed by function name and parameters
def greet(String name) {
    return "Hello, ${name}!"
}
Control Structures Supports standard control flow like if/else, for, while
if (buildNumber > 100) {
    echo "Build is large"
} else {
    echo "Build is small"
}
Lists and Maps Lists use square brackets, maps use curly braces
def fruits = ['apple', 'banana']
def person = [name: 'John', age: 30]

Example: Basic Pipeline Script

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                echo 'Building...'
            }
        }
    }
}

2. Using Node and Stage Blocks

Property Description Example
node Allocates a node to run the pipeline or stage on. node('label') { ... }
stage Defines a stage in the pipeline with a name and steps. stage('Build') { steps { ... } }

Example: Basic Node and Stage Usage

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                echo 'Building...'
            }
        }
    }
}

Example: Node with Label

pipeline {
    agent {
        node {
            label 'ubuntu-latest'
        }
    }
    stages {
        stage('Test') {
            steps {
                sh 'npm test'
            }
        }
    }
}
Note: The node block is used to allocate an executor for the pipeline or stage, and stage blocks define distinct phases of a Jenkins pipeline.

3. Defining Variables and Functions

Variable Type Declaration Description Usage Example
Environment Variables env.VAR_NAME Accessible in pipeline steps, set via Jenkins UI or CLI sh "echo ${env.VAR_NAME}"
Pipeline Variables params.VAR_NAME Defined in pipeline script or via UI, used for configuration echo "Build number: ${params.BUILD_NUMBER}"
Global Variables global.VAR_NAME Defined at the top level of pipeline script
def globalVar = "value"
echo globalVar

Example: Setting and Using Pipeline Variables

pipeline {
    agent any
    parameters {
        string(name: 'BUILD_NUMBER', defaultValue: '1', description: 'Build number')
    }
    stages {
        stage('Example') {
            steps {
                script {
                    def buildNumber = params.BUILD_NUMBER
                    echo "Current build number: ${buildNumber}"
                }
            }
        }
    }
}

Example: Using Environment Variables

pipeline {
    agent any
    environment {
        NODE_ENV = 'production'
        API_URL = 'https://api.example.com'
    }
    stages {
        stage('Print Environment') {
            steps {
                sh "echo NODE_ENV is ${env.NODE_ENV}"
                sh "echo API_URL is ${env.API_URL}"
            }
        }
    }
}

Example: Defining Functions in Jenkins Pipeline

def deployToStaging() {
    sh "echo Deploying to staging environment"
}

pipeline {
    agent any
    stages {
        stage('Deploy') {
            steps {
                script {
                    deployToStaging()
                }
            }
        }
    }
}
Note: Functions defined in the script block can be reused throughout the pipeline.

4. Using Try-Catch-Finally Blocks

Try-catch-finally blocks in Jenkins scripted pipelines provide structured error handling and resource management. They allow you to handle exceptions gracefully, execute cleanup code, and ensure that critical operations are completed even when errors occur.

Block Description Usage
try Contains code that might throw an exception. try { // code } catch (e) { ... }
catch Handles exceptions thrown in the try block. catch (Exception e) { // handle error }
finally Executes code regardless of whether an exception occurred. finally { // cleanup code }

Example: Basic Try-Catch-Finally Usage

pipeline {
    agent any
    stages {
        stage('Example') {
            steps {
                script {
                    try {
                        sh 'echo "Starting operation..."'
                        sh 'exit 1' // Simulate failure
                    } catch (e) {
                        echo "Caught exception: ${e}"
                    } finally {
                        echo "Cleanup operations..."
                    }
                }
            }
        }
    }
}

Example: Handling Specific Exceptions

pipeline {
    agent any
    stages {
        stage('Example') {
            steps {
                script {
                    try {
                        sh 'ls /nonexistent'
                    } catch (FileNotFoundException e) {
                        echo "File not found: ${e}"
                    } catch (Exception e) {
                        echo "General error occurred: ${e}"
                    } finally {
                        echo "Always executed"
                    }
                }
            }
        }
    }
}
Note: The finally block is always executed, even if there's a return statement in the try or catch block.

Key Points

  • The try block contains code that might throw an exception.
  • The catch block handles specific or general exceptions.
  • The finally block runs regardless of exception occurrence.
  • Use specific exception types for better error handling.

5. Implementing Conditional Logic

Condition Type Description Usage Example
when Defines when a stage should run based on various conditions like branch, environment, or changes in SCM
when {
    branch 'main'
}
when changeset Triggers the stage only if there are changes in the SCM
when {
    changeset '**/*.js'
}
when environment Runs the stage only if an environment variable matches a specific value
when {
    environment name: 'ENV', value: 'production'
}

Example: Using when with multiple conditions

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                echo 'Building...'
            }
        }
        stage('Deploy') {
            when {
                allOf {
                    branch 'main'
                    environment name: 'ENV', value: 'production'
                }
            }
            steps {
                echo 'Deploying to production'
            }
        }
    }
}
Note: The when directive can be used at the stage or parallel stage level.
Warning: Make sure to properly escape special characters in conditions to avoid syntax errors.

6. Using Loops

Loop Type Description Example
for Iterates over a list or range
for (int i = 0; i < 5; i++) {
    echo "Iteration: ${i}"
}
while Continues while a condition is true
int count = 0
while (count < 3) {
    echo "Count: ${count}"
    count++
}
until Continues until a condition becomes true
int counter = 0
until (counter == 2) {
    echo "Until loop: ${counter}"
    counter++
}

Example: For Loop with List

def fruits = ['apple', 'banana', 'orange']
for (fruit in fruits) {
    echo "Fruit: ${fruit}"
}

Example: While Loop with Conditional Check

int i = 0
while (i < 3) {
    echo "Processing item: ${i}"
    i++
}

7. Calling External Scripts

Script Type Invocation Method Notes
Shell Script sh 'script.sh' Executes shell script in Jenkins workspace
Python Script sh 'python3 script.py' Requires Python installed on Jenkins node
Groovy Script sh 'groovy script.groovy' Can be executed within Jenkins pipeline

Example: Calling External Shell Script

pipeline {
    agent any
    stages {
        stage('Run External Script') {
            steps {
                sh 'chmod +x ./deploy.sh'
                sh './deploy.sh'
            }
        }
    }
}

Example: Passing Parameters to Script

pipeline {
    agent any
    stages {
        stage('Execute With Args') {
            steps {
                sh "bash ./script.sh --env production --version v1.2.3"
            }
        }
    }
}
Note: Ensure scripts are executable and located in the Jenkins workspace or accessible via a shared filesystem.

8. Using Shared Libraries

Shared Libraries in Jenkins allow you to reuse code across multiple pipelines. They are stored as Git repositories and can contain functions, variables, and other reusable components.

Property Description Example
library.name Name of the library to be used in the pipeline mySharedLib
library.version Version of the library to use (e.g., branch, tag, or commit) master
library.defaultVersion Default version to use if not specified in the pipeline v1.0

Example: Using a Shared Library in a Pipeline

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                script {
                    // Load the shared library
                    def myLib = library('mySharedLib@master')
                    // Use a function from the library
                    myLib.myFunction()
                }
            }
        }
    }
}
Note: Shared libraries must be defined in Jenkins under Manage Jenkins > Configure System > Global Tool Configuration.
Warning: Ensure that the shared library repository is secure and accessible to all Jenkins agents.

Key Points

  • Shared libraries promote code reuse across pipelines.
  • They are managed via Git repositories and can be versioned.
  • Libraries can contain Groovy classes, functions, and global variables.

9. Handling Exceptions

Exception Type Description Handling Strategy
IOException Thrown when I/O operations fail, such as file read/write errors. Use try-catch blocks to handle and log the error appropriately.
AbortException Indicates that a build was aborted by the user or system. Implement catch (AbortException e) to gracefully handle build interruptions.
GroovyRuntimeException Occurs during Groovy script execution errors. Wrap in try-catch and provide meaningful error messages to the user.

Example: Catching and Logging Exceptions

try {
    sh "ls -l /nonexistent"
} catch (IOException e) {
    echo "Caught IOException: " + e.getMessage()
    currentBuild.result = "FAILURE"
}

Example: Handling Build Aborts

try {
    // Some long-running operation
    sh "sleep 30"
} catch (AbortException e) {
    echo "Build was aborted: " + e.getMessage()
    // Optionally mark build as unstable or failed
    currentBuild.result = "UNSTABLE"
}
Note: Always ensure that exceptions are logged for debugging purposes and that the build status is updated accordingly to reflect the outcome.

10. Using Parallel Execution

Parallel execution in Jenkins allows you to run multiple stages concurrently, which can significantly reduce build times for independent tasks.

Property Description Example
parallel Defines a set of stages to run in parallel
parallel (
    stage1: {
        // Stage 1 steps
    },
    stage2: {
        // Stage 2 steps
    }
)

Example: Parallel Pipeline Stages

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                echo 'Building...'
            }
        }
        stage('Test') {
            parallel {
                stage('Unit Tests') {
                    steps {
                        echo 'Running unit tests'
                    }
                }
                stage('Integration Tests') {
                    steps {
                        echo 'Running integration tests'
                    }
                }
            }
        }
        stage('Deploy') {
            steps {
                echo 'Deploying...'
            }
        }
    }
}
Note: All parallel stages must complete before the pipeline continues to the next stage.

Key Points

  • Use parallel to define concurrent stages.
  • Each parallel stage runs independently and can have its own agent or environment.
  • Parallel stages must be completed before the pipeline proceeds to subsequent stages.

Was this article helpful?