Skip to content
Published on

Advanced CI/CD Pipeline Guide 2025: Deployment Strategies, GitOps, Monorepo, Security Pipeline

Authors

Introduction

According to the 2024 DORA (DevOps Research and Assessment) report, elite teams deploy multiple times per day with a change failure rate below 5%. Low-performing teams deploy once a month and take weeks to recover. The key differentiator is CI/CD pipeline maturity.

Beyond simple build-test-deploy, modern CI/CD encompasses deployment strategies (Blue-Green, Canary), GitOps, monorepo optimization, feature flags, and security pipelines. This guide systematically covers advanced CI/CD strategies proven in production environments in 2025.


1. Deployment Strategies

1.1 Rolling Update

The most basic deployment method, replacing instances sequentially.

Time ->

Instance 1:  [v1] [v1] [v2] [v2] [v2]
Instance 2:  [v1] [v1] [v1] [v2] [v2]
Instance 3:  [v1] [v1] [v1] [v1] [v2]

Traffic:     100% v1 -> mixed -> 100% v2
# Kubernetes Rolling Update
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-server
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1        # Max 1 additional Pod
      maxUnavailable: 0  # Zero downtime
  template:
    spec:
      containers:
        - name: api
          image: myapp:v2
          readinessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 10
            periodSeconds: 5

Pros: Simple, minimal extra resources, gradual replacement Cons: Mixed v1/v2 traffic during deployment, difficult instant rollback

1.2 Blue-Green Deployment

Maintain two identical environments (Blue/Green) and switch traffic all at once.

┌─────────────────────────────────────────────┐
│                                             │
Load Balancer|v (Before switch: traffic to Blue)│   ┌───────────┐     ┌───────────┐           │
│   │   Blue    │     │   Green   │           │
   (v1)   (v2)    │           │
│   │  Active   │     │  Standby  │           │
│   └───────────┘     └───────────┘           │
│                                             │
After switch: 100% traffic to Green│                                             │
│   ┌───────────┐     ┌───────────┐           │
│   │   Blue    │     │   Green   │           │
   (v1)   (v2)    │           │
│   │  Standby  │     │  Active   │           │
│   └───────────┘     └───────────┘           │
└─────────────────────────────────────────────┘
# Blue-Green with AWS ALB (GitHub Actions)
name: Blue-Green Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build and Push Docker Image
        run: |
          docker build -t myapp:${{ github.sha }} .
          docker push myregistry/myapp:${{ github.sha }}

      - name: Deploy to Green Environment
        run: |
          aws ecs update-service \
            --cluster production \
            --service green-service \
            --task-definition myapp:${{ github.sha }}

      - name: Run Smoke Tests on Green
        run: |
          ./scripts/smoke-test.sh https://green.myapp.com

      - name: Switch Traffic to Green
        run: |
          aws elbv2 modify-listener \
            --listener-arn ${{ secrets.ALB_LISTENER_ARN }} \
            --default-actions \
              Type=forward,TargetGroupArn=${{ secrets.GREEN_TG_ARN }}

Pros: Instant rollback (switch traffic to Blue), zero downtime Cons: 2x infrastructure cost, complex database migrations

1.3 Canary Deployment

Deploy the new version to a small percentage of traffic first for validation.

Phase 1: 5% traffic to Canary (v2)
┌──────────────────────────────┐
│ v1 v1 v1 v1 v1 v1 v1 v1 v1  │ 95%
│ v2                           │  5%
└──────────────────────────────┘

Phase 2: Expand to 25% after validation
┌──────────────────────────────┐
│ v1 v1 v1 v1 v1 v1 v1        │ 75%
│ v2 v2 v2                     │ 25%
└──────────────────────────────┘

Phase 3: 100% after confirming stability
┌──────────────────────────────┐
│ v2 v2 v2 v2 v2 v2 v2 v2 v2  │ 100%
└──────────────────────────────┘
# Canary Deployment with Istio
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: myapp
spec:
  hosts:
    - myapp.example.com
  http:
    - route:
        - destination:
            host: myapp
            subset: stable
          weight: 95
        - destination:
            host: myapp
            subset: canary
          weight: 5
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: myapp
spec:
  host: myapp
  subsets:
    - name: stable
      labels:
        version: v1
    - name: canary
      labels:
        version: v2

