Merge pull request #63 from KB-JAKKU/refactor/audio #41
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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}}" |