Declarative Pipelines & Jenkinsfile
Jenkins: Declarative Pipelines & Jenkinsfile Jenkins is the most widely used open-source CI/CD server. Pipelines are defined as code in a Jenkinsfile (checked i…
Jenkins: Declarative Pipelines & Jenkinsfile
Jenkins is the most widely used open-source CI/CD server. Pipelines are defined as code in a Jenkinsfile (checked into the repo) using either Declarative or Scripted syntax. Declarative is preferred — more structured and readable.
Declarative Pipeline Structure
// Jenkinsfile — declarative pipeline
pipeline {
agent any // run on any available agent
options {
timeout(time: 30, unit: 'MINUTES')
disableConcurrentBuilds()
buildDiscarder(logRotator(numToKeepStr: '10'))
timestamps()
}
environment {
APP_NAME = 'my-app'
DOCKER_REGISTRY = 'registry.example.com'
NODE_VERSION = '20'
}
triggers {
githubPush() // trigger on GitHub push
cron('H 2 * * 1-5') // nightly at ~2am Mon-Fri
}
stages {
stage('Checkout') {
steps {
checkout scm // check out source code
}
}
stage('Install') {
steps {
sh 'npm ci'
}
}
stage('Lint & Test') {
parallel {
stage('Lint') {
steps { sh 'npm run lint' }
}
stage('Unit Tests') {
steps {
sh 'npm test -- --coverage'
junit 'test-results/**/*.xml'
publishCoverage adapters: [coberturaAdapter('coverage/cobertura-coverage.xml')]
}
}
}
}
stage('Build') {
steps {
sh 'npm run build'
}
}
stage('Deploy') {
when {
branch 'main' // only deploy from main branch
}
steps {
sh './scripts/deploy.sh'
}
}
}
post {
always {
archiveArtifacts artifacts: 'dist/**/*', fingerprint: true
cleanWs() // clean workspace after build
}
success {
slackSend channel: '#deployments', message: "✅ ${env.JOB_NAME} #${env.BUILD_NUMBER} passed"
}
failure {
slackSend channel: '#deployments', color: 'danger',
message: "❌ ${env.JOB_NAME} #${env.BUILD_NUMBER} failed: ${env.BUILD_URL}"
emailext to: 'team@example.com', subject: "Build Failed: ${env.JOB_NAME}",
body: "Build ${env.BUILD_NUMBER} failed. See: ${env.BUILD_URL}"
}
}
}Stages & Steps
stages {
stage('Test') {
steps {
// Shell commands
sh 'npm test'
sh '''
echo "Multi-line shell"
npm run lint
npm run build
'''
// Read/write files
writeFile file: 'version.txt', text: env.BUILD_NUMBER
def version = readFile('version.txt').trim()
// Environment variables
echo "Building ${env.BRANCH_NAME} on ${env.NODE_NAME}"
echo "Build URL: ${env.BUILD_URL}"
// Capture output
def output = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim()
// Conditional
script {
if (env.BRANCH_NAME == 'main') {
sh 'npm run deploy:prod'
} else {
sh 'npm run deploy:staging'
}
}
// Input — wait for manual approval
input message: 'Deploy to production?', ok: 'Deploy'
}
}
}When Conditions
stage('Deploy Production') {
when {
// Run only when all conditions are true
allOf {
branch 'main'
not { changeRequest() } // not a PR
environment name: 'CI', value: 'true'
}
}
steps { sh './deploy.sh prod' }
}
stage('Deploy Preview') {
when {
anyOf {
branch 'develop'
changeRequest() // pull request
}
}
steps { sh './deploy.sh preview' }
}
// Other when conditions:
// tag 'v*' — matches tag pattern
// expression { return params.DEPLOY == 'true' }
// beforeAgent true — evaluate before allocating agent