Skip to main content
โšก Calmops

CI/CD Pipelines 2026 Complete Guide: Modern DevOps Practices

Introduction

Continuous Integration and Continuous Deployment (CI/CD) have evolved significantly. In 2026, pipelines are faster, more secure, and more automated than ever. From cloud-native builds to intelligent testing, modern CI/CD transforms how software gets delivered.

This guide covers the CI/CD landscape in 2026, from major platforms to best practices. Whether you’re setting up your first pipeline or optimizing existing workflows, this guide provides practical insights.

Modern CI/CD Platforms

GitHub Actions

# .github/workflows/ci.yml
name: CI Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

env:
  NODE_VERSION: '20'
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  test:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: ${{ env.NODE_VERSION }}
        cache: 'npm'
    
    - name: Install dependencies
      run: npm ci
    
    - name: Run linter
      run: npm run lint
    
    - name: Run tests
      run: npm test
      env:
        CI: true
        DATABASE_URL: ${{ secrets.DATABASE_URL }}
    
    - name: Upload coverage
      uses: codecov/codecov-action@v4
      with:
        token: ${{ secrets.CODECOV_TOKEN }}

  build:
    needs: test
    runs-on: ubuntu-latest
    if: github.event_name == 'push'
    
    steps:
    - uses: actions/checkout@v4
    
    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v3
    
    - name: Login to Container Registry
      uses: docker/login-action@v3
      with:
        registry: ${{ env.REGISTRY }}
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}
    
    - name: Build and push
      uses: docker/build-push-action@v5
      with:
        context: .
        push: true
        tags: |
          ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
          ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
        cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache
        cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment: production
    
    steps:
    - name: Deploy to production
      run: |
        echo "Deploying to production..."
        # Add deployment commands

GitLab CI/CD

# .gitlab-ci.yml
stages:
  - test
  - build
  - deploy

variables:
  NODE_VERSION: "20"
  DOCKER_IMAGE: $CI_REGISTRY_IMAGE

test:
  stage: test
  image: node:${NODE_VERSION}
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - node_modules/
  script:
    - npm ci
    - npm run lint
    - npm test -- --coverage
  coverage: '/Coverage: \d+\.\d+%/'

build:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker build -t $DOCKER_IMAGE:$CI_COMMIT_SHA .
    - docker push $DOCKER_IMAGE:$CI_COMMIT_SHA
  only:
    - main

deploy:
  stage: deploy
  image: alpine:latest
  script:
    - apk add --no-cache curl
    - curl -X POST $DEPLOY_WEBHOOK
  environment:
    name: production
    url: https://example.com
  only:
    - main

CircleCI

# .circleci/config.yml
version: 2.1

orbs:
  node: circleci/node@5
  docker: circleci/docker@2

workflows:
  build-test-deploy:
    jobs:
      - node/test:
          version: '20'
          pkg-manager: npm
      
      - docker/build:
          image: myapp
          tag: $CIRCLE_SHA1
      
      - docker/publish:
          requires:
            - docker/build
          registry: ghcr.io
          repo: org/myapp
          tag: $CIRCLE_SHA1
      
      - deploy/production:
          requires:
            - docker/publish
          filters:
            branches:
              only: main

Pipeline Security

Secret Management

# Using secrets in GitHub Actions
steps:
- name: Deploy
  env:
    API_TOKEN: ${{ secrets.API_TOKEN }}
  run: |
    curl -H "Authorization: Bearer $API_TOKEN" \
      https://api.example.com/deploy

Security Scanning

# Dependency scanning
- name: Audit dependencies
  run: npm audit --audit-level=high

# Container scanning
- name: Trivy vulnerability scan
  uses: aquasecurity/trivy-action@master
  with:
    scan-type: 'fs'
    severity: 'CRITICAL,HIGH'
    exit-code: '1'

# SAST scanning
- name: CodeQL Analysis
  uses: github/codeql-action/analyze@v3
  with:
    languages: javascript,typescript
    queries: security-extended

# Infrastructure scanning
- name: Checkov
  uses: bridgecrewio/checkov-action@master
  with:
    directory: ./infrastructure
    framework: terraform

Supply Chain Security

# SLSA compliance
- name: Generate SLSA provenance
  uses: slsa-framework/slsa-action@v1
  with:
    provenancename: "provenance.json"

