Pipelines, stages, shared libraries, agents, plugins, security, declarative syntax, and CI/CD automation.
pipeline {
agent any
// ── Global Environment ──
environment {
DOCKER_REGISTRY = 'registry.example.com'
IMAGE_NAME = 'myapp'
IMAGE_TAG = "${env.BUILD_NUMBER}"
CREDENTIALS_ID = 'docker-registry-creds'
}
// ── Pipeline Triggers ──
triggers {
pollSCM('H/5 * * * *') // Poll every 5 minutes
// OR use webhook from GitHub/GitLab
}
options {
timeout(time: 30, unit: 'MINUTES')
retry(2) // Retry failed stages
buildDiscarder(logRotator(numToKeepStr: '20'))
disableConcurrentBuilds()
timestamps()
ansiColor('xterm')
}
// ── Stages ──
stages {
stage('Checkout') {
steps {
checkout scmGit(
branches: [[name: '*/main']],
extensions: [[$class: 'CleanBeforeCheckout']]
)
sh 'git log --oneline -5'
}
}
stage('Install Dependencies') {
steps {
sh 'npm ci --production=false'
}
}
stage('Lint & Format') {
parallel {
stage('ESLint') {
steps { sh 'npm run lint' }
}
stage('Type Check') {
steps { sh 'npx tsc --noEmit' }
}
}
}
stage('Test') {
steps {
sh 'npm run test:coverage'
}
post {
always {
junit 'reports/junit.xml'
publishHTML(target: [
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: 'coverage',
reportFiles: 'index.html',
reportName: 'Coverage Report'
])
}
}
}
stage('Build') {
steps {
sh 'npm run build'
archiveArtifacts artifacts: 'dist/**', fingerprint: true
}
}
stage('Docker Build & Push') {
steps {
script {
docker.withRegistry("https://${DOCKER_REGISTRY}", CREDENTIALS_ID) {
def img = docker.build("${IMAGE_NAME}:${IMAGE_TAG}")
img.push()
img.push('latest')
}
}
}
}
stage('Deploy') {
when { branch 'main' }
steps {
sh '''
kubectl set image deployment/myapp myapp=${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG} --namespace=production
'''
}
}
}
post {
success { echo 'Pipeline completed successfully!' }
failure { echo 'Pipeline FAILED. Check logs.' }
always {
cleanWs()
emailext(
subject: "Build ${currentBuild.result}: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
body: "${env.JOB_NAME} - Build #${env.BUILD_NUMBER} - ${currentBuild.result}",
to: 'team@example.com'
)
}
}
}| Directive | Purpose | Example |
|---|---|---|
| agent | Where to run pipeline | agent { docker "node:18" } |
| environment | Environment variables | env { KEY = "val" } |
| options | Pipeline options | retry(3), timeout(time: 10) |
| triggers | Auto-trigger builds | pollSCM, cron, upstream |
| parameters | User input parameters | string, boolean, choice |
| tools | Auto-install tools | maven "3.9", jdk "17" |
| when | Conditional execution | when { branch "main" } |
| matrix | Parallel configurations | matrix { axes { ... } } |
| Condition | Description |
|---|---|
| branch "main" | Git branch matches |
| buildingTag() | Building a tag |
| changeRequest() | PR/MR build |
| changeRequest(target: "master") | PR targets master |
| environment name: "prod" | Specific environment |
| expression { return true } | Groovy expression |
| not { branch "dev" } | Negation |
| allOf { ... } | All conditions must match |
| anyOf { ... } | Any condition matches |
// ── Shared Variables & Functions ──
def getGitBranch() {
return sh(returnStdout: true, script: 'git rev-parse --abbrev-ref HEAD').trim()
}
def getDockerTags() {
def commit = sh(returnStdout: true, script: 'git rev-parse --short HEAD').trim()
def branch = getGitBranch()
def tags = ["${env.BUILD_NUMBER}", commit]
if (branch == 'main') {
tags << 'latest'
}
return tags
}
// ── Conditional Logic ──
script {
if (env.BRANCH_NAME == 'main') {
stage('Production Deploy') {
sh 'kubectl apply -f k8s/production/'
}
} else if (env.BRANCH_NAME.startsWith('feature/')) {
stage('Dev Deploy') {
sh 'kubectl apply -f k8s/development/'
}
} else {
echo "No deployment for branch: ${env.BRANCH_NAME}"
}
}
// ── Retry Logic ──
retry(3) {
sh 'npm install --registry=https://registry.npmjs.org'
}
// ── Timeout ──
timeout(time: 5, unit: 'MINUTES') {
sh 'npm run test:e2e'
}
// ── Wait for Condition ──
waitUntil {
script {
def r = sh(script: 'curl -s -o /dev/null -w "%{http_code}" http://localhost:3000', returnStdout: true).trim()
return (r == "200")
}
}
// ── Parallel Stages with Matrix ──
matrix {
axes {
axis {
name 'NODE_VERSION'
values '18', '20', '22'
}
}
stages {
stage('Test') {
steps {
sh "docker run --rm node:${NODE_VERSION} npm test"
}
}
}
}| Method | Use Case | Example |
|---|---|---|
| usernamePassword | Git credentials | credentials("git-creds") |
| string | API tokens | credentials("api-token") |
| file | Config files | credentials("kubeconfig") |
| sshUserPrivateKey | SSH keys | credentials("deploy-key") |
| withCredentials | Wrapper block | Multiple credentials |
| Flag | Purpose | Example |
|---|---|---|
| returnStdout: true | Capture stdout | sh(script: "echo hi", returnStdout: true) |
| returnStatus: true | Capture exit code | sh(script: "ls", returnStatus: true) |
| script: | Command to run | sh(script: "npm test") |
Declarative uses a predefined structure with pipeline, agent,stages, steps. It is opinionated, easier to read, and supports Blue Ocean visualization.Scripted is pure Groovy code giving full programmatic control. Use declarative for most pipelines; use script blocks within declarative pipelines only when you need Groovy features like loops, conditionals, or try/catch.
Agents (formerly slaves/nodes) are machines that execute build workloads. The controller schedules builds to available agents based on labels. Use agent { label "docker" } to route to specific agents. Agents can be SSH-based, JNLP-based, or use the Kubernetes plugin for dynamic pod provisioning. Cloud plugins (EC2, Azure, GCP) can spin up agents on-demand and terminate them after builds.