Skip to content

Merge pull request #63 from KB-JAKKU/refactor/audio #41

Merge pull request #63 from KB-JAKKU/refactor/audio

Merge pull request #63 from KB-JAKKU/refactor/audio #41

Workflow file for this run

name: Frontend Deploy
on:
push:
branches: [develop, feat/cicd]
paths:
- '**'
workflow_dispatch:
env:
IMAGE_NAME: ${{ secrets.DOCKERHUB_USERNAME }}/jakku-frontend
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
# (선택) CI 빌드 검증: 빠른 실패 확인용
- name: Install & Build (optional)
run: |
npm ci
npm run build
# Docker Hub 로그인
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# latest + sha 태그 동시 발행 (latest는 항상 발행)
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.IMAGE_NAME }}
tags: |
type=raw,value=latest
type=raw,value=sha-${{ github.sha }}
- name: Setup Buildx
uses: docker/setup-buildx-action@v3
- name: Build & Push
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# --- EC2: Blue/Green(=Canary)로 안전 교체 ---
- name: Deploy to EC2 (blue/green swap)
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.AWS_HOST }}
username: ${{ secrets.AWS_USERNAME }}
key: ${{ secrets.AWS_SSH_KEY }}
timeout: 5m
script: |
set -euo pipefail
IMAGE="${{ env.IMAGE_NAME }}:latest" # ✅ 항상 최신
MAIN_NAME="web"
CANARY_NAME="web_canary"
MAIN_PORT=5173
CANARY_PORT=15173
NET="jakku_net"
echo "[0/6] ensure docker network & attach backend"
docker network create "$NET" >/dev/null 2>&1 || true
# 백엔드 컨테이너 이름이 'jakku' 라는 전제 (이미 떠있다면 네트워크에 연결)
docker network connect "$NET" jakku >/dev/null 2>&1 || true
echo "[1/6] docker login & pull"
echo "${{ secrets.DOCKERHUB_TOKEN }}" | docker login -u "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin
docker pull "$IMAGE"
echo "[2/6] start canary on :${CANARY_PORT}"
docker rm -f "$CANARY_NAME" >/dev/null 2>&1 || true
docker run -d --name "$CANARY_NAME" --restart "no" \
--network "$NET" \
-p ${CANARY_PORT}:80 \
"$IMAGE"
echo "[3/6] health check canary(index.html)"
ok=0
for i in $(seq 1 30); do
if curl -fsS "http://localhost:${CANARY_PORT}/index.html" >/dev/null 2>&1; then ok=1; break; fi
sleep 1
done
if [ "$ok" -ne 1 ]; then
echo "X Canary failed. Keep current main."
docker logs "$CANARY_NAME" || true
docker rm -f "$CANARY_NAME" || true
exit 1
fi
echo "[4/6] swap to main(:${MAIN_PORT})"
docker rm -f "$MAIN_NAME" >/dev/null 2>&1 || true
# 포트 5173이 다른 프로세스가 잡고 있는지 보호
if ss -ltn | awk '{print $4}' | grep -q ":${MAIN_PORT}$"; then
echo "X Port ${MAIN_PORT} is occupied by non-docker. Abort."
docker rm -f "$CANARY_NAME" || true
exit 1
fi
docker run -d --name "$MAIN_NAME" --restart unless-stopped \
--network "$NET" \
-p ${MAIN_PORT}:80 \
"$IMAGE"
echo "[5/6] cleanup canary"
docker rm -f "$CANARY_NAME" >/dev/null 2>&1 || true
echo "[6/6] show containers"
docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}"