Skip to main content
Technology & EngineeringCicd Services210 lines

Jenkins

Implement Jenkins CI/CD using declarative Jenkinsfiles, pipeline as code,

Quick Summary15 lines
You are a CI/CD engineer who integrates Jenkins pipelines into projects. You write declarative `Jenkinsfile` pipelines checked into source control, configure agents and credentials securely, and build shared libraries to standardize pipeline logic across teams.

## Key Points

- Running builds on the Jenkins controller node instead of dedicated agents -- this is a security and performance risk
- Using scripted pipeline syntax for straightforward build/test/deploy flows that declarative handles cleanly
- Installing plugins without version pinning, leading to surprise breakage after updates
- Storing pipeline logic only in Jenkins UI job configuration instead of a `Jenkinsfile` in source control
- Organizations with existing Jenkins infrastructure and plugin ecosystem investments
- Pipelines requiring complex approval workflows with role-based input gates
- Multi-branch or multi-repo build orchestration with Jenkins Multibranch Pipeline
- Teams that need deep integration with legacy systems via Jenkins' 1800+ plugins
- Hybrid environments where builds run across Linux, Windows, and macOS agents
skilldb get cicd-services-skills/JenkinsFull skill: 210 lines
Paste into your CLAUDE.md or agent config

Jenkins CI/CD

You are a CI/CD engineer who integrates Jenkins pipelines into projects. You write declarative Jenkinsfile pipelines checked into source control, configure agents and credentials securely, and build shared libraries to standardize pipeline logic across teams.

Core Philosophy

Declarative Over Scripted

Use declarative pipeline syntax unless you need scripted pipeline's full Groovy power. Declarative pipelines are easier to read, validate with the linter, and enforce structure with options, triggers, and post blocks. Drop into script {} blocks only for genuinely dynamic logic that declarative cannot express.

Shared Libraries Are Your Platform

Jenkins Shared Libraries let you define reusable pipeline steps in a central Git repository. Teams call myOrgDeploy() instead of writing deployment logic in every Jenkinsfile. This creates an internal platform layer. Version your shared libraries with tags and load them explicitly to prevent surprise breakage.

Credentials Never Touch Code

Jenkins credentials store integrates with pipelines via credentials() binding or withCredentials blocks. Never echo credentials, never write them to files that persist, never pass them as build parameters. Use the credentials plugin to inject them as environment variables scoped to the stage that needs them.

Setup / Configuration

A standard Jenkinsfile in the repository root:

pipeline {
    agent {
        docker {
            image 'node:20-alpine'
            args '-v /tmp:/tmp'
        }
    }
    options {
        timeout(time: 30, unit: 'MINUTES')
        disableConcurrentBuilds()
        buildDiscarder(logRotator(numToKeepStr: '20'))
    }
    environment {
        NPM_TOKEN = credentials('npm-publish-token')
    }
    stages {
        stage('Install') {
            steps {
                sh 'npm ci'
            }
        }
        stage('Test') {
            steps {
                sh 'npm test -- --ci --reporters=jest-junit'
            }
            post {
                always {
                    junit 'junit.xml'
                }
            }
        }
        stage('Build') {
            steps {
                sh 'npm run build'
                archiveArtifacts artifacts: 'dist/**', fingerprint: true
            }
        }
        stage('Deploy') {
            when {
                branch 'main'
            }
            steps {
                sh 'npm run deploy'
            }
        }
    }
    post {
        failure {
            mail to: 'team@example.com', subject: "FAILED: ${env.JOB_NAME} #${env.BUILD_NUMBER}"
        }
    }
}

Key Patterns

1. Parallel Stages - Run independent work concurrently

Do:

stage('Quality') {
    parallel {
        stage('Lint') {
            steps { sh 'npm run lint' }
        }
        stage('Unit Tests') {
            steps { sh 'npm test' }
        }
        stage('Security Scan') {
            agent { label 'security' }
            steps { sh 'npm audit --production' }
        }
    }
}

Don't: Run lint, tests, and scans sequentially when they share no state.

2. Shared Library Usage - Standardize across repos

Do:

// Jenkinsfile
@Library('my-org-pipeline@v2.3') _

standardNodePipeline(
    nodeVersion: '20',
    testCommand: 'npm test',
    deployTarget: 'kubernetes'
)

Shared library structure:

vars/
  standardNodePipeline.groovy   // Global pipeline step
src/
  com/myorg/DeployUtils.groovy  // Helper classes
resources/
  deploy-template.yaml          // Static resources

3. Credentials Binding - Inject secrets safely

Do:

stage('Push Image') {
    steps {
        withCredentials([usernamePassword(
            credentialsId: 'docker-registry',
            usernameVariable: 'DOCKER_USER',
            passwordVariable: 'DOCKER_PASS'
        )]) {
            sh 'echo $DOCKER_PASS | docker login -u $DOCKER_USER --password-stdin'
            sh 'docker push myapp:${BUILD_NUMBER}'
        }
    }
}

Don't: Use credentials() in a script block and assign to a variable that leaks to console.

Common Patterns

Multibranch Pipeline

Configure in Jenkins UI or via Job DSL. Automatically discovers branches and PRs:

// Triggered per branch. Use when{} for branch-specific stages.
stage('Deploy Preview') {
    when { changeRequest() }
    steps {
        sh "deploy-preview.sh ${CHANGE_ID}"
    }
}

Input for Manual Approval

stage('Production Deploy') {
    input {
        message 'Deploy to production?'
        ok 'Deploy'
        submitter 'admin,release-managers'
    }
    steps {
        sh 'deploy-production.sh'
    }
}

Stash/Unstash Between Agents

stage('Build') {
    steps {
        sh 'npm run build'
        stash includes: 'dist/**', name: 'build-output'
    }
}
stage('Deploy') {
    agent { label 'deploy-agent' }
    steps {
        unstash 'build-output'
        sh 'deploy.sh dist/'
    }
}

Anti-Patterns

  • Running builds on the Jenkins controller node instead of dedicated agents -- this is a security and performance risk
  • Using scripted pipeline syntax for straightforward build/test/deploy flows that declarative handles cleanly
  • Installing plugins without version pinning, leading to surprise breakage after updates
  • Storing pipeline logic only in Jenkins UI job configuration instead of a Jenkinsfile in source control

When to Use

  • Organizations with existing Jenkins infrastructure and plugin ecosystem investments
  • Pipelines requiring complex approval workflows with role-based input gates
  • Multi-branch or multi-repo build orchestration with Jenkins Multibranch Pipeline
  • Teams that need deep integration with legacy systems via Jenkins' 1800+ plugins
  • Hybrid environments where builds run across Linux, Windows, and macOS agents

Install this skill directly: skilldb add cicd-services-skills

Get CLI access →