Merge pull request #138 from finpik/develop #57
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: Build & Deploy | |
| on: | |
| push: | |
| branches: [ "main" ] | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository }} # org/repo | |
| IMAGE_REPO: ghcr.io/${{ github.repository }} # ghcr.io/org/repo | |
| jobs: | |
| build-and-push: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write | |
| outputs: | |
| sha_short: ${{ steps.vars.outputs.sha_short }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Set up JDK 21 | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: temurin | |
| java-version: '21' | |
| - name: Login to GHCR (runner) | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract short SHA | |
| id: vars | |
| run: echo "sha_short=${GITHUB_SHA::7}" >> $GITHUB_OUTPUT | |
| - name: Build and push | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| push: true | |
| tags: | | |
| ${{ env.IMAGE_REPO }}:${{ steps.vars.outputs.sha_short }} | |
| ${{ env.IMAGE_REPO }}:latest | |
| deploy: | |
| needs: build-and-push | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: SSH & Deploy (stop-first) | |
| uses: appleboy/ssh-action@v1.2.0 | |
| with: | |
| host: ${{ secrets.SSH_HOST }} # EC2 퍼블릭 IP/도메인 | |
| username: ${{ secrets.SSH_USER }} # ec2-user | |
| key: ${{ secrets.SSH_KEY }} # pem 내용 | |
| script: | | |
| set -Eeuo pipefail | |
| IMAGE_REPO="${{ env.IMAGE_REPO }}" | |
| IMAGE_TAG="${{ needs.build-and-push.outputs.sha_short }}" | |
| APP_NAME="finpik-app" | |
| PORT="8080" | |
| ENV_FILE="/srv/app/.env" | |
| RESTART_POLICY="no" | |
| JAVA_OPTS="-Xms1g -Xmx1g -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:+ExitOnOutOfMemoryError" | |
| # (선택) GHCR private이면 EC2에서 로그인 필요: packages:read 권한 PAT를 GHCR_TOKEN/USERNAME로 넣어두기 | |
| if [ -n "${{ secrets.GHCR_TOKEN || '' }}" ]; then | |
| echo "${{ secrets.GHCR_TOKEN }}" | docker login ghcr.io -u "${{ secrets.GHCR_USERNAME }}" --password-stdin | |
| fi | |
| # .env 존재 확인(최초 1회 수동 생성 가정) | |
| if [ ! -f "${ENV_FILE}" ]; then | |
| echo "ERROR: ${ENV_FILE} not found"; exit 1 | |
| fi | |
| echo "== Pull image ==" | |
| docker pull "${IMAGE_REPO}:${IMAGE_TAG}" | |
| echo "== Stop & remove old ==" | |
| docker ps -a --filter "name=^/${APP_NAME}$" -q | xargs -r docker stop | |
| docker ps -a --filter "name=^/${APP_NAME}$" -q | xargs -r docker rm | |
| echo "== Run new container ==" | |
| docker run -d \ | |
| --name "${APP_NAME}" \ | |
| -p "${PORT}:8080" \ | |
| --env-file "${ENV_FILE}" \ | |
| -e SPRING_PROFILES_ACTIVE=prod \ | |
| -e JAVA_TOOL_OPTIONS="${JAVA_OPTS}" \ | |
| --restart "${RESTART_POLICY}" \ | |
| "${IMAGE_REPO}:${IMAGE_TAG}" | |
| echo "== Wait for health (up to 60s) ==" | |
| # 호스트에서 외부 헬스체크(컨테이너 안에 curl/wget 없어도 OK) | |
| command -v curl >/dev/null 2>&1 || sudo yum -y install -q curl || true | |
| ok="" | |
| for i in {1..12}; do | |
| if curl -fsS "http://127.0.0.1:${PORT}/actuator/health" >/dev/null; then | |
| ok="yes"; echo "healthy"; break | |
| fi | |
| sleep 5 | |
| done | |
| if [ -z "$ok" ]; then | |
| echo "!! app not healthy. recent logs:" | |
| docker logs --tail=200 "${APP_NAME}" || true | |
| exit 1 | |
| fi | |
| echo "== OK: ${APP_NAME} is healthy on :${PORT}" |