Back to CI/CD Pipeline
Q30Question 30 of 56

CI/CD Pipeline Stages and the Difference Between Continuous Integration, Delivery and Deployment

Key Concepts
  • A CI/CD pipeline is an automated sequence of stages that carries a code change from commit to a running environment.
  • Typical stages are source, build, test, package, scan, deploy, and verify, each gating the next.
  • Continuous Integration merges, builds, and tests every change automatically and frequently.
  • Continuous Delivery automates everything up to a production-ready artifact but keeps a manual approval before production.
  • Continuous Deployment removes the manual gate and releases every green build to production automatically.
  • The artifact must be immutable, tagged with the commit SHA, and promoted unchanged across environments.

Definition

CI proves the code is good, Continuous Delivery keeps it release-ready behind a button, and Continuous Deployment presses that button automatically.
  • CI/CD pipeline – an automated sequence of stages that takes a code change from a developer's commit all the way to a running environment.
  • Source – fetch the exact commit that triggered the pipeline.
  • Build – compile and assemble the primary artifact (JAR, binary, image).
  • Test – run unit and integration tests to validate correctness.
  • Package – produce an immutable deployable artifact such as a container image tagged with the commit.
  • Scan – run static analysis and vulnerability scanning with quality gates.
  • Deploy – push the artifact to an environment (dev, QA, production).
  • Verify – run smoke tests and health checks to confirm the deployment is healthy.

Think of the National Bank of India's cheque clearing line. A cheque arrives at the counter (source), is read and stamped (build), verified against the signature and balance (test), sealed into a clearing envelope (package), checked for forgery (scan), sent to the destination branch (deploy), and the destination confirms it landed correctly (verify). Continuous Integration is Rajesh and Priya dropping cheques into the clearing line many times a day with the machine checking each one immediately. Continuous Delivery means every verified cheque is packed and ready at the vault door, but a manager must press the button to release it. Continuous Deployment means the machine releases it automatically.

Understanding the Concepts

What is a CI/CD pipeline?

A CI/CD pipeline is an automated sequence of stages that carries a code change from a developer's commit to a running environment. Each stage gates the next: if a stage fails, the pipeline stops and nothing broken moves forward. The goal is to detect problems as early as possible and to produce a proven, immutable artifact.

YAML
# GitHub Actions: a simple CI/CD pipeline for a banking service
name: transfer-service-pipeline
on:
  push:
    branches: [main]
jobs:
  build-test-scan-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4          # Source
      - uses: actions/setup-java@v4        # Build
        with: { java-version: '21', distribution: 'temurin' }
      - run: mvn clean package             # Build + Test
      - run: mvn sonar:sonar               # Scan (quality gate)
      - run: trivy image --severity HIGH,CRITICAL $IMAGE  # Scan (CVE)
      - run: kubectl set image deployment/transfer-service  # Deploy
      - run: curl -f https://transfer.bank.local/actuator/health  # Verify

What happens at each stage?

The source stage checks out the exact commit. A trigger such as a Git push or a merged pull request causes the CI server to fetch the code at a known SHA so every later stage works on identical code.

The build stage compiles the source and assembles the primary artifact. For a Spring Boot banking service this is usually mvn clean package -DskipTests, which produces a runnable JAR. Separating build from test lets you fail fast on compilation errors.

BASH
# Build the banking transfer service
mvn clean package -DskipTests
# Output: target/transfer-service-1.4.2.jar

The test stage runs automated tests. Unit tests run first because they are fast, then integration tests run against a throwaway database spun up with Testcontainers.

BASH
# Run unit tests
mvn test
# Run integration tests with Testcontainers Postgres
mvn verify -Pintegration

The package stage produces a deployable unit. In a container world this is building and tagging an image.

BASH
# Package as a container image tagged with the commit SHA
docker build -t registry.bank.local/transfer-service:abc1234 .

The scan stage enforces quality and security. SonarQube checks code quality and coverage; Trivy checks for known CVEs.

BASH
# Quality gate
mvn sonar:sonar -Dsonar.qualitygate.wait=true
# Vulnerability scan
trivy image --exit-code 1 --severity HIGH,CRITICAL \
  registry.bank.local/transfer-service:abc1234

The deploy stage pushes the artifact to an environment.

BASH
# Deploy to Kubernetes
kubectl set image deployment/transfer-service \
  transfer-service=registry.bank.local/transfer-service:abc1234 \
  -n production

The verify stage confirms the deployment is healthy with smoke tests and health checks.

BASH
# Health check
curl -f https://transfer.bank.local/actuator/health
# Business smoke test: a test transfer
curl -X POST https://transfer.bank.local/api/transfers \
  -d '{"from":"SAV2001","to":"SAV2002","amount":"1.00"}'

What is Continuous Integration?

Continuous Integration is the practice of merging every developer's change frequently and automatically building and testing each merge. The goal is to catch integration problems within minutes, not days.

GROOVY
// Jenkinsfile: CI pipeline triggered on every push
pipeline {
    agent any
    triggers { githubPush() }
    stages {
        stage('Build') { steps { sh 'mvn clean compile' } }
        stage('Test')  { steps { sh 'mvn test' } }
        stage('Scan')  { steps { sh 'mvn sonar:sonar' } }
    }
}

CI stops at a green build and test. It does not deploy to any environment.

What is Continuous Delivery?

Continuous Delivery extends CI so that every passing build is automatically prepared as a release-ready artifact. The final push to production is behind a manual approval gate.

GROOVY
// Jenkinsfile: Continuous Delivery with manual approval before Prod
pipeline {
    agent any
    stages {
        stage('Build & Test') { steps { sh 'mvn clean verify' } }
        stage('Package')      { steps { sh 'docker build -t $IMAGE .' } }
        stage('Deploy QA')    { steps { sh 'kubectl apply -f qa/' } }
        stage('Approval') {
            steps {
                input message: 'Deploy to production?',
                      submitter: 'release-managers'
            }
        }
        stage('Deploy Prod')  { steps { sh 'kubectl apply -f prod/' } }
    }
}

This is the standard for banking because a human must sign off before touching the live ledger.

What is Continuous Deployment?

Continuous Deployment removes the manual gate entirely. Every green build reaches production automatically with no human approval.

YAML
# GitHub Actions: full Continuous Deployment
jobs:
  deploy-prod:
    needs: [build, test, scan]
    runs-on: ubuntu-latest
    steps:
      - run: kubectl set image deployment/transfer-service $IMAGE
      - run: curl -f https://transfer.bank.local/actuator/health
    # No manual approval step. Every green build goes to Prod.

How do CI, CD (Delivery), and CD (Deployment) compare?

| Aspect | Continuous Integration | Continuous Delivery | Continuous Deployment |
|---|---|---|---|
| Trigger | Every commit | Every commit | Every commit |
| Build and test | Automated | Automated | Automated |
| Artifact produced | Yes | Yes, release-ready | Yes, release-ready |
| Deploy to staging | Not included | Automated | Automated |
| Deploy to production | Not included | Manual approval | Fully automated |
| Rollback | Not applicable | Manual or automated | Automated |
| Banking suitability | Always | Production (regulated) | Dev and QA environments |

What are common mistakes?

YAML
# WRONG: deploying without scanning.
# A vulnerable dependency reaches production.
steps:
  - run: mvn clean package
  - run: docker build -t $IMAGE .
  - run: kubectl apply -f prod/   # No scan, no quality gate!

# CORRECT: scan and gate before deploy.
steps:
  - run: mvn clean verify
  - run: mvn sonar:sonar -Dsonar.qualitygate.wait=true
  - run: docker build -t $IMAGE .
  - run: trivy image --exit-code 1 --severity HIGH,CRITICAL $IMAGE
  - run: kubectl apply -f prod/
YAML
# WRONG: rebuilding the artifact for each environment.
# What runs in Prod is not what was tested in QA.
steps:
  - run: mvn clean package   # Build #1 for QA
  - run: mvn clean package   # Build #2 for Prod -- different!

# CORRECT: build once, promote the same image.
steps:
  - run: mvn clean package
  - run: docker build -t $IMAGE:$SHA .
  # Promote the exact same image to QA, then to Prod.

What should a senior engineer know?

A senior engineer keeps the artifact immutable and traceable. The image is tagged with the commit SHA and promoted unchanged across every environment. This eliminates the classic problem of deploying the wrong version.

Regulated banking systems almost always use Continuous Delivery to production with an approval gate, while using full Continuous Deployment for lower environments like dev and QA.

BASH
# Tag with commit SHA for traceability
IMAGE=registry.bank.local/transfer-service:$(git rev-parse --short HEAD)
docker build -t $IMAGE .
docker push $IMAGE
# The same $IMAGE is deployed to dev, QA, and Prod.

The verify stage is not optional. A deploy that is not confirmed healthy is treated as a failure and rolled back automatically.

Visual Overview

DIAGRAM
  Developer pushes code
       │
       ▼
  ┌──────────┐   ┌──────────┐   ┌──────────┐
  │  SOURCE   │──▶│  BUILD   │──▶│   TEST   │
  │ checkout  │   │ compile  │   │ unit+int │
  └──────────┘   └──────────┘   └──────────┘
                                      │
       ┌──────────────────────────────┘
       ▼
  ┌──────────┐   ┌──────────┐   ┌──────────┐   ┌──────────┐
  │ PACKAGE  │──▶│   SCAN   │──▶│  DEPLOY  │──▶│  VERIFY  │
  │ image tag│   │ SonarQube│   │ kubectl  │   │ smoke    │
  │ :abc1234 │   │ Trivy    │   │ apply    │   │ health   │
  └──────────┘   └──────────┘   └──────────┘   └──────────┘

  CI vs Delivery vs Deployment:

  ├── CI ──────────────────────┤
  │ Build + Test               │
  │                            │
  ├── Continuous Delivery ─────┼──── Manual Gate ──── Prod
  │ Build + Test + Package +   │     (approval)
  │ Scan + Deploy to staging   │
  │                            │
  ├── Continuous Deployment ───┼──── Auto ──── Prod
  │ Everything automated,      │     (no gate)
  │ including production       │

Key Takeaway

A CI/CD pipeline is an automated sequence that carries a code change from commit to a running environment through well-defined stages. Each stage gates the next, so a failure stops promotion immediately and nothing broken moves forward. The stages are source, build, test, package, scan, deploy, and verify, and the key design principle is fail fast and promote only what is proven.

The three terms are often confused. Continuous Integration is the discipline of merging every change frequently and automatically building and testing it, catching integration problems within minutes. Continuous Delivery extends that so every passing build is release-ready, but production stays behind a manual approval. Continuous Deployment removes even that gate and releases every green build straight to production. In banking, production uses Continuous Delivery with a human gate while lower environments use full Continuous Deployment.

The most important practice is that the artifact must be immutable and traceable. The image is tagged with the commit SHA, built once, and promoted unchanged through every environment. This eliminates the classic problem of deploying something different from what was tested.

Remember one sentence: CI proves the code works, Delivery keeps it ready behind a button, and Deployment presses that button automatically.

---

Share
Use ← → arrow keys to navigate