Pros: Minimized risk, validation with real traffic, progressive rollout Cons: Implementation complexity, requires metrics-based automation

1.4 Deployment Strategy Comparison

StrategyDowntimeRollback SpeedCostComplexityBest For
RollingNoneSlowLowLowGeneral services
Blue-GreenNoneInstantHigh (2x)MediumCritical services
CanaryNoneFastMediumHighHigh-traffic services
A/B TestingNoneFastMediumVery HighFeature experiments

2. GitOps

2.1 GitOps Principles

┌──────────────────────────────────────────────────────┐
GitOps Principles│                                                      │
1. Declarative- System state declared as code                   │
│                                                      │
2. Versioned- Git is the Single Source of Truth (SSOT)│                                                      │
3. Automated- Approved changes auto-applied to system          │
│                                                      │
4. Self-healing                                      │
- Auto-corrects drift between desired/actual state │
└──────────────────────────────────────────────────────┘

2.2 ArgoCD Configuration

# argocd-application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp-production
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/k8s-manifests.git
    targetRevision: main
    path: apps/myapp/overlays/production
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true         # Clean up orphaned resources
      selfHeal: true      # Auto-revert manual changes
      allowEmpty: false
    syncOptions:
      - CreateNamespace=true
      - PrunePropagationPolicy=foreground
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m

2.3 ArgoCD App-of-Apps Pattern

# root-application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: root-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/k8s-manifests.git
    targetRevision: main
    path: apps
  destination:
    server: https://kubernetes.default.svc

# apps/ directory structure
# apps/
#   myapp/
#     application.yaml
#   api-gateway/
#     application.yaml
#   monitoring/
#     application.yaml
#   cert-manager/
#     application.yaml

2.4 ArgoCD vs Flux Comparison

FeatureArgoCDFlux v2
UI DashboardBuilt-in web UIWeave GitOps (separate)
Multi-clusterSupportedSupported
Helm SupportNativeHelmRelease CRD
KustomizeNativeNative
Image Auto-updateArgoCD Image UpdaterBuilt-in
NotificationsArgoCD NotificationsNotification Controller
RBACBuilt-inUses Kubernetes RBAC
ApproachPull-basedPull-based
Learning CurveMediumMedium-High

2.5 ArgoCD Notification Setup

# argocd-notifications-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-notifications-cm
  namespace: argocd
data:
  service.slack: |
    token: $slack-token
  trigger.on-sync-succeeded: |
    - when: app.status.sync.status == 'Synced'
      send: [app-sync-succeeded]
  trigger.on-sync-failed: |
    - when: app.status.sync.status == 'Unknown'
      send: [app-sync-failed]
  template.app-sync-succeeded: |
    slack:
      attachments: |
        [{
          "color": "#18be52",
          "title": "{{.app.metadata.name}} sync succeeded",
          "text": "Deployment complete: {{.app.spec.source.targetRevision}}"
        }]
  template.app-sync-failed: |
    slack:
      attachments: |
        [{
          "color": "#E96D76",
          "title": "{{.app.metadata.name}} sync failed",
          "text": "Error: {{.app.status.conditions}}"
        }]

3. Monorepo CI

3.1 Monorepo Structure

monorepo/
  apps/
    web/           # Next.js frontend
    api/           # Express backend
    mobile/        # React Native app
  packages/
    ui/            # Shared UI components
    utils/         # Shared utilities
    config/        # Shared configuration
  turbo.json       # Turborepo config
  nx.json          # Or Nx config
  package.json

3.2 Turborepo Configuration

{
  "globalDependencies": ["**/.env.*local"],
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**"],
      "cache": true
    },
    "test": {
      "dependsOn": ["build"],
      "outputs": [],
      "cache": true
    },
    "lint": {
      "outputs": [],
      "cache": true
    },
    "deploy": {
      "dependsOn": ["build", "test", "lint"],
      "cache": false
    }
  }
}

3.3 Nx Affected Builds

# .github/workflows/monorepo-ci.yml
name: Monorepo CI

on:
  pull_request:
    branches: [main]

