CollabOps

GCP Docker Deploy

A pipeline that builds/pushes images to GCP Artifact Registry and deploys to GKE

A pipeline that builds Docker images and deploys them to a GKE cluster in a GCP environment.

Prerequisites

The following secrets and vars must be registered in advance:

TypeKeyDescription
SecretGCP_SA_KEYGCP service account key JSON
VarGCP_PROJECT_IDGCP project ID
VarGKE_CLUSTERGKE cluster name
VarGKE_REGIONGKE cluster region

Full Code

name: gcp-deploy

# Runs only on main branch push + when src/ changes
triggers:
  push:
    branches: [main]
    paths: [src/**, Dockerfile, package.json]

# Global environment variables — used across all Jobs
env:
  PROJECT_ID: "${{ vars.GCP_PROJECT_ID }}"
  REGISTRY: "asia-northeast3-docker.pkg.dev"
  IMAGE_NAME: "my-app"

jobs:
  # ─────────────────────────────────────────
  # 1. Source code checkout
  # ─────────────────────────────────────────
  checkout:
    phase: source
    steps:
      - name: checkout
        uses: "collabops/checkout@v2"
        with:
          repo-url: "https://<collabops-host>/<workspace>/<repository>.git"

  # ─────────────────────────────────────────
  # 2. GCP authentication + Docker Registry authentication
  # ─────────────────────────────────────────
  auth:
    phase: source
    needs: [checkout]
    steps:
      # GCP service account authentication
      - name: gcloud-auth
        uses: "collabops/gcloud-auth@v1"
        with:
          project-id: ${{ vars.GCP_PROJECT_ID }}
          credentials: ${{ secrets.GCP_SA_KEY }}

      # Artifact Registry Docker authentication
      - name: docker-auth
        uses: "collabops/gcloud-docker-auth@v1"
        with:
          registry: asia-northeast3-docker.pkg.dev

  # ─────────────────────────────────────────
  # 3. Docker image build and push
  # ─────────────────────────────────────────
  build:
    phase: build
    needs: [checkout, auth]      # Requires checkout + authentication
    steps:
      # Extract version info (step output referenced within the same Job)
      - name: extract-version
        id: version
        image: node:18
        run: |
          cd /workspace/source

          # Extract version from package.json
          APP_VERSION=$(node -p "require('./package.json').version")
          echo "app_version=${APP_VERSION}" >> $COLLABOPS_OUTPUT

          # Generate short SHA (for image tag)
          SHORT_SHA=$(echo "${{ collabops.sha }}" | cut -c1-7)
          echo "short_sha=${SHORT_SHA}" >> $COLLABOPS_OUTPUT

          echo "Version: ${APP_VERSION}, SHA: ${SHORT_SHA}"

      - name: build-push
        uses: "collabops/docker-build-push@v1"
        with:
          # Multi-tag: latest + version + SHA
          tags: |
            ${{ env.REGISTRY }}/${{ env.PROJECT_ID }}/docker/${{ env.IMAGE_NAME }}:latest
            ${{ env.REGISTRY }}/${{ env.PROJECT_ID }}/docker/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.app_version }}
            ${{ env.REGISTRY }}/${{ env.PROJECT_ID }}/docker/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.short_sha }}
          build-args: |
            NODE_ENV=production

  # ─────────────────────────────────────────
  # 4. GKE deployment
  # ─────────────────────────────────────────
  deploy:
    phase: deploy
    needs: [build]
    # Deploy only on main branch push (CRs only build)
    if: "collabops.ref == 'refs/heads/main' && collabops.event_name == 'push'"
    steps:
      # GKE cluster authentication
      - name: gke-setup
        uses: "collabops/gcloud-setup@v1"
        with:
          project-id: ${{ vars.GCP_PROJECT_ID }}
          cluster-name: ${{ vars.GKE_CLUSTER }}
          cluster-location: ${{ vars.GKE_REGION }}

      # Update image via kubectl
      - name: rollout
        image: google/cloud-sdk:527.0.0-slim
        run: |
          SHORT_SHA=$(echo "${{ collabops.sha }}" | cut -c1-7)
          IMAGE="${{ env.REGISTRY }}/${{ env.PROJECT_ID }}/docker/${{ env.IMAGE_NAME }}:${SHORT_SHA}"
          kubectl set image deployment/${{ env.IMAGE_NAME }} \
            app=${IMAGE} \
            -n production
          kubectl rollout status deployment/${{ env.IMAGE_NAME }} \
            -n production \
            --timeout=300s

  # ─────────────────────────────────────────
  # 5. Deployment completion notification
  # ─────────────────────────────────────────
  notify:
    needs: [deploy]
    if: "always()"               # Notify regardless of deploy success/failure
    steps:
      - name: slack-notify
        uses: "collabops/slack-notify@v1"
        with:
          webhook-url: ${{ secrets.SLACK_WEBHOOK }}
          message: "GKE deploy complete: ${{ env.IMAGE_NAME }} (${{ collabops.sha }})"
          title: "Deploy to GKE"
          color: good

Execution Flow

checkout
  └── auth (GCP authentication)
        └── build (version extraction → Docker build & push)
              └── deploy (GKE deployment, main push only)
                    └── notify (Slack notification, always)

Table of Contents