Skip to content

Finders CD (Deploy to Prod) #19

Finders CD (Deploy to Prod)

Finders CD (Deploy to Prod) #19

Workflow file for this run

name: Finders CD (Deploy to Prod)
on:
push:
branches: [ "main" ]
env:
DOCKER_IMAGE: ${{ secrets.DOCKER_USERNAME }}/finders-api
CONTAINER_NAME: finders-api
permissions:
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build without Test
# CI์—์„œ ์ด๋ฏธ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ต๊ณผํ–ˆ๋‹ค๊ณ  ๋ฏฟ๊ณ , ๋ฐฐํฌ ์†๋„๋ฅผ ์œ„ํ•ด ํ…Œ์ŠคํŠธ๋Š” ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค.
run: ./gradlew build -x test
# 4. Docker Hub ๋กœ๊ทธ์ธ
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
# 5. Docker ์ด๋ฏธ์ง€ ๋นŒ๋“œ ๋ฐ ํ‘ธ์‹œ
- name: Build and Push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ env.DOCKER_IMAGE }}:latest
# 6. docker-compose.prod.yml ํŒŒ์ผ์„ ์„œ๋ฒ„๋กœ ์ „์†ก (SCP)
- name: Copy Docker Compose file to Server
uses: appleboy/scp-action@master
with:
host: ${{ secrets.GCE_HOST }}
username: ${{ secrets.GCE_USER }}
key: ${{ secrets.GCE_SSH_KEY }}
port: 22
source: "docker-compose.prod.yml"
target: "/home/${{ secrets.GCE_USER }}/app"
strip_components: 0
# 7. GCE ์„œ๋ฒ„์— ๋ฐฐํฌ ๋ฐ ๊ฒ€์ฆ (Health Check ์ถ”๊ฐ€๋จ)
- name: Deploy to GCE
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.GCE_HOST }}
username: ${{ secrets.GCE_USER }}
key: ${{ secrets.GCE_SSH_KEY }}
port: 22
script: |
# 1. ์•ฑ ๋””๋ ‰ํ† ๋ฆฌ ์ด๋™ ๋ฐ ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์„ค์ •
cd ~/app
echo "${{ secrets.ENV_PROD }}" > .env.prod
# 2. ์ตœ์‹  ์ด๋ฏธ์ง€ Pull
sudo docker compose -f docker-compose.prod.yml pull
# 3. ๊ธฐ์กด ์ปจํ…Œ์ด๋„ˆ ๋‚ด๋ฆฌ๊ณ  ์ƒˆ๋กœ ์‹œ์ž‘
sudo docker compose -f docker-compose.prod.yml down
sudo docker compose -f docker-compose.prod.yml up -d
# 4. ๋ฐฐํฌ ๊ฒ€์ฆ (Health Check) ๋กœ์ง
echo "๋ฐฐํฌ ํ›„ Health Check ์‹œ์ž‘..."
# ์ตœ๋Œ€ 60์ดˆ(5์ดˆ*12ํšŒ) ๋Œ€๊ธฐ
for i in {1..12}; do
RESPONSE=$(curl -s http://localhost:8080/api/actuator/health || true)
if [[ "$RESPONSE" == *"UP"* ]]; then
echo "โœ… ์„œ๋น„์Šค ์ •์ƒ ์‹คํ–‰ ํ™•์ธ! (Attempt $i)"
sudo docker image prune -f # ๋ถˆํ•„์š”ํ•œ ์ด๋ฏธ์ง€ ์ •๋ฆฌ
exit 0 # ์„ฑ๊ณต์œผ๋กœ ์ข…๋ฃŒ
fi
echo "์„œ๋น„์Šค ์‹œ์ž‘ ๋Œ€๊ธฐ ์ค‘... ($i/12)"
sleep 5
done
# 5. ์‹คํŒจ ์‹œ ์ฒ˜๋ฆฌ
echo "โŒ ๋ฐฐํฌ ์‹คํŒจ: ์„œ๋น„์Šค๊ฐ€ ์ œํ•œ ์‹œ๊ฐ„ ๋‚ด์— ๋œจ์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค."
sudo docker compose -f docker-compose.prod.yml logs --tail=100
exit 1 # GitHub Actions๋ฅผ '์‹คํŒจ(Red)'๋กœ ์ฒ˜๋ฆฌ