cicd-jenkins

Jenkins — declarative Jenkinsfile for build, test, and deploy.

SKILL.md

GitHub

Jenkins Pipelines

Declarative Jenkinsfile (preferred)

// Jenkinsfile
pipeline {
    agent {
        docker {
            image 'node:20-alpine'
            args '-v /var/run/docker.sock:/var/run/docker.sock'
        }
    }

    environment {
        REGISTRY = credentials('docker-registry-url')
        DEPLOY_KEY = credentials('deploy-ssh-key')
    }

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

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

        stage('Lint') {
            steps {
                sh 'npm run lint'
            }
        }

        stage('Test') {
            steps {
                sh 'npm test'
            }
            post {
                always {
                    junit 'test-results/*.xml'
                }
            }
        }

        stage('Build Image') {
            when {
                branch 'main'
            }
            steps {
                sh "docker build -t ${REGISTRY}/myapp:${GIT_COMMIT} ."
                sh "docker push ${REGISTRY}/myapp:${GIT_COMMIT}"
            }
        }

        stage('Deploy') {
            when {
                branch 'main'
            }
            input {
                message 'Deploy to production?'
                ok 'Deploy'
            }
            steps {
                sshagent(['deploy-ssh-key']) {
                    sh """
                        ssh -o StrictHostKeyChecking=no deploy@${DEPLOY_HOST} '
                            cd /opt/myapp &&
                            IMAGE_TAG=${GIT_COMMIT} docker compose pull app &&
                            IMAGE_TAG=${GIT_COMMIT} docker compose up -d &&
                            docker image prune -f
                        '
                    """
                }
            }
        }
    }

    post {
        failure {
            mail to: 'team@example.com',
                 subject: "Pipeline failed: ${env.JOB_NAME}",
                 body: "Build ${env.BUILD_URL} failed."
        }
    }
}

Credentials Management

  • Store all secrets in Jenkins Credentials (not Jenkinsfile)
  • Use credentials() binding or withCredentials block
  • Types: Username/Password, SSH Key, Secret Text, Secret File
  • Never echo credentials — use set +x if you must debug
withCredentials([usernamePassword(
    credentialsId: 'docker-registry',
    usernameVariable: 'DOCKER_USER',
    passwordVariable: 'DOCKER_PASS'
)]) {
    sh 'docker login -u $DOCKER_USER -p $DOCKER_PASS'
}

Shared Libraries

For reusable pipeline logic across repositories:

// Jenkinsfile
@Library('my-shared-library') _

deployApp(environment: 'production', image: 'myapp')

Best Practices

  • Use declarative syntax over scripted — more readable and constrained
  • Use agent { docker {} } to run in containers — no environment pollution
  • disableConcurrentBuilds() prevents race conditions on shared resources
  • buildDiscarder prevents disk exhaustion from keeping old builds
  • Use input for manual approval gates before production deploys
  • Add timeout to prevent stuck builds from blocking the executor
  • Use post { always {} } for test report publishing — runs even on failure
  • Configure Blue Ocean plugin for better UI visualization