# SBOM generation
- name: Generate SBOM
  uses: cyclonedx/cyclonedx-npm@v1
  with:
    output-file: sbom.json

Testing in CI/CD

Test Strategies

# Unit tests
- name: Unit Tests
  run: npm run test:unit

# Integration tests
- name: Integration Tests
  run: npm run test:integration
  services:
    - name: postgres
      image: postgres:16
      env:
        POSTGRES_DB: test
        POSTGRES_USER: test
        POSTGRES_PASSWORD: test
    - name: redis
      image: redis:7

# E2E tests
- name: E2E Tests
  run: npm run test:e2e
  environment:
    BASE_URL: https://staging.example.com

# Performance tests
- name: Load Testing
  run: |
    k6 run --out json=k6-results.json tests/load.js

Test Parallelization

# Split tests across jobs
jobs:
  test-part-1:
    runs-on: ubuntu-latest
    steps:
      - run: npm test -- --grep "part1"
  
  test-part-2:
    runs-on: ubuntu-latest
    steps:
      - run: npm test -- --grep "part2"
  
  test-part-3:
    runs-on: ubuntu-latest
    steps:
      - run: npm test -- --grep "part3"

Deployment Strategies

Blue-Green Deployment

# Blue-green deployment
- name: Deploy to blue
  run: |
    kubectl set image deployment/app-blue app=$IMAGE:blue
    kubectl rollout status deployment/app-blue

- name: Run smoke tests
  run: |
    curl -f https://blue.example.com/health || exit 1

- name: Switch traffic
  run: |
    kubectl patch service app -p '{"spec":{"selector":{"version":"blue"}}}'

- name: Monitor and rollback
  if: failure()
  run: |
    kubectl rollout undo deployment/app-blue

Canary Deployment

# Canary deployment
- name: Deploy canary
  run: |
    kubectl apply -f canary.yaml

- name: Route 10% traffic to canary
  run: |
    kubectl apply -f canary-ingress.yaml

- name: Monitor metrics
  run: |
    # Check error rate
    ERROR_RATE=$(curl -s metrics.example.com/error-rate)
    if (( $(echo "$ERROR_RATE > 0.05" | bc -l) )); then
      echo "Error rate too high, rolling back"
      kubectl delete -f canary.yaml
      exit 1
    fi

- name: Promote canary
  if: success()
  run: |
    kubectl scale deployment/app --replicas=10

GitOps Deployment

# ArgoCD Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/org/repo.git
    targetRevision: HEAD
    path: deploy
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Cloud-Native Build

Build Caching

# Docker layer caching
- name: Build with cache
  uses: docker/build-push-action@v5
  with:
    context: .
    cache-from: type=gha
    cache-to: type=gha,mode=max

# npm cache
- name: Cache npm
  uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-npm-

# Build artifact caching
- name: Cache build
  uses: actions/cache@v4
  with:
    path: |
      dist/
      build/
    key: ${{ runner.os }}-build-${{ github.sha }}

Container Build

# Multi-platform build
- name: Build multi-platform
  uses: docker/build-push-action@v5
  with:
    context: .
    platforms: linux/amd64,linux/arm64
    push: true
    tags: |
      app:latest
      app:${{ github.sha }}

Monitoring and Feedback

Pipeline Metrics

# Record metrics
- name: Report metrics
  run: |
    METRICS=$(npm run test:coverage -- --json)
    echo "::notice::Coverage: $METRICS"

Slack Notifications

# Notify on completion
- name: Notify Slack
  if: always()
  uses: 8398a7/action-slack@v3
  with:
    status: ${{ job.status }}
    fields: repo,message,commit,author
  env:
    SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}

External Resources

CI/CD Platforms

Tools

  • ArgoCD - GitOps controller
  • Flux - GitOps toolkit
  • Tekton - Cloud-native pipelines

Security

Conclusion

CI/CD in 2026 is about speed, security, and reliability. Modern pipelines automate everything from code review to production deployment, with built-in security at every step.

Focus on incremental improvements: faster builds, better caching, comprehensive testing, and secure deployments. The best pipeline is one that gets code to production safely and quickly while maintaining high quality.

Stay current with platform features, adopt GitOps practices, and always prioritize security. Your pipeline is the backbone of your software delivery.

Comments