Skip to content

Instantly share code, notes, and snippets.

@surajsaini95
Last active April 20, 2020 04:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save surajsaini95/8457b663a05974cf7d018db3ba02f78a to your computer and use it in GitHub Desktop.
Save surajsaini95/8457b663a05974cf7d018db3ba02f78a to your computer and use it in GitHub Desktop.

Going Declarative in Jenkins

Jenkins pipeline plugin version 2.5 introduces support for Declarative pipelines.

Declarative pipeline contains a predefined hierarchy to create Jenkins pipelines but it still uses the DSL steps as its base with a well-defined structure around the steps. It gives you the ability to control all aspects of a pipeline execution in a simple, straight-forward manner.

Declarative Pipeline is a more recent feature of Jenkins Pipeline which:

  • provides richer syntactical features over Scripted Pipeline syntax, and

  • is designed to make writing and reading Pipeline code easier.

Declarative Pipelines Syntax

The basic statements and expressions which are valid in Declarative Pipeline follow the same rules as scripted pipeline with the following exceptions:

  • The top-level of the Pipeline must be a block, specifically: pipeline { }. It contains all the instructions (wrapped inside section or directives) needed for the entire build process.

  • No semicolons as each statement has to be on its own line.

  • Blocks must only consist of directives or steps.

  • A property reference statement is treated as a no-argument method invocation. So, for example, input is treated as input().

Lets have a look at a basic pipeline

pipeline {
    agent any
    stages {
        stage('Greetings') {
            steps {
                sh 'echo "I am a declarative pipeline"'
            }
        }
    }
}

Sections

Agent

  • The agent section specifies where the entire Pipeline, or a specific stage, will execute in the Jenkins environment depending on where the agent section is placed.

  • It ensures that the source repository is checked out and made available for steps in the subsequent stages.

  • It can be defined both at top level or at stage level

    In agents declared at the outermost level or the top level of the Pipeline, the options are invoked after entering the agent.

    In agents declared at stage level , the options are invoked before entering the agent and before checking any when conditions.

Stages

  • This section allows to generate different stages on your pipeline that will be visualized as different segments when the job is run.

  • It must contain at least one stage directive.

Steps

  • The steps section defines a series of one or more steps to be executed in a given stage directive.

Post

  • The post section defines one or more additional steps that are run upon the completion of a Pipeline
  • It supports many of the post-condition blocks such as always, changed, fixed, regression, aborted, failure, success, unstable, unsuccessful, and cleanup.
  • These condition blocks allow the execution of steps inside each condition depending on the completion status of the Pipeline or stage.

A combined example of sections discussed above

pipeline {
    agent none 
    stages {
        stage('Building-stage') {
            agent aws_node1
            steps {
                sh 'mvn clean verify'
            }
        }
        stage('PAckaging-stage') {
            agent aws_node2 
            steps {
                sh 'mvn package'
            }
        }
    }
    post {
        always {
            deleteDir()
        }
        success {
            echo 'Build success'
        }
        failure {
            echo 'Build failed'
        }
    }
}

Directives

Jenkins pipeline could be easily decorated with multiple directives available such as environment,options, etc.

Lets have a look on some of the directives with examples...

Environment

  • The environment directive specifies a sequence of key-value pairs which will be defined as environment variables for all steps, or stage-specific steps, depending on where the environment directive is located within the Pipeline.

  • This directive supports a special helper method credentials() which can be used to access pre-defined Credentials by their identifier in the Jenkins environment.

  • Consider this pipeline as an example

pipeline {
    agent any
    environment {
       GLOBAL_VAR = "this is available everywhere"
    }
    stages {
        stage('Use-creds') {
            environment {
                GIT_CREDS = credentials('git_creds')
                LOCAL_VAR = "this is local to stage Use-creds"
            }
            steps {
                sh 'echo "GIT_CREDS : ${GIT_CREDS}"'
                sh 'echo "Username : ${GIT_CREDS_USR}"'
                sh 'echo "Password : ${GIT_CREDS_PSW}"'
            }
        }
    }
}

Options

The options directive allows configuring Pipeline-specific options from within the Pipeline itself such as

  • retry
    • enable retrying the failed build for the specified times
  • timeout
    • Set a timeout period for the Pipeline run, after which the Pipeline aborts.
  • buildDiscarder
    • Persist artifacts and console output for the specific number of recent Pipeline runs.
  • quietPeriod
    • Set the quiet period, in seconds, for the Pipeline
