Skip to content

Latest commit

 

History

History
321 lines (274 loc) · 11.3 KB

File metadata and controls

321 lines (274 loc) · 11.3 KB

Jenkins

Generic example

// Jenkins Declarative Pipeline syntax reference:
// https://www.jenkins.io/doc/book/pipeline/syntax/#declarative-pipeline

pipeline {

    // agent directive:
    // https://www.jenkins.io/doc/book/pipeline/syntax/#agent
    agent any

    // options directive:
    // https://www.jenkins.io/doc/book/pipeline/syntax/#options
    options {
        // buildDiscarder option using LogRotator:
        // https://www.jenkins.io/doc/book/pipeline/syntax/#options
        // https://javadoc.jenkins.io/hudson/tasks/LogRotator.html
        buildDiscarder(logRotator(numToKeepStr: '20', artifactNumToKeepStr: '20'))

        // disableConcurrentBuilds option:
        // https://www.jenkins.io/doc/book/pipeline/syntax/#options
        disableConcurrentBuilds()

        // timestamps step (Timestamper plugin):
        // https://www.jenkins.io/doc/pipeline/steps/timestamper/#timestamps-timestamps
        timestamps()

        // timeout wrapper at pipeline level:
        // Declarative options:
        //   https://www.jenkins.io/doc/book/pipeline/syntax/#options
        // Step reference:
        //   https://www.jenkins.io/doc/pipeline/steps/workflow-basic-steps/#timeout-enforce-time-limit
        timeout(time: 60, unit: 'MINUTES')
    }

    // triggers directive:
    // https://www.jenkins.io/doc/book/pipeline/syntax/#triggers
    // Cron & pollSCM behavior:
    // https://docs.cloudbees.com/docs/cloudbees-ci/latest/pipeline-syntax-reference-guide/declarative-pipeline#_triggers
    triggers {
        cron('H H * * 1-5')        // Run once on weekdays
        pollSCM('H/5 * * * *')     // Poll SCM every 5 minutes
    }

    // parameters directive:
    // https://www.jenkins.io/doc/book/pipeline/syntax/#parameters
    parameters {
        // string parameter:
        // https://www.jenkins.io/doc/book/pipeline/syntax/#parameters
        string(
            name: 'APP_ENV',
            defaultValue: 'dev',
            description: 'Application environment (dev/stage/prod)'
        )

        // booleanParam:
        // https://www.jenkins.io/doc/book/pipeline/syntax/#parameters
        booleanParam(
            name: 'RUN_INTEGRATION_TESTS',
            defaultValue: false,
            description: 'Run integration tests?'
        )

        // choice parameter:
        // https://www.jenkins.io/doc/book/pipeline/syntax/#parameters
        choice(
            name: 'DEPLOY_TARGET',
            choices: ['none', 'staging', 'production'],
            description: 'Where to deploy'
        )
    }

    // environment directive:
    // https://www.jenkins.io/doc/book/pipeline/syntax/#environment
    // credentials() helper:
    // https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#for-secret-text-usernames-and-passwords-and-secret-files
    environment {
        APP_NAME = 'example-service'
        APP_PORT = '8080'

        // Provides env vars based on the credential type
        GIT_CREDENTIALS = credentials('github-ssh-key-id')
    }

    // tools directive:
    // https://www.jenkins.io/doc/book/pipeline/syntax/#tools
    tools {
        maven 'maven-3.9'
        jdk   'jdk-17'
    }

    // stages directive:
    // https://www.jenkins.io/doc/book/pipeline/syntax/#stages
    stages {

        // stage directive:
        // https://www.jenkins.io/doc/book/pipeline/syntax/#stage
        stage('Initialize') {

            // when directive:
            // https://www.jenkins.io/doc/book/pipeline/syntax/#when
            when {
                anyOf {
                    environment name: 'APP_ENV', value: 'dev'
                    branch 'main'
                }
            }

            // steps directive:
            // https://www.jenkins.io/doc/book/pipeline/syntax/#steps
            steps {
                // echo step:
                // https://www.jenkins.io/doc/pipeline/steps/workflow-basic-steps/#echo-print-message
                echo "Initializing pipeline for ${env.APP_NAME} in ${params.APP_ENV}"

                // cleanWs step (Workspace Cleanup plugin):
                // https://www.jenkins.io/doc/pipeline/steps/ws-cleanup/#cleanws-delete-workspace-when-build-is-done
                cleanWs()

                // checkout step using the job’s SCM configuration:
                // https://www.jenkins.io/doc/pipeline/steps/workflow-scm-step/#checkout-check-out-from-version-control
                checkout scm
            }
        }

        stage('Build') {
            // agent at stage level:
            // https://www.jenkins.io/doc/book/pipeline/syntax/#agent
            agent {
                label 'linux-build'
            }

            steps {
                // sh step:
                // https://www.jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#sh-shell-script
                sh '''
                    set -e
                    ./gradlew clean assemble
                '''

                // stash built artifacts:
                // https://www.jenkins.io/doc/pipeline/steps/workflow-basic-steps/#stash-stash-some-files-to-be-used-later-in-the-build
                stash name: 'build-artifacts', includes: 'build/libs/**/*.jar'
            }
        }

        stage('Unit tests') {
            steps {
                // timeout step:
                // https://www.jenkins.io/doc/pipeline/steps/workflow-basic-steps/#timeout-enforce-time-limit
                timeout(time: 15, unit: 'MINUTES') {
                    sh './gradlew test'
                }

                // junit step:
                // https://www.jenkins.io/doc/pipeline/steps/junit/#junit-archive-junit-formatted-test-results
                junit testResults: 'build/test-results/test/*.xml', allowEmptyResults: true
            }
        }

        stage('Static analysis') {
            when {
                // when / expression:
                // https://www.jenkins.io/doc/book/pipeline/syntax/#when
                expression { env.BRANCH_NAME == 'main' }
            }
            steps {
                sh './gradlew check'
            }
        }

        stage('Integration tests') {
            when {
                expression { return params.RUN_INTEGRATION_TESTS }
            }

            // parallel directive:
            // https://www.jenkins.io/doc/book/pipeline/syntax/#parallel
            parallel {
                stage('Integration tests DB') {
                    steps {
                        // unstash step:
                        // https://www.jenkins.io/doc/pipeline/steps/workflow-basic-steps/#unstash-restore-files-previously-stashed
                        unstash 'build-artifacts'
                        sh './gradlew integrationTestDb'
                    }
                }

                stage('Integration tests API') {
                    steps {
                        unstash 'build-artifacts'
                        sh './gradlew integrationTestApi'
                    }
                }
            }
        }

        stage('Package') {
            steps {
                // script directive inside Declarative:
                // https://www.jenkins.io/doc/book/pipeline/syntax/#script
                script {
                    // fileExists step:
                    // https://www.jenkins.io/doc/pipeline/steps/workflow-basic-steps/#fileexists-verify-if-file-exists-in-workspace
                    if (!fileExists('build/libs')) {
                        // error step:
                        // https://www.jenkins.io/doc/pipeline/steps/workflow-basic-steps/#error-error-signal
                        error "Expected build/libs directory not found"
                    }
                }

                // archiveArtifacts step:
                // https://www.jenkins.io/doc/pipeline/steps/core/#archiveartifacts-archive-the-artifacts
                archiveArtifacts artifacts: 'build/libs/**/*.jar', fingerprint: true

                // stash packaged artifacts for later deploy:
                // https://www.jenkins.io/doc/pipeline/steps/workflow-basic-steps/#stash-stash-some-files-to-be-used-later-in-the-build
                stash name: 'package', includes: 'build/libs/**/*.jar'
            }
        }

        stage('Manual approval') {
            when {
                anyOf {
                    environment name: 'APP_ENV', value: 'prod'
                    equals expected: 'production', actual: params.DEPLOY_TARGET
                }
            }

            steps {
                // input step (Pipeline: Input Step plugin):
                // https://www.jenkins.io/doc/pipeline/steps/pipeline-input-step/#input-wait-for-interactive-input
                input message: "Deploy ${env.APP_NAME} to ${params.DEPLOY_TARGET}?", ok: 'Deploy'
            }
        }

        stage('Deploy') {
            when {
                expression { params.DEPLOY_TARGET != 'none' }
            }

            // environment at stage scope:
            // https://www.jenkins.io/doc/book/pipeline/syntax/#environment
            environment {
                TARGET_ENV = "${params.DEPLOY_TARGET}"
            }

            steps {
                // withCredentials step (Credentials Binding plugin):
                // https://www.jenkins.io/doc/pipeline/steps/credentials-binding/#withcredentials-bind-credentials-to-variables
                withCredentials([
                    usernamePassword(
                        credentialsId: 'deployment-user',
                        usernameVariable: 'DEPLOY_USER',
                        passwordVariable: 'DEPLOY_PASS'
                    )
                ]) {

                    // script directive:
                    // https://www.jenkins.io/doc/book/pipeline/syntax/#script
                    script {
                        echo "Deploying to ${TARGET_ENV} as ${DEPLOY_USER}"
                    }

                    unstash 'package'

                    // retry step:
                    // https://www.jenkins.io/doc/pipeline/steps/workflow-basic-steps/#retry-retry-the-body-up-to-n-times
                    retry(3) {
                        sh '''
                            set -e
                            ./scripts/deploy.sh \
                              --env "${TARGET_ENV}" \
                              --user "${DEPLOY_USER}" \
                              --password "${DEPLOY_PASS}"
                        '''
                    }
                }
            }
        }
    }

    // post directive:
    // https://www.jenkins.io/doc/book/pipeline/syntax/#post
    // Tour of post usage:
    // https://www.jenkins.io/doc/pipeline/tour/post/
    post {
        always {
            echo 'Post: always'
            cleanWs()
        }

        success {
            echo 'Post: success'
        }

        failure {
            echo 'Post: failure'
        }

        unstable {
            echo 'Post: unstable'
        }

        changed {
            echo "Post: build result changed from previous: ${currentBuild.previousBuild?.result} -> ${currentBuild.currentResult}"
        }
    }
}