Skip to content

WF-001: CI/CD Pipeline

DOCUMENT CONTROL

FieldValue
WF IDWF-001
Version1.0
StatusActive

Overview

Set up continuous deployment from a Git repository to Cloud Run. Every push to your main branch automatically builds and deploys your application.

Workflow Diagram

┌─────────────────────────────────────────────────────────────────────┐
│                         CI/CD PIPELINE                              │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  ┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────────────┐  │
│  │  Code   │───▶│  Cloud  │───▶│Artifact │───▶│   Cloud Run     │  │
│  │  Push   │    │  Build  │    │Registry │    │   Deployment    │  │
│  └─────────┘    └─────────┘    └─────────┘    └─────────────────┘  │
│       │              │              │                  │            │
│       ▼              ▼              ▼                  ▼            │
│  [Trigger]     [Build Image]  [Store Image]    [Deploy & Route]    │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Phase 1: Connect Repository

  1. Go to Cloud Run Console
  2. Click Create Service
  3. Select Continuously deploy from a repository
  4. Click Set up with Cloud Build
  5. Authenticate with GitHub/GitLab
  6. Select repository and branch

Option B: gcloud CLI

bash
# Enable required APIs
gcloud services enable \
  run.googleapis.com \
  cloudbuild.googleapis.com \
  artifactregistry.googleapis.com

# Create Artifact Registry repository
gcloud artifacts repositories create cloud-run-repo \
  --repository-format docker \
  --location us-central1

# Connect repository (opens browser)
gcloud beta builds repositories create my-repo \
  --remote-uri https://github.com/YOUR_USER/YOUR_REPO \
  --region us-central1

Phase 2: Configure Build Trigger

Create cloudbuild.yaml

yaml
# cloudbuild.yaml
steps:
  # Build the container
  - name: 'gcr.io/cloud-builders/docker'
    args:
      - 'build'
      - '-t'
      - 'us-central1-docker.pkg.dev/$PROJECT_ID/cloud-run-repo/my-service:$COMMIT_SHA'
      - '-t'
      - 'us-central1-docker.pkg.dev/$PROJECT_ID/cloud-run-repo/my-service:latest'
      - '.'

  # Push to Artifact Registry
  - name: 'gcr.io/cloud-builders/docker'
    args:
      - 'push'
      - '--all-tags'
      - 'us-central1-docker.pkg.dev/$PROJECT_ID/cloud-run-repo/my-service'

  # Deploy to Cloud Run
  - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    entrypoint: gcloud
    args:
      - 'run'
      - 'deploy'
      - 'my-service'
      - '--image'
      - 'us-central1-docker.pkg.dev/$PROJECT_ID/cloud-run-repo/my-service:$COMMIT_SHA'
      - '--region'
      - 'us-central1'

images:
  - 'us-central1-docker.pkg.dev/$PROJECT_ID/cloud-run-repo/my-service:$COMMIT_SHA'
  - 'us-central1-docker.pkg.dev/$PROJECT_ID/cloud-run-repo/my-service:latest'

options:
  logging: CLOUD_LOGGING_ONLY

Create Build Trigger

bash
gcloud builds triggers create github \
  --name my-service-trigger \
  --repo-name YOUR_REPO \
  --repo-owner YOUR_USER \
  --branch-pattern "^main$" \
  --build-config cloudbuild.yaml \
  --region us-central1

Phase 3: Set Up Staging Environment

yaml
# cloudbuild.yaml with staging
steps:
  - name: 'gcr.io/cloud-builders/docker'
    args: ['build', '-t', '$_IMAGE_TAG', '.']

  - name: 'gcr.io/cloud-builders/docker'
    args: ['push', '$_IMAGE_TAG']

  # Deploy to staging first
  - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    entrypoint: gcloud
    args:
      - 'run'
      - 'deploy'
      - 'my-service-staging'
      - '--image=$_IMAGE_TAG'
      - '--region=us-central1'
      - '--tag=staging'
      - '--no-traffic'

  # Run integration tests
  - name: 'gcr.io/cloud-builders/curl'
    script: |
      STAGING_URL=$(gcloud run services describe my-service-staging \
        --region us-central1 --format 'value(status.url)')
      curl -f "${STAGING_URL}" || exit 1

  # Promote to production
  - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    entrypoint: gcloud
    args:
      - 'run'
      - 'deploy'
      - 'my-service'
      - '--image=$_IMAGE_TAG'
      - '--region=us-central1'

substitutions:
  _IMAGE_TAG: 'us-central1-docker.pkg.dev/$PROJECT_ID/cloud-run-repo/my-service:$COMMIT_SHA'

Phase 4: Configure Rollback

Automatic Rollback on Failure

yaml
# In cloudbuild.yaml, add health check
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
  entrypoint: bash
  args:
    - '-c'
    - |
      SERVICE_URL=$(gcloud run services describe my-service \
        --region us-central1 --format 'value(status.url)')

      # Wait for service to be ready
      sleep 30

      # Health check
      if ! curl -sf "${SERVICE_URL}/health"; then
        echo "Health check failed, rolling back..."
        PREV_REV=$(gcloud run revisions list --service my-service \
          --region us-central1 --format 'value(metadata.name)' | sed -n '2p')
        gcloud run services update-traffic my-service \
          --region us-central1 --to-revisions ${PREV_REV}=100
        exit 1
      fi

Manual Rollback

bash
# List recent revisions
gcloud run revisions list --service my-service --region us-central1

# Rollback to specific revision
gcloud run services update-traffic my-service \
  --region us-central1 \
  --to-revisions my-service-00005-abc=100

Success Criteria

  • [ ] Push to main triggers automatic build
  • [ ] Build completes in < 5 minutes
  • [ ] New revision deployed with 100% traffic
  • [ ] Health check passes post-deployment
  • [ ] Previous revision retained for rollback
  • [ ] Build notifications configured (Slack/email)

Monitoring Pipeline

bash
# View recent builds
gcloud builds list --limit 5

# Watch build in progress
gcloud builds log --stream $(gcloud builds list --ongoing --format 'value(id)' | head -1)

# View deployment history
gcloud run revisions list --service my-service --region us-central1