프로덕션 전체 파이프라인
실제 프로덕션 환경의 전체 CI/CD 파이프라인 — 체크아웃부터 배포, 알림까지
실제 프로덕션 환경에서 사용할 수 있는 전체 파이프라인 예제입니다. 체크아웃, 린트, 테스트, 빌드, 배포, 알림까지 모든 단계를 포함합니다.
전체 코드
name: production-pipeline
# ─────────────────────────────────────────
# 트리거 설정
# ─────────────────────────────────────────
triggers:
# main/develop push 시 실행 (src/ 변경 시에만)
push:
branches: [main, develop]
paths: [src/**, package.json, Dockerfile]
# main 대상 Change Request 시 실행
change_request:
branches: [main]
# 매일 자정 스케줄 실행
schedule:
branch: main
cron: ["0 0 * * *"]
# 수동 실행 가능
workflow_dispatch:
# ─────────────────────────────────────────
# 전역 환경 변수
# ─────────────────────────────────────────
env:
APP_NAME: my-app
REGISTRY: "asia-northeast3-docker.pkg.dev"
PROJECT_ID: "${{ vars.GCP_PROJECT_ID }}"
jobs:
# ═══════════════════════════════════════
# Phase 1: Source
# ═══════════════════════════════════════
checkout:
phase: source
steps:
- name: checkout
uses: "collabops/checkout@v2"
with:
repo-url: "https://<collabops-host>/<workspace>/<repository>.git"
fetch-depth: "0" # 전체 히스토리 (버전 추출용)
# 버전 정보 + 메타데이터 수집 (build Job 내부에서 사용)
# → Step Output은 같은 Job 내에서만 참조 가능하므로,
# 메타데이터 수집 step을 build Job 안에 배치합니다.
# ═══════════════════════════════════════
# Phase 2: Dependencies
# ═══════════════════════════════════════
install:
phase: deps
needs: [checkout]
steps:
- name: npm-ci
image: node:18
run: |
cd /workspace/source
npm ci # 의존성 clean install
# ═══════════════════════════════════════
# Phase 3: Test (병렬 실행)
# ═══════════════════════════════════════
lint:
phase: test
needs: [install]
steps:
- name: eslint
image: node:18
run: |
cd /workspace/source
npm run lint
- name: typecheck
image: node:18
run: |
cd /workspace/source
npx tsc --noEmit
test:
phase: test
needs: [install] # lint와 병렬 실행
steps:
- name: unit-test
id: test-result
image: node:18
run: |
cd /workspace/source
npm test -- --coverage 2>&1 | tee /tmp/test.txt
# 커버리지 수치 추출
COVERAGE=$(grep 'Statements' /tmp/test.txt | grep -oP '\d+\.\d+' | head -1 || echo "N/A")
echo "coverage=${COVERAGE}%" >> $COLLABOPS_OUTPUT
env:
CI: "true"
# ═══════════════════════════════════════
# Phase 4: Build
# ═══════════════════════════════════════
# GCP 인증 (빌드/배포에 필요)
auth:
phase: build
needs: [checkout]
steps:
- name: gcloud-auth
uses: "collabops/gcloud-auth@v1"
with:
project-id: ${{ vars.GCP_PROJECT_ID }}
credentials: ${{ secrets.GCP_SA_KEY }}
- name: docker-auth
uses: "collabops/gcloud-docker-auth@v1"
with:
registry: ${{ env.REGISTRY }}
build:
phase: build
needs: [lint, test, auth] # 테스트 통과 + 인증 완료 후
services:
- docker # Docker 서비스 활성화
steps:
# 메타데이터 수집 (같은 Job 내에서 step output 참조)
- name: collect-meta
id: meta
image: node:18
run: |
cd /workspace/source
# package.json 버전
VERSION=$(node -p "require('./package.json').version")
echo "version=${VERSION}" >> $COLLABOPS_OUTPUT
# 짧은 SHA (이미지 태그용)
SHORT_SHA=$(echo "${{ collabops.sha }}" | cut -c1-7)
echo "short_sha=${SHORT_SHA}" >> $COLLABOPS_OUTPUT
# 빌드 타임스탬프
echo "build_time=$(date -u +%Y%m%dT%H%M%S)" >> $COLLABOPS_OUTPUT
echo "=== Build Metadata ==="
echo "Version: ${VERSION}"
echo "SHA: ${SHORT_SHA}"
echo "Branch: ${{ collabops.ref_name }}"
echo "Event: ${{ collabops.event_name }}"
- name: build-push
uses: "collabops/docker-build-push@v1"
with:
tags: |
${{ env.REGISTRY }}/${{ env.PROJECT_ID }}/docker/${{ env.APP_NAME }}:latest
${{ env.REGISTRY }}/${{ env.PROJECT_ID }}/docker/${{ env.APP_NAME }}:${{ steps.meta.outputs.version }}
${{ env.REGISTRY }}/${{ env.PROJECT_ID }}/docker/${{ env.APP_NAME }}:${{ steps.meta.outputs.short_sha }}
build-args: |
NODE_ENV=production
APP_VERSION=${{ steps.meta.outputs.version }}
BUILD_TIME=${{ steps.meta.outputs.build_time }}
# ═══════════════════════════════════════
# Phase 5: Deploy (main push만)
# ═══════════════════════════════════════
deploy:
phase: deploy
needs: [build]
# main 브랜치 push일 때만 프로덕션 배포
# CR이나 다른 브랜치에서는 빌드까지만 실행
if: "collabops.ref == 'refs/heads/main' && collabops.event_name == 'push'"
steps:
# GKE 클러스터 인증
- 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 }}
# 프로덕션 배포
- 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.APP_NAME }}:${SHORT_SHA}"
echo "Deploying ${IMAGE} to production..."
# Deployment 이미지 업데이트
kubectl set image deployment/${{ env.APP_NAME }} \
app=${IMAGE} \
-n production
# 롤아웃 완료 대기 (최대 5분)
kubectl rollout status deployment/${{ env.APP_NAME }} \
-n production \
--timeout=300s
echo "Deploy complete!"
# ═══════════════════════════════════════
# Phase 6: Notification (항상 실행)
# ═══════════════════════════════════════
notify:
needs: [deploy]
if: "always()" # 성공/실패 관계없이 항상 알림
steps:
- name: slack
uses: "collabops/slack-notify@v1"
with:
webhook-url: ${{ secrets.SLACK_WEBHOOK }}
title: "Production Deploy"
message: |
App: ${{ env.APP_NAME }}
Branch: ${{ collabops.ref_name }}
Commit: ${{ collabops.sha }}
Actor: ${{ collabops.actor }}
color: good실행 흐름
checkout
├── install (의존성 설치)
│ ├── lint (ESLint + TypeScript) ← 병렬
│ └── test (단위 테스트 + 커버리지) ← 병렬
└── auth (GCP + Docker 인증)
│
└── build (메타데이터 수집 → Docker 빌드 & 푸시)
│ ※ lint, test, auth 모두 완료 후 실행
└── deploy (GKE 배포, main push만)
└── notify (Slack 알림, 항상)트리거별 동작
| 트리거 | 실행 범위 |
|---|---|
push (main) | 전체 실행 (테스트 → 빌드 → 배포 → 알림) |
push (develop) | 테스트 → 빌드까지 (배포 건너뜀) |
change_request | 테스트 → 빌드까지 (배포 건너뜀) |
schedule | 테스트 → 빌드까지 (배포 건너뜀) |
workflow_dispatch | 테스트 → 빌드까지 (배포 건너뜀) |
deploy Job의 if 조건이 collabops.event_name == 'push'이므로, schedule이나 workflow_dispatch를 포함하여 push 외의 모든 트리거에서는 빌드까지만 실행되고 배포는 건너뜁니다.