-
Notifications
You must be signed in to change notification settings - Fork 2
194 lines (165 loc) · 7.94 KB
/
deploy.yml
File metadata and controls
194 lines (165 loc) · 7.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
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:
# metadata-action이 생성한 고유하고 안정적인 태그를 전달
image_tag: ${{ steps.meta.outputs.version }}
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 }}
# docker/metadata-action을 사용하여 태그와 라벨을 자동으로 생성
- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha,prefix=develop-,format=short
# 도커 이미지 빌드 및 푸시 (자동 생성된 불변 태그 사용)
- name: Build and push Docker image
id: build
uses: docker/build-push-action@v5
with:
# 현재 디렉토리를 빌드 컨텍스트로 사용
context: .
# 빌드 후 레지스트리에 푸시
push: true
# metadata-action이 생성한 tags와 labels를 직접 사용
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# GitHub Actions 캐시를 사용하여 빌드 속도 향상
cache-from: type=gha
cache-to: type=gha,mode=max
# 빌드할 플랫폼 지정
platforms: linux/amd64
# 모든 환경 변수를 하나의 build-arg로 전달
build-args: |
BUILD_ENV_VARS=${{ format('NEXT_PUBLIC_API_URL={0} NEXT_PUBLIC_API_SERVER_URL={1} NEXT_PUBLIC_KAKAO_CLIENT_ID={2} NEXT_PUBLIC_KAKAO_APP_JS_KEY={3} NEXT_PUBLIC_SITE_URL={4} NEXT_PUBLIC_KAKAO_SIGNIN_REDIRECT_URL={5} NEXT_PUBLIC_KAKAO_SIGNUP_REDIRECT_URL={6}', secrets.NEXT_PUBLIC_API_URL, secrets.NEXT_PUBLIC_API_SERVER_URL, secrets.NEXT_PUBLIC_KAKAO_CLIENT_ID, secrets.NEXT_PUBLIC_KAKAO_APP_JS_KEY, secrets.NEXT_PUBLIC_SITE_URL, secrets.NEXT_PUBLIC_KAKAO_SIGNIN_REDIRECT_URL, secrets.NEXT_PUBLIC_KAKAO_SIGNUP_REDIRECT_URL) }}
# 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
run: |
ssh -i ~/.ssh/id_rsa ${{ secrets.OCI_USERNAME }}@${{ secrets.OCI_HOST }} << 'ENDSSH'
set -e
export IMAGE_TAG="${{ needs.build.outputs.image_tag }}"
export IMAGE_URL="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${IMAGE_TAG}"
echo "📦 Starting deployment..."
echo "🏷️ Deploying image: ${IMAGE_URL}"
echo "🔖 Version: ${IMAGE_TAG}"
# 프로젝트 디렉토리로 이동
cd ~/projects/GlobalNomad
# .env 파일 생성
echo "📝 Creating .env file from secrets..."
# 기존 .env 파일이 있다면 삭제하여 최신 상태 유지
rm -f .env
touch .env
echo "NEXT_PUBLIC_API_URL=${{ secrets.NEXT_PUBLIC_API_URL }}" >> .env
echo "NEXT_PUBLIC_API_SERVER_URL=${{ secrets.NEXT_PUBLIC_API_SERVER_URL }}" >> .env
echo "NEXT_PUBLIC_KAKAO_CLIENT_ID=${{ secrets.NEXT_PUBLIC_KAKAO_CLIENT_ID }}" >> .env
echo "NEXT_PUBLIC_KAKAO_APP_JS_KEY=${{ secrets.NEXT_PUBLIC_KAKAO_APP_JS_KEY }}" >> .env
echo "NEXT_PUBLIC_SITE_URL=${{ secrets.NEXT_PUBLIC_SITE_URL }}" >> .env
echo "NEXT_PUBLIC_KAKAO_SIGNIN_REDIRECT_URL=${{ secrets.NEXT_PUBLIC_KAKAO_SIGNIN_REDIRECT_URL }}" >> .env
echo "NEXT_PUBLIC_KAKAO_SIGNUP_REDIRECT_URL=${{ secrets.NEXT_PUBLIC_KAKAO_SIGNUP_REDIRECT_URL }}" >> .env
# 최신 코드 가져오기
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 > /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 > /dev/null 2>&1; then
echo "❌ Service health check failed after 60 seconds!"
docker compose logs --tail 50 nextjs
docker compose logs --tail 50 nginx
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') - ${IMAGE_TAG}" >> ~/deployments/history.log
# 오래된 이미지 정리 (최근 3개만 유지)
echo "🧹 Cleaning up old images..."
docker images --filter=reference='*/*global-nomad' --format '{{.ID}}' | tail -n +4 | xargs -r docker rmi || true
echo "✅ Deployment completed successfully!"
echo "📊 Deployed version: ${IMAGE_TAG}"
ENDSSH
# 배포 결과 알림
- name: Notify deployment status
if: always()
run: |
if [ ${{ job.status }} == 'success' ]; then
echo "✅ 배포 성공!"
echo "🏷️ Image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.build.outputs.image_tag }}"
echo "🔖 Version: ${{ needs.build.outputs.image_tag }}"
else
echo "❌ 배포 실패!"
fi