cluster deboistech.in Get started
Cheatsheet

Jenkins

Declarative Pipeline syntax for a Jenkinsfile: stages, steps, parameters, credentials, conditions, parallel work and post actions.

Practice this path

Pipeline skeleton

  • pipeline {
      agent any
      stages {
        stage('Build') {
          steps { sh 'make build' }
        }
        stage('Test') {
          steps { sh 'make test' }
        }
      }
    }

    The smallest Jenkinsfile with two stages

  • agent { docker { image 'node:20' } }

    Run the build inside a container

  • agent { label 'linux && docker' }

    Pick a machine by label

  • options { timeout(time: 15, unit: 'MINUTES'); timestamps(); buildDiscarder(logRotator(numToKeepStr: '20')) }

    A time limit, timestamps and a limit on kept builds

Steps you use daily

  • sh './gradlew test'

    Run a shell command (the build fails if it exits non-zero)

  • sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim()

    Capture a command's output

  • echo "Building ${env.BRANCH_NAME} #${env.BUILD_NUMBER}"

    Print, using the built-in variables

  • dir('app') { sh 'npm ci' }

    Run steps in a sub-folder

  • archiveArtifacts artifacts: 'dist/**', fingerprint: true

    Keep build output with the build

  • junit 'reports/**/*.xml'

    Publish test results

  • retry(3) { sh './flaky.sh' }

    Try again on failure

  • input message: 'Deploy to production?'

    Pause for a human to approve

Parameters, environment and credentials

  • parameters { string(name: 'ENV', defaultValue: 'staging'); booleanParam(name: 'DRY_RUN', defaultValue: true) }

    Inputs for "Build with Parameters"; read as params.ENV

  • environment { REGISTRY = 'registry.example.test'; APP = "web-${BUILD_NUMBER}" }

    Variables for every step

  • environment { TOKEN = credentials('deploy-token') }

    Load a stored credential (it is masked in the log)

  • withCredentials([usernamePassword(credentialsId: 'registry', usernameVariable: 'U', passwordVariable: 'P')]) {
      sh 'docker login -u "$U" -p "$P" registry.example.test'
    }

    Use credentials only inside a block

Conditions and parallel work

  • when { branch 'main' }

    Run a stage only on one branch

  • when { allOf { branch 'main'; not { changeRequest() } } }

    Combine conditions

  • when { expression { return params.DRY_RUN == false } }

    Run a stage when your own test is true

  • stage('Checks') {
      parallel {
        stage('Lint') { steps { sh 'make lint' } }
        stage('Unit') { steps { sh 'make unit' } }
      }
    }

    Run stages at the same time

  • triggers { pollSCM('H/5 * * * *'); cron('H 2 * * 1-5') }

    Check the repository every 5 minutes, and build on weekdays at about 2

After the build

  • post {
      always { junit 'reports/**/*.xml' }
      success { echo 'Done' }
      failure { mail to: 'team@example.test', subject: "Failed: ${env.JOB_NAME}", body: env.BUILD_URL }
      cleanup { cleanWs() }
    }

    Run steps depending on the result, and always clean the workspace

  • currentBuild.result = 'UNSTABLE'

    Mark a build unstable without failing it (in a script block)

  • script { if (env.BRANCH_NAME == 'main') { echo 'releasing' } }

    Use full Groovy where declarative syntax is not enough

Good habits

  • Jenkinsfile in the repository

    Keep the pipeline with the code so it is reviewed and versioned

  • Small, fast stages

    Fail early: lint and unit tests first, slow tests and deployment last

  • Never print secrets

    Use credentials(); avoid echoing variables that hold them

  • Pin tool and image versions

    A build that worked last month should still work today

Cheatsheet for the Jenkins path · Deboistech · All cheatsheets