pipeline {
    agent any
    options {
        buildDiscarder(logRotator(numToKeepStr: '3'))
    }
    stages {
        stage('Stage 1') {
            options {
               timeout(time: 5, unit: 'SECONDS')
            }
            steps {
                sh 'sbt --version'
            }
        }
         stage('Stage 2') {
            options {
               timeout(time: 10, unit: 'SECONDS')
            }
            steps {
                sh 'mvn --version'
            }
        }
    }
}

Parameters

  • The parameters directive provides a list of parameters that a user should provide when triggering the Pipeline.
  • The parameter defined must be used via param object.
  • Available Parameters are :
    • string
    • text
    • chioce
    • password
    • booleanParam
  • Example
pipeline {
    agent any
    parameters {
        string(name: 'NAME', defaultValue: 'Hello', description: 'Hello , whats your name?')
    }
    stages {
        stage('Use parameters') {
            steps {
                echo "${params.NAME} provided parameters to this pipeline"
            }
        }
        
    }
}

Triggers

  • It defines the automated ways in which the Pipeline should be re-triggered.
  • Triggers are specified using cron expressions
  • Pipelines which are integrated with a source such as GitHub or BitBucket( which provides webhooks-based integration), triggers may not be necessary for them.
  • For example consider this pipeline which will be triggered every minute automatically.
pipeline {
    agent any
    triggers {
        cron('* * * * *')
    }
    stages {
        stage('Stage-1') {
            steps {
                echo 'Hello World'
            }
        }
    }
}

Tools

  • A section defining tools to auto-install and put on the PATH.
  • This is ignored if agent none is specified.
pipeline {
    agent ubuntu_aws
    tools {
        maven 'apache-maven-3.6.0' 
    }
    stages {
        stage('Example') {
            steps {
                sh 'mvn --version'
            }
        }
    }
}

Input

  • The input directive on a stage allows you to prompt for input, using the input step.
  • The stage will pause after any options have been applied, and before entering the agent block for that stage or evaluating the when condition of the stage.
  • If the input is approved, the stage will then continue.
  • Any parameters provided as part of the input submission will be available in the environment for the rest of the stage.
pipeline {
    agent any
    stages {
        stage('Take-Off') {
            input {
                message "Lets Explore Space"
                ok "Launch"
                submitter "admin"
                parameters {
                    string(name: 'SPACESHIP', defaultValue: 'Apollo', description: 'which one to launch ?')
                    string(name: 'DESTINATION', defaultValue: 'Moon', description: 'where to explore ?')
                }
            }
            steps {
                echo "${SPACESHIP} will now explore ${DESTINATION}"
            }
        }
    }
}

Sequential Stages

Stages in Declarative Pipeline may have a stages section that executes in sequential order.

//sequential execution
pipeline {
    agent any
    stages {
        stage('sequential-1') {
           steps {
                echo "in sequential-1"
            }
            post {
                success {
                    echo "S1 success"
                }
                failure {
                    echo "S1 failure"
                }
            }
        }
        stage('sequential-2') {
           steps {
                echo "in sequential-2"
            }
            post {
                success {
                    echo "S2 success"
                }
                failure {
                    echo "S2 failure"
                }
            }
        }      
    }
}

Parallel

Stages in Declarative Pipeline may have a parallel section to execute stages to be run in parallel.

//parallel execution
pipeline {
    agent any
    stages {
        stage('Run stages in parallel') {
            parallel {
                stage('Parallel P1') {
                   steps {
                        echo "in P1"
                    }
                    post {
                        success {
                            echo "P1 success"
                        }
                        failure {
                            echo "P1 failure"
                        }
                    }
                }
                stage('Parallel P2') {
                   steps {
                        echo "in P2"
                    }
                    post {
                        success {
                            echo "P2 success"
                        }
                        failure {
                            echo "P2 failure"
                        }
                    }
                }
            }
        }
    }
}

Extra Notes

  • A stage must have one and only one of step, stages or parallel.
  • It is not possible to nest a parallel block within a stage directive if that stage directive is nested within a parallel block itself.
  • However, a stage directive within a parallel block can use all other functionality of a stage, including agent, tools, when, etc.

Thanks for keeping up !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment