CI/CD Pipeline Explained: From Code Commit to Production Deployment
📅 Published: June 2026
⏱️ Estimated Reading Time: 20 minutes
🏷️ Tags: CI/CD, Jenkins, GitHub Actions, GitLab CI, DevOps, Automation
Introduction: What is CI/CD?
CI/CD stands for Continuous Integration and Continuous Delivery (or Continuous Deployment). It is the backbone of modern software development, enabling teams to ship code faster, more reliably, and with less manual work.
Think of CI/CD as an assembly line for software. Just as a car assembly line moves a car through stations where robots install parts, test quality, and prepare for shipping, a CI/CD pipeline moves code through automated stages where it is tested, built, and deployed.
Without CI/CD:
Developers merge code manually, hoping nothing breaks
Tests run on someone's laptop, not consistently
Deployments happen on Friday afternoons (everyone's favorite)
Rollbacks involve searching for old files and praying
With CI/CD:
Every code change runs through the same automated process
Tests run every time, the same way, every time
Deployments are one-click (or zero-click)
Rollbacks are instant and reliable
The Two Halves: CI and CD
Continuous Integration (CI)
Continuous Integration means merging code changes frequently (multiple times per day) and automatically testing each change. The goal is to catch integration issues early, when they are cheap to fix.
What CI does:
Developer pushes code to Git
CI server detects the push
Server pulls the code
Server runs tests
Server reports results (pass/fail)
The "integration" part means you merge to main frequently. Small, frequent merges are easier to debug than massive monthly merges.
Continuous Delivery (CD)
Continuous Delivery means that after CI passes, the code is automatically built and deployed to a staging environment. It is ready to be deployed to production with a single click.
What CD does:
CI passes
Build artifacts (Docker images, binaries) are created
Deployed to staging environment
Acceptance tests run
Ready for production deployment (manual approval)
Continuous Deployment (CD - same acronym, different meaning)
Continuous Deployment takes it one step further: every change that passes CI is automatically deployed to production. No manual approval required.
The difference:
Continuous Delivery: Ready to deploy, human clicks button
Continuous Deployment: Deploys automatically
Which should you choose?
Continuous Delivery for most teams, especially regulated industries
Continuous Deployment for high-confidence teams, SaaS products, when speed is critical
The CI/CD Pipeline Stages
A typical CI/CD pipeline has six stages:
Code Commit → Build → Test → Deploy (Staging) → Acceptance → Deploy (Production)
Stage 1: Code Commit
Developer pushes code to Git repository (GitHub, GitLab, Bitbucket). This triggers the pipeline automatically.
git add . git commit -m "feat: add login feature" git push origin main
Stage 2: Build
The CI server pulls the code and builds the application. This creates deployable artifacts.
| Type of App | Build Output |
|---|---|
| Node.js | Minified JavaScript, node_modules |
| Java | JAR or WAR file |
| Python | Package or wheel |
| Go | Binary executable |
| Docker | Container image |
Example build step (GitHub Actions):
- name: Build Docker image run: docker build -t myapp:${{ github.sha }} .
Stage 3: Test
Automated tests run to verify the code works correctly.
Types of tests:
Unit tests: Test individual functions
Integration tests: Test components together
Linting: Check code style
Security scanning: Find vulnerabilities
Container scanning: Check Docker images
Example test step:
- name: Run tests run: npm test
Stage 4: Deploy to Staging
The built artifact is deployed to a staging environment that mirrors production.
Why staging matters:
Catch environment-specific issues before production
Run integration tests against real services
Demo features to stakeholders safely
Load testing without affecting users
Stage 5: Acceptance / Verification
After deployment to staging, additional tests run against the live environment.
Smoke tests: Basic functionality works (app is up, database connects)
E2E tests: Full user journeys (login, purchase, logout)
Performance tests: Response times, throughput
Security tests: Vulnerability scanning
Stage 6: Deploy to Production
The approved artifact is deployed to production. This may be automatic (Continuous Deployment) or manual (Continuous Delivery).
Deployment strategies:
| Strategy | Description | Downtime |
|---|---|---|
| Rolling Update | Gradually replace old instances | Zero |
| Blue-Green | Switch traffic to new environment | Zero |
| Canary | Slowly roll out to small percentage | Zero |
| Recreate | Stop old, start new | Yes |
CI/CD Tools Comparison
| Tool | Best For | Key Features |
|---|---|---|
| GitHub Actions | GitHub users | Native integration, free for public repos |
| GitLab CI | GitLab users | Built-in, integrated with GitLab |
| Jenkins | Complex, customizable pipelines | Huge plugin ecosystem |
| CircleCI | Fast builds, parallel execution | Excellent caching |
| Travis CI | Open source projects | Free for public repos |
| Azure Pipelines | Microsoft ecosystem | Integration with Azure |
| AWS CodePipeline | AWS users | Native AWS integration |
Pipeline Example: GitHub Actions
# .github/workflows/ci-cd.yml name: CI/CD Pipeline on: push: branches: [ main, develop ] pull_request: branches: [ main ] env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} jobs: # Stage 1: Test test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '18' - name: Install dependencies run: npm ci - name: Lint run: npm run lint - name: Unit tests run: npm test - name: Security scan run: npm audit # Stage 2: Build build: runs-on: ubuntu-latest needs: test steps: - uses: actions/checkout@v4 - name: Build Docker image run: docker build -t ${{ env.IMAGE_NAME }}:${{ github.sha }} . - name: Push to registry run: | echo ${{ secrets.GITHUB_TOKEN }} | docker login ${{ env.REGISTRY }} -u ${{ github.actor }} --password-stdin docker push ${{ env.IMAGE_NAME }}:${{ github.sha }} # Stage 3: Deploy to Staging deploy-staging: runs-on: ubuntu-latest needs: build if: github.ref == 'refs/heads/develop' environment: staging steps: - name: Deploy to staging run: | kubectl set image deployment/myapp myapp=${{ env.IMAGE_NAME }}:${{ github.sha }} -n staging kubectl rollout status deployment/myapp -n staging # Stage 4: Acceptance tests acceptance: runs-on: ubuntu-latest needs: deploy-staging environment: staging steps: - name: Run smoke tests run: | curl -f https://staging.example.com/health # Stage 5: Deploy to Production deploy-production: runs-on: ubuntu-latest needs: acceptance if: github.ref == 'refs/heads/main' environment: name: production url: https://example.com steps: - name: Deploy to production run: | kubectl set image deployment/myapp myapp=${{ env.IMAGE_NAME }}:${{ github.sha }} -n production kubectl rollout status deployment/myapp -n production
Pipeline Example: GitLab CI
# .gitlab-ci.yml stages: - test - build - deploy-staging - acceptance - deploy-production variables: IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA # Stage 1: Test test: stage: test script: - npm ci - npm run lint - npm test - npm audit only: - main - develop # Stage 2: Build build: stage: build script: - docker build -t $IMAGE_TAG . - docker push $IMAGE_TAG only: - main - develop # Stage 3: Deploy to Staging deploy-staging: stage: deploy-staging script: - kubectl set image deployment/myapp myapp=$IMAGE_TAG -n staging - kubectl rollout status deployment/myapp -n staging environment: name: staging url: https://staging.example.com only: - develop # Stage 4: Acceptance acceptance: stage: acceptance script: - curl -f https://staging.example.com/health environment: name: staging only: - develop # Stage 5: Deploy to Production deploy-production: stage: deploy-production script: - kubectl set image deployment/myapp myapp=$IMAGE_TAG -n production - kubectl rollout status deployment/myapp -n production environment: name: production url: https://example.com only: - main when: manual
Benefits of CI/CD
For Developers
Less manual work: No more "but it worked on my machine"
Fast feedback: Know within minutes if you broke something
Smaller merges: Merge daily, not monthly
Less stress: Automated rollbacks if something fails
For Teams
Shared ownership: Everyone sees the pipeline results
Consistent process: Every change follows the same path
Better quality: Bugs caught earlier
Higher velocity: Deploy more often, with confidence
For Business
Faster time to market: Features reach users faster
Higher reliability: Fewer deployment failures
Better security: Automated vulnerability scanning
Audit trail: Every change is tracked
Common CI/CD Anti-Patterns
| Anti-Pattern | Problem | Solution |
|---|---|---|
| Long-running branches | Merges become painful | Merge to main daily |
| Large commits | Hard to review, debug | Small, focused commits |
| Skipping tests locally | CI fails repeatedly | Run tests before push |
| Manual deployment steps | Error-prone, slow | Automate everything |
| Same pipeline for all apps | Suboptimal, slow | Optimize per app |
| Not testing rollbacks | Rollbacks fail | Practice rollback regularly |
CI/CD Maturity Model
| Level | What Happens | Risk |
|---|---|---|
| Level 0 | Manual builds, manual tests, manual deploys | High |
| Level 1 | Automated builds, manual tests, manual deploys | Medium |
| Level 2 | Automated builds, automated tests, manual deploys | Low |
| Level 3 | Automated builds, automated tests, automated staging | Very Low |
| Level 4 | Fully automated, Continuous Deployment | Minimal |
Most teams start at Level 0-1 and progress toward Level 3-4 over time.
Getting Started with CI/CD
Step 1: Automate Builds
Start with simple build automation. Every time code is pushed, build it.
Step 2: Add Linting and Unit Tests
Add style checking and small, fast tests that run in seconds.
Step 3: Add Integration Tests
Test how components work together. These take minutes.
Step 4: Automate Staging Deployment
Deploy to a staging environment automatically after tests pass.
Step 5: Add Acceptance Tests
Test the running application in staging.
Step 6: Automate Production Deployment (Optional)
Deploy to production automatically or with one click.
Summary
CI/CD transforms software delivery from a stressful, manual process into a reliable, automated pipeline.
| Phase | Purpose | Automation Level |
|---|---|---|
| Continuous Integration | Merge and test frequently | Fully automated |
| Continuous Delivery | Ready to deploy, manual approval | Automated up to production |
| Continuous Deployment | Deploy everything that passes | Fully automated |
The journey starts small:
Add a simple build script
Add tests to your script
Run it on every push
Add deployment automation
Add approval gates
You don't need to build the perfect pipeline overnight. Start with one stage—perhaps just running tests on every push. Add more stages as you gain confidence.
Learn More
Practice building CI/CD pipelines with hands-on exercises in our interactive labs:
https://devops.trainwithsky.com/
Comments
Post a Comment