jobs:
  affected:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Full history needed

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'

      - run: npm ci

      # Only build/test changed projects
      - name: Lint affected
        run: npx nx affected --target=lint --base=origin/main

      - name: Test affected
        run: npx nx affected --target=test --base=origin/main

      - name: Build affected
        run: npx nx affected --target=build --base=origin/main

  # Remote Caching
  remote-cache:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - name: Build with remote cache
        run: npx turbo build --team=myteam --token=${{ secrets.TURBO_TOKEN }}
        env:
          TURBO_TEAM: myteam
          TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}

3.4 Turborepo vs Nx vs Bazel

FeatureTurborepoNxBazel
Learning CurveLowMediumHigh
Language SupportJS/TSJS/TS, Go, Rust, etc.Multi-language
Change DetectionFile hashesProject graphDependency graph
Remote CachingVercel RCNx CloudRemote Execution
Config ComplexityVery simpleMediumComplex
Scale SuitabilityMediumLargeVery large
Code GenerationNoneBuilt-in GeneratorRules

4. Feature Flags

4.1 Types of Feature Flags

┌──────────────────────────────────────────────────┐
Feature Flag Types├──────────────────────────────────────────────────┤
│                                                  │
1. Release Flag- Hide incomplete features while deploying    │
- Lifespan: Short (days to weeks)│                                                  │
2. Experiment Flag- A/B testing, feature comparison             │
- Lifespan: Medium (weeks to months)│                                                  │
3. Ops Flag- System behavior control (kill switch)- Lifespan: Permanent│                                                  │
4. Permission Flag- Per-user/organization feature access         │
- Lifespan: Permanent└──────────────────────────────────────────────────┘

4.2 Implementation Example

// featureFlags.ts
import { UnleashClient } from 'unleash-proxy-client';

const unleash = new UnleashClient({
  url: 'https://unleash.myapp.com/api/frontend',
  clientKey: process.env.UNLEASH_CLIENT_KEY!,
  appName: 'myapp-frontend',
  refreshInterval: 15,
});

unleash.start();

// React Hook
export function useFeatureFlag(flagName: string): boolean {
  const [enabled, setEnabled] = useState(false);

  useEffect(() => {
    setEnabled(unleash.isEnabled(flagName));

    const handler = () => {
      setEnabled(unleash.isEnabled(flagName));
    };
    unleash.on('update', handler);
    return () => unleash.off('update', handler);
  }, [flagName]);

  return enabled;
}

// Usage in component
function CheckoutPage() {
  const newCheckoutEnabled = useFeatureFlag('new-checkout-flow');

  if (newCheckoutEnabled) {
    return <NewCheckoutFlow />;
  }
  return <LegacyCheckoutFlow />;
}

4.3 Progressive Rollout

// Server-side feature flags (LaunchDarkly style)
import LaunchDarkly from 'launchdarkly-node-server-sdk';

const client = LaunchDarkly.init(process.env.LD_SDK_KEY!);

async function getFeatureValue(
  flagKey: string,
  user: LDUser,
  defaultValue: boolean
): Promise<boolean> {
  await client.waitForInitialization();
  return client.variation(flagKey, user, defaultValue);
}

// Progressive rollout phases:
// Phase 1: Internal employees only (beta-testers group)
// Phase 2: 5% of users
// Phase 3: 25% of users
// Phase 4: 50% of users
// Phase 5: 100% of users

// Kill switch pattern
async function processPayment(order: Order) {
  const newPaymentEnabled = await getFeatureValue(
    'new-payment-gateway',
    { key: order.userId },
    false  // Default: disabled
  );

  if (newPaymentEnabled) {
    return newPaymentGateway.process(order);
  }
  return legacyPaymentGateway.process(order);
}

4.4 LaunchDarkly vs Unleash vs Flagsmith

FeatureLaunchDarklyUnleashFlagsmith
PricingPaid (expensive)Open source + EnterpriseOpen source + Cloud
TargetingVery sophisticatedBasicSophisticated
A/B TestingBuilt-inSeparateBuilt-in
SDK Support25+ languages15+ languages15+ languages
Self-hostingNot availableAvailableAvailable
Audit LogsSupportedSupportedSupported

5. Environment Management

5.1 Environment Hierarchy

