Skip to content

Jenkins - Continuous Deployment

Jenkins - Pipeline Workflows & Continuous Deployment

Section titled “Jenkins - Pipeline Workflows & Continuous Deployment”

Continuous Deployment (CD) extends Continuous Integration by automating the deployment of every validated change directly into production. Jenkins Pipelines are the primary mechanism for defining and executing these complex end-to-end workflows.

A typical CI/CD workflow involves multiple stages:

Code Commit -> Build -> Unit Test -> Static Analysis -> Integration Test -> (Optional Manual Approval) -> Deploy to Staging -> Automated Acceptance Test -> (Optional Manual Approval) -> Deploy to Production -> Post-Deployment Monitoring

Jenkins allows you to model this flow using the stages within a Jenkinsfile.

Note: The older ‘Build Pipeline Plugin’ and ‘Delivery Pipeline Plugin’ provided visualizations but are largely superseded by the built-in Pipeline capabilities and visualization provided by the core Pipeline Stage View or the Blue Ocean plugin.

Building a Multi-Stage Deployment Pipeline

Section titled “Building a Multi-Stage Deployment Pipeline”

Let’s enhance a basic build pipeline to include deployment stages.

pipeline {
agent any // Define agent globally or per stage
environment {
// Define environment variables accessible across stages
STAGING_SERVER = 'staging.example.com'
PROD_SERVER = 'prod.example.com'
APP_NAME = 'my-web-app'
// Credentials should be loaded securely, not hardcoded
DEPLOY_CREDENTIAL_ID = 'ssh-deploy-key'
}
options {
// Automatically clean workspace before build
// cleanWs()
// Keep only the last 5 builds
buildDiscarder(logRotator(numToKeepStr: '5', artifactNumToKeepStr: '3'))
// Timeout for the entire pipeline
timeout(time: 1, unit: 'HOURS')
}
stages {
stage('Checkout') {
steps {
git url: 'https://github.com/your-org/your-repo.git',
branch: 'main',
credentialsId: 'github-credentials'
}
}
stage('Build') {
agent { label 'build-agent' } // Use a specific agent if needed
steps {
echo "Building ${env.APP_NAME}..."
sh 'mvn clean package -DskipTests'
// Archive the artifact for later stages
archiveArtifacts artifacts: 'target/*.war', fingerprint: true
}
}
stage('Unit & Integration Tests') {
agent { label 'test-agent' } // Agent might need DB access
steps {
echo 'Running tests...'
sh 'mvn verify'
}
post {
always {
junit '**/target/surefire-reports/*.xml'
junit '**/target/failsafe-reports/*.xml'
}
}
}
stage('Static Analysis') {
steps {
echo 'Running Checkstyle, SpotBugs...'
// Example: sh 'mvn checkstyle:check spotbugs:check'
}
post {
always {
// Requires Warnings Next Generation plugin
recordIssues tools: [
checkStyle(pattern: '**/target/checkstyle-result.xml'),
spotbugs(pattern: '**/target/spotbugsXml.xml')
]
}
}
}
// --- Continuous Delivery Point ---
// Code passing up to here is potentially releasable
stage('Deploy to Staging') {
steps {
echo "Deploying ${env.APP_NAME} to Staging (${env.STAGING_SERVER})..."
// Unarchive artifact from build stage
unarchiveMapping(mapping: ['target/*.war': '.'])
// Example using SSH
sshagent(credentials: [env.DEPLOY_CREDENTIAL_ID]) {
sh "scp *.war user@${env.STAGING_SERVER}:/path/to/deploy/"
sh "ssh user@${env.STAGING_SERVER} /path/to/restart-script.sh"
}
}
}
stage('Acceptance Tests on Staging') {
agent { label 'acceptance-test-agent' } // Agent with testing tools/browsers
steps {
echo 'Running acceptance tests against staging environment...'
// Example: sh 'run-selenium-tests.sh --env=staging'
// Example: sh 'npx cypress run --env environment=staging'
}
post {
always {
// Publish acceptance test results
junit '**/test-results/acceptance/*.xml'
// publishHTML ... for HTML reports
}
}
}
// --- Continuous Deployment Point ---
// If this stage runs automatically, it's Continuous Deployment
stage('Deploy to Production') {
// Add an input step for manual approval before production deployment
input {
message "Deploy ${env.APP_NAME} ${env.BUILD_NUMBER} to Production?"
ok 'Yes, Deploy to Production'
submitter 'approver-group,admin-user' // Optional: Restrict who can approve
}
steps {
echo "Deploying ${env.APP_NAME} to Production (${env.PROD_SERVER})..."
// Deployment steps similar to staging, but targeting production server
unarchiveMapping(mapping: ['target/*.war': '.'])
sshagent(credentials: [env.DEPLOY_CREDENTIAL_ID]) {
sh "scp *.war user@${env.PROD_SERVER}:/path/to/deploy/"
sh "ssh user@${env.PROD_SERVER} /path/to/restart-script.sh"
}
}
}
}
post {
// Notifications for overall pipeline status
success {
slackSend channel: '#deployments', message: "SUCCESS: Pipeline '${env.JOB_NAME} [${env.BUILD_NUMBER}]' completed successfully. Deployed to Production."
}
failure {
slackSend channel: '#alerts', color: 'danger', message: "FAILURE: Pipeline '${env.JOB_NAME} [${env.BUILD_NUMBER}]' failed. (${env.BUILD_URL})"
}
}
}
  • Pipeline as Code (Jenkinsfile): Defining the entire workflow in a Jenkinsfile stored in version control is crucial for repeatability, collaboration, and disaster recovery.
  • Stages: Break down the workflow into logical steps (Build, Test, Deploy Staging, Deploy Prod).
  • Artifact Management: Use archiveArtifacts to save build outputs and unarchiveMapping or stash/unstash to pass them between stages, especially if stages run on different agents.
  • Environment Variables: Use the environment block to define configuration reused across stages.
  • Credentials: Store all secrets (API keys, passwords, SSH keys) securely using the Jenkins Credentials system and access them via bindings (withCredentials step) or directly in steps that support them (like git, sshagent).
  • Manual Approval: Use the input step to pause the pipeline and require human confirmation before critical actions like production deployments.
  • Conditional Execution: Use the when directive to skip stages based on conditions (e.g., only run deployment stage on the main branch).
  • Notifications: Use the post block to send notifications (Email, Slack, Teams) based on the final pipeline status or stage status.

Jenkins provides built-in visualization for Pipelines:

  • Pipeline Stage View: The default view on the classic UI build page shows stages, their status, and duration.
  • Blue Ocean Plugin: Offers a modern, graphical representation of the pipeline flow, highlighting successes, failures, logs per stage, and pending inputs. Highly recommended for visualizing complex pipelines.

By leveraging Jenkins Pipelines and best practices, you can build robust, automated workflows for Continuous Delivery or Continuous Deployment.