Jenkins
01 / 03

Declarative Pipelines & Jenkinsfile

Jenkins: Declarative Pipelines & Jenkinsfile

Jenkins is the most widely used open-source CI/CD server. Pipelines are defined as code in a Jenkinsfile (checked into the repo) using either Declarative or Scripted syntax. Declarative is preferred — more structured and readable.

Declarative Pipeline Structure

// Jenkinsfile — declarative pipeline
pipeline {
    agent any              // run on any available agent

    options {
        timeout(time: 30, unit: 'MINUTES')
        disableConcurrentBuilds()
        buildDiscarder(logRotator(numToKeepStr: '10'))
        timestamps()
    }

    environment {
        APP_NAME = 'my-app'
        DOCKER_REGISTRY = 'registry.example.com'
        NODE_VERSION = '20'
    }

    triggers {
        githubPush()            // trigger on GitHub push
        cron('H 2 * * 1-5')   // nightly at ~2am Mon-Fri
    }

    stages {
        stage('Checkout') {
            steps {
                checkout scm   // check out source code
            }
        }

        stage('Install') {
            steps {
                sh 'npm ci'
            }
        }

        stage('Lint & Test') {
            parallel {
                stage('Lint') {
                    steps { sh 'npm run lint' }
                }
                stage('Unit Tests') {
                    steps {
                        sh 'npm test -- --coverage'
                        junit 'test-results/**/*.xml'
                        publishCoverage adapters: [coberturaAdapter('coverage/cobertura-coverage.xml')]
                    }
                }
            }
        }

        stage('Build') {
            steps {
                sh 'npm run build'
            }
        }

        stage('Deploy') {
            when {
                branch 'main'   // only deploy from main branch
            }
            steps {
                sh './scripts/deploy.sh'
            }
        }
    }

    post {
        always {
            archiveArtifacts artifacts: 'dist/**/*', fingerprint: true
            cleanWs()          // clean workspace after build
        }
        success {
            slackSend channel: '#deployments', message: "✅ ${env.JOB_NAME} #${env.BUILD_NUMBER} passed"
        }
        failure {
            slackSend channel: '#deployments', color: 'danger',
                message: "❌ ${env.JOB_NAME} #${env.BUILD_NUMBER} failed: ${env.BUILD_URL}"
            emailext to: 'team@example.com', subject: "Build Failed: ${env.JOB_NAME}",
                body: "Build ${env.BUILD_NUMBER} failed. See: ${env.BUILD_URL}"
        }
    }
}

Stages & Steps

stages {
    stage('Test') {
        steps {
            // Shell commands
            sh 'npm test'
            sh '''
                echo "Multi-line shell"
                npm run lint
                npm run build
            '''

            // Read/write files
            writeFile file: 'version.txt', text: env.BUILD_NUMBER
            def version = readFile('version.txt').trim()

            // Environment variables
            echo "Building ${env.BRANCH_NAME} on ${env.NODE_NAME}"
            echo "Build URL: ${env.BUILD_URL}"

            // Capture output
            def output = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim()

            // Conditional
            script {
                if (env.BRANCH_NAME == 'main') {
                    sh 'npm run deploy:prod'
                } else {
                    sh 'npm run deploy:staging'
                }
            }

            // Input — wait for manual approval
            input message: 'Deploy to production?', ok: 'Deploy'
        }
    }
}

When Conditions

stage('Deploy Production') {
    when {
        // Run only when all conditions are true
        allOf {
            branch 'main'
            not { changeRequest() }   // not a PR
            environment name: 'CI', value: 'true'
        }
    }
    steps { sh './deploy.sh prod' }
}

stage('Deploy Preview') {
    when {
        anyOf {
            branch 'develop'
            changeRequest()          // pull request
        }
    }
    steps { sh './deploy.sh preview' }
}

// Other when conditions:
// tag 'v*'               — matches tag pattern
// expression { return params.DEPLOY == 'true' }
// beforeAgent true       — evaluate before allocating agent

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free