┌─────────────────────────────────────────┐
Production- Real user traffic                     │
- Highest level monitoring              │
- Change approval process               │
├─────────────────────────────────────────┤
Staging- Identical to production config        │
- QA team testing                       │
- Integration tests                     │
├─────────────────────────────────────────┤
Development- Latest feature integration            │
- Auto-deploy from main branch          │
├─────────────────────────────────────────┤
PR Preview- Independent environment per PR- Auto-deleted when PR closes           │
└─────────────────────────────────────────┘

5.2 Ephemeral Environments

# .github/workflows/preview.yml
name: PR Preview Environment

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  deploy-preview:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy Preview
        run: |
          PREVIEW_URL="pr-${{ github.event.number }}.preview.myapp.com"
          helm upgrade --install \
            pr-${{ github.event.number }} \
            ./charts/myapp \
            --namespace previews \
            --set image.tag=${{ github.sha }} \
            --set ingress.host=$PREVIEW_URL \
            --set resources.requests.memory=256Mi \
            --set resources.requests.cpu=100m

      - name: Comment PR with URL
        uses: actions/github-script@v7
        with:
          script: |
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `Preview deployed: https://pr-${context.issue.number}.preview.myapp.com`
            })

  cleanup-preview:
    if: github.event.action == 'closed'
    runs-on: ubuntu-latest
    steps:
      - name: Delete Preview
        run: |
          helm uninstall pr-${{ github.event.number }} \
            --namespace previews

6. Pipeline Security

6.1 Secrets Management

# GitHub Actions - AWS Auth via OIDC (no long-lived secrets)
name: Secure Deploy

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # OIDC-based AWS auth (no long-lived secrets needed)
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/github-actions-role
          aws-region: us-east-1

      # Secret scanning
      - name: Scan for secrets
        uses: trufflesecurity/trufflehog@v3
        with:
          path: ./
          extra_args: --only-verified

      # Container image scanning
      - name: Scan container image
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: myapp:${{ github.sha }}
          severity: 'CRITICAL,HIGH'
          exit-code: '1'

6.2 SLSA (Supply-chain Levels for Software Artifacts)

# SLSA Level 3 - Signed builds + provenance attestation
name: SLSA Build

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
      attestations: write
    steps:
      - uses: actions/checkout@v4

      - name: Build
        run: npm run build

      # Artifact signing with Sigstore
      - name: Sign artifact
        uses: sigstore/cosign-installer@v3

      - name: Sign container image
        run: |
          cosign sign \
            --yes \
            myregistry/myapp:${{ github.sha }}

      # Generate SLSA provenance attestation
      - name: Generate SLSA provenance
        uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0
        with:
          image: myregistry/myapp
          digest: ${{ steps.build.outputs.digest }}

6.3 Security Scanning Pipeline

# .github/workflows/security.yml
name: Security Pipeline

on:
  pull_request:
    branches: [main]
  schedule:
    - cron: '0 6 * * 1'  # Every Monday at 06:00

jobs:
  sast:
    name: Static Analysis
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run Semgrep
        uses: semgrep/semgrep-action@v1
        with:
          config: p/owasp-top-ten

  dependency-check:
    name: Dependency Audit
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm audit --audit-level=high
      - name: Snyk Test
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

  container-scan:
    name: Container Security
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build image
        run: docker build -t myapp:scan .
      - name: Trivy scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: myapp:scan
          severity: 'CRITICAL,HIGH'
          format: 'sarif'
          output: 'trivy-results.sarif'
      - name: Upload SARIF
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: 'trivy-results.sarif'

  iac-scan:
    name: Infrastructure as Code Scan
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Checkov scan
        uses: bridgecrewio/checkov-action@master
        with:
          directory: ./terraform
          framework: terraform

7. Rollback Strategies

7.1 Instant Rollback

# Kubernetes rollback
# Immediately rollback to last successful version
# kubectl rollout undo deployment/myapp

