Skip to content

Merge pull request #56 from codeit-2team/chore/54 #3

Merge pull request #56 from codeit-2team/chore/54

Merge pull request #56 from codeit-2team/chore/54 #3

Workflow file for this run

name: Deploy to OCI
on:
push:
branches:
- develop
# GitHub Actions 탭에서 수동으로 실행 가능
workflow_dispatch:
# 워크플로우 전체에서 사용할 환경 변수 설정
env:
# 사용할 컨테이너 레지스트리(GitHub Container Registry)
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository_owner }}/global-nomad
jobs:
# Job 1: Docker 이미지 빌드를 빌드하고 GHCR에 푸시
build:
name: Build and Push Docker Image
runs-on: ubuntu-latest
# 해당 Job이 사용할 권한 설정
permissions:
contents: read
# GHCR에 이미지를 쓰기(푸시) 위한 권한
packages: write
# Job의 결과를 다른 Job에서 사용할 수 있도록 출력 설정
outputs:
# 정확한 이미지 태그 전달 (SHA 기반) - 배포할 정확한 이미지 주소, 버전 확인을 위한 커밋 해시
image-url: ${{ steps.image.outputs.image-url }}
git-sha: ${{ steps.vars.outputs.sha-short }}
steps:
# 코드 체크아웃
- name: Checkout code
uses: actions/checkout@v4
# Docker Buildx 설정
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# GHCR 로그인
# - secrets.GITHUB_TOKEN: 워크플로우 실행 시 GitHub이 자동으로 생성해주는 임시 토큰
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# 빌드에 사용할 변수 생성 (짧은 커밋 해시, 빌드 날짜)
- name: Generate build vars
id: vars
run: |
echo "sha-short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
echo "build-date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
# 도커 이미지 빌드 및 푸시 (불변 태그 사용)
- name: Build and push Docker image
id: build
uses: docker/build-push-action@v5
with:
# 현재 디렉토리를 빌드 컨텍스트로 사용
context: .
# 빌드 후 레지스트리에 푸시
push: true
# 이미지에 여러 태그를 부여
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:develop
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:develop-${{ steps.vars.outputs.sha-short }}
# 이미지에 메타 데이터 라벨 추가
labels: |
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.created=${{ steps.vars.outputs.build-date }}
# GitHub Actions 캐시를 사용하여 빌드 속도 향상
cache-from: type=gha
cache-to: type=gha,mode=max
# 빌드할 플랫폼 지정
platforms: linux/amd64
# Job으로 전달할 정확한 이미지 URL 출력으로 설정
- name: Set image output
id: image
run: |
echo "image-url=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:develop-${{ steps.vars.outputs.sha-short }}" >> $GITHUB_OUTPUT
# Job 2: OCI 서버에 배포
deploy:
name: Deploy to OCI Server
runs-on: ubuntu-latest
# 빌드 Job이 성공해야만 실행
needs: build
steps:
- name: Setup SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.OCI_SSH_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -t rsa ${{ secrets.OCI_HOST }} >> ~/.ssh/known_hosts
# 서버에 배포 스크립트 실행
- name: Deploy to server
env:
IMAGE_URL: ${{ needs.build.outputs.image-url }}
GIT_SHA: ${{ needs.build.outputs.git-sha }}
run: |
ssh -i ~/.ssh/id_rsa ${{ secrets.OCI_USERNAME }}@${{ secrets.OCI_HOST }} << 'ENDSSH'
set -e
echo "📦 Starting deployment..."
echo "🏷️ Image: ${IMAGE_URL}"
echo "🔖 Version: ${GIT_SHA}"
# 프로젝트 디렉토리로 이동
cd ~/projects/GlobalNomad
# 최신 코드 가져오기
echo "🔄 Pulling latest code..."
git pull origin develop
# GHCR 로그인 (PAT 사용)
echo "🔐 Logging in to GHCR..."
echo "${{ secrets.GHCR_PAT }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
# 현재 실행 중인 이미지 태그 저장 (롤백용)
echo "💾 Saving current version..."
CURRENT_IMAGE=$(docker compose ps -q nextjs | xargs docker inspect -f '{{.Config.Image}}' 2>/dev/null || echo "none")
echo "Current: $CURRENT_IMAGE" > ~/deployments/previous-version.txt
# 기존 컨테이너 중지
echo "🛑 Stopping existing containers..."
docker compose down || true
# 최신 이미지 pull (정확한 버전)
echo "📥 Pulling image: ${IMAGE_URL}"
docker pull ${IMAGE_URL}
# 환경 변수로 이미지 지정하여 실행
echo "🚀 Starting containers..."
export NEXTJS_IMAGE="${IMAGE_URL}"
docker compose up -d
# 헬스 체크
echo "❤️ Health check..."
for i in {1..30}; do
if curl -f http://localhost:3000 > /dev/null 2>&1; then
echo "✅ Service is healthy!"
break
fi
echo "⏳ Waiting for service... ($i/30)"
sleep 2
done
# 최종 확인
if ! curl -f http://localhost:3000 > /dev/null 2>&1; then
echo "❌ Service health check failed after 60 seconds!"
docker compose logs --tail 50 nextjs
exit 1
fi
# 배포 정보 기록
echo "📝 Recording deployment..."
mkdir -p ~/deployments
echo "${IMAGE_URL}" > ~/deployments/current-version.txt
echo "$(date -u +'%Y-%m-%d %H:%M:%S UTC') - ${GIT_SHA}" >> ~/deployments/history.log
# 오래된 이미지 정리 (최근 3개만 유지)
echo "🧹 Cleaning up old images..."
docker images | grep global-nomad | tail -n +4 | awk '{print $3}' | xargs -r docker rmi || true
echo "✅ Deployment completed successfully!"
echo "📊 Deployed version: ${GIT_SHA}"
ENDSSH
# 배포 결과 알림 (Slack, Discord 등 추가 가능)
- name: Notify deployment status
if: always()
run: |
if [ ${{ job.status }} == 'success' ]; then
echo "✅ 배포 성공!"
echo "🏷️ Image: ${{ needs.build.outputs.image-url }}"
echo "🔖 Version: ${{ needs.build.outputs.git-sha }}"
else
echo "❌ 배포 실패!"
fi