# GitHub Actions auto-rollback
name: Deploy with Auto-Rollback

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy new version
        id: deploy
        run: |
          kubectl set image deployment/myapp \
            myapp=myregistry/myapp:${{ github.sha }}
          kubectl rollout status deployment/myapp --timeout=300s

      - name: Run post-deploy checks
        id: healthcheck
        run: |
          for i in $(seq 1 10); do
            STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://myapp.com/health)
            if [ "$STATUS" != "200" ]; then
              echo "Health check failed: $STATUS"
              exit 1
            fi
            sleep 5
          done

      - name: Rollback on failure
        if: failure()
        run: |
          echo "Rolling back to previous version..."
          kubectl rollout undo deployment/myapp
          kubectl rollout status deployment/myapp --timeout=300s

7.2 Database-Aware Rollback

When DB schema changes are part of a deployment:

1. Forward-Compatible Migration (safe)
   ┌─────────────────────────────────────┐
Step 1: Add new column (nullable)Step 2: Deploy app v2 (uses both)Step 3: Migrate data                │
Step 4: Remove old column           │
   └─────────────────────────────────────┘

2. Expand-Contract Pattern
   Phase 1 (Expand): Add new schema, keep old
   Phase 2 (Migrate): Transfer data
   Phase 3 (Contract): Remove old schema

7.3 Forward-Fix vs Rollback Decision Guide

SituationRecommended StrategyReason
Simple bug fixForward-FixFix is faster than rollback
Critical outageInstant RollbackService recovery is top priority
Includes DB migrationForward-FixRisk of data loss on rollback
Performance degradationCanary RollbackAssess impact before deciding

8. Pipeline Performance Optimization

8.1 Caching Strategies

# .github/workflows/optimized-ci.yml
name: Optimized CI

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # Node.js dependency caching
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'

      # Docker layer caching
      - uses: docker/setup-buildx-action@v3
      - uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          tags: myapp:${{ github.sha }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

      # Turborepo remote caching
      - name: Build with cache
        run: npx turbo build --cache-dir=.turbo
        env:
          TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
          TURBO_TEAM: myteam

8.2 Parallelization Strategy

# Parallel job execution
jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run lint

  unit-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run test:unit

  type-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run type-check

  # Build after all checks pass
  build:
    needs: [lint, unit-test, type-check]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run build

8.3 Self-Hosted Runners

# Self-hosted runners (ARM64 Mac, etc.)
jobs:
  build-ios:
    runs-on: [self-hosted, macOS, ARM64]
    steps:
      - uses: actions/checkout@v4
      - name: Build iOS
        run: xcodebuild -workspace MyApp.xcworkspace ...

  build-android:
    runs-on: [self-hosted, Linux, X64]
    steps:
      - uses: actions/checkout@v4
      - name: Build Android
        run: ./gradlew assembleRelease

9. Release Management

9.1 Semantic Versioning

MAJOR.MINOR.PATCH (e.g., 2.1.3)

MAJOR: Incompatible API changes
MINOR: Backward-compatible new features
PATCH: Backward-compatible bug fixes

Examples:
  1.0.0 -> 1.0.1  (bug fix)
  1.0.1 -> 1.1.0  (new feature)
  1.1.0 -> 2.0.0  (Breaking Change)

9.2 Automated Release Notes

# .github/workflows/release.yml
name: Release

on:
  push:
    tags: ['v*']

permissions:
  contents: write

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Generate Changelog
        id: changelog
        uses: orhun/git-cliff-action@v3
        with:
          config: cliff.toml

      - name: Create Release
        uses: softprops/action-gh-release@v2
        with:
          body: ${{ steps.changelog.outputs.content }}
          draft: false
          prerelease: false

9.3 Conventional Commits

# Commit message format
# type(scope): description

feat(auth): add OAuth2.0 login support
fix(cart): resolve quantity update race condition
docs(api): update REST API documentation
chore(deps): upgrade express to v5.0
perf(db): optimize query for order listing
refactor(payment): extract payment strategy pattern
test(checkout): add E2E tests for checkout flow

# Breaking Change notation
feat(api)!: change response format for /orders endpoint

BREAKING CHANGE: The orders endpoint now returns
paginated responses instead of a flat array.

9.4 Release Train Model

┌─────────────────────────────────────────────┐
Release Train (bi-weekly releases)│                                             │
Week 1: Feature development + Code FreezeWeek 2: QA + Bug fixes + Release│                                             │
--+------+------+------+------+--│   v2.1   v2.2   v2.3   v2.4   v2.5│                                             │
Hotfixes deploy immediately from│ separate branch                             │
└─────────────────────────────────────────────┘

10. Multi-Cloud Deployment

10.1 Multi-Cloud with Terraform

# main.tf - Multi-cloud providers
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

# AWS deployment
resource "aws_ecs_service" "primary" {
  name            = "myapp-primary"
  cluster         = aws_ecs_cluster.main.id
  task_definition = aws_ecs_task_definition.app.arn
  desired_count   = 3

  load_balancer {
    target_group_arn = aws_lb_target_group.app.arn
    container_name   = "myapp"
    container_port   = 8080
  }
}

# GCP deployment (DR)
resource "google_cloud_run_service" "failover" {
  name     = "myapp-failover"
  location = "us-central1"

  template {
    spec {
      containers {
        image = "gcr.io/myproject/myapp:latest"
      }
    }
  }
}

11. Quiz

Q1: What is the biggest advantage of Blue-Green deployment?

A) Lower infrastructure costs B) Instant rollback capability C) Simple implementation D) Traffic splitting capability

Answer: B

Blue-Green deployment maintains two identical environments, so when issues arise, you can instantly switch the load balancer traffic back to the previous environment (Blue). The tradeoff is 2x infrastructure cost.

Q2: What is the role of the Git repository in GitOps?

A) Code backup storage B) CI/CD pipeline runner C) Single Source of Truth (SSOT) for infrastructure D) Monitoring dashboard

Answer: C

In GitOps, the Git repository serves as the Single Source of Truth (SSOT) for infrastructure and application state. All changes go through Git, and tools like ArgoCD/Flux synchronize Git state with the actual cluster state.

Q3: What is the benefit of "affected" builds in monorepo CI?

A) It always builds all projects B) It only builds changed projects and their dependents, saving time C) It ignores build caches D) It skips tests

Answer: B

Affected builds analyze the Git diff to selectively build and test only changed projects and their dependents. This significantly reduces CI time in large monorepos.

Q4: What is the "kill switch" purpose of Feature Flags?

A) Shuts down the server B) Instantly disables a problematic feature without code deployment C) Deletes the database D) Stops the CI pipeline

Answer: B

A kill switch toggles a feature flag to OFF in production when problems occur, instantly disabling that feature without deploying new code. This is much faster than a rollback.

Q5: What is the purpose of SLSA (Supply-chain Levels for Software Artifacts)?

A) Code performance optimization B) Ensures software supply chain integrity C) Database security D) UI design verification

Answer: B

SLSA is a security framework to prevent software supply chain attacks. It ensures software integrity through build provenance attestation, artifact signing, and build environment isolation.


12. CI/CD Maturity Checklist

CI/CD Maturity Checklist:

Level 1 - Basic
[  ] Automated build pipeline
[  ] Automated test execution
[  ] Code review process

Level 2 - Standard
[  ] Deployment strategy (Rolling/Blue-Green)
[  ] Environment separation (dev/staging/prod)
[  ] Secrets management (Vault/OIDC)

Level 3 - Advanced
[  ] GitOps (ArgoCD/Flux)
[  ] Feature Flags
[  ] Canary deployment
[  ] PR Preview environments

Level 4 - Elite
[  ] Pipeline security (SLSA)
[  ] Auto-rollback
[  ] Monorepo optimization
[  ] Release automation

13. References

  1. DORA Metrics: dora.dev
  2. ArgoCD Documentation: argo-cd.readthedocs.io
  3. Flux Documentation: fluxcd.io
  4. Turborepo Documentation: turbo.build
  5. Nx Documentation: nx.dev
  6. LaunchDarkly Docs: docs.launchdarkly.com
  7. Unleash Documentation: docs.getunleash.io
  8. SLSA Framework: slsa.dev
  9. Sigstore / Cosign: sigstore.dev
  10. Semgrep: semgrep.dev
  11. Conventional Commits: conventionalcommits.org
  12. Git Cliff (Changelog): git-cliff.org
  13. GitHub Actions Docs: docs.github.com/actions
  14. Kubernetes Deployment Strategies: kubernetes.io/docs