클라우드 Prod temp BE CD 스크립트 작성 - 100-hours-a-week/16-Hot6-wiki GitHub Wiki

아래는 작성하신 GitHub Actions 워크플로우(Backend CI & Dev CD)를 역할별로 정리하고, 가독성과 설명 중심으로 재구성한 것입니다. 워크플로우는 prod-temp 브랜치에서 push될 때 실행되며, 다음과 같은 두 가지 주요 작업으로 나뉩니다:

alt text


🔧 Workflow: Backend CI & Dev CD

트리거

on:
  push:
    branches:
      - prod-temp

Job 1: Build Backend

jobs:
  build:
    name: Build Backend
    runs-on: ubuntu-latest
    environment: ${{ github.ref_name == 'main' && 'main' || 'prod-temp' }}

🔨 Steps

  1. 레포지토리 체크아웃

    - uses: actions/checkout@v3
  2. JDK 21 설치

    - uses: actions/setup-java@v3
      with:
        distribution: 'temurin'
        java-version: '21'
  3. Gradle 실행 권한 부여

    - run: chmod +x ./gradlew
  4. Jar 빌드 (테스트 제외)

    - run: ./gradlew bootJar -x test
  5. 빌드된 JAR 아티팩트 업로드

    - uses: actions/upload-artifact@v4
      with:
        name: backend-jar
        path: build/libs/*.jar

Job 2: Deploy to Dev Server (via SSH)

  deploy:
    name: Deploy to Dev via SSH
    needs: build
    runs-on: ubuntu-latest
    environment: ${{ github.ref_name == 'main' && 'main' || 'prod' }}
    env:
      DEPLOY_ENV: ${{ github.ref_name == 'main' && 'prod' || 'prod-temp' }}
      SECRET_LABELS: ${{ github.ref_name == 'main' && 'backend_shared backend_prod' || 'backend_shared backend_dev' }}

비밀 설정 및 배포

  1. JAR 다운로드 및 이름 변경

    - uses: actions/download-artifact@v4
      with:
        name: backend-jar
        path: .
    - run: |
        JAR_FILE=$(find . -name "*.jar" | head -n 1)
        cp "$JAR_FILE" backend.jar
  2. GCP 인증

    - uses: google-github-actions/auth@v2
      with:
        credentials_json: '${{ secrets.GCP_SA_KEY }}'
  3. secrets.properties 파일 생성

    - run: |
        mkdir -p ./secrets
        touch ./secrets/secrets.properties
        for LABEL in $SECRET_LABELS; do
          gcloud secrets list --filter="labels.env=$LABEL" --format="value(name)" | while read SECRET_NAME; do
            SECRET_VALUE=$(gcloud secrets versions access latest --secret="$SECRET_NAME")
            IFS='-' read -r SERVICE KEY ENV <<< "$SECRET_NAME"
            echo "${KEY}=${SECRET_VALUE}" >> ./secrets/secrets.properties
          done
        done
  4. SSH Jump Server 설정

    - run: |
        mkdir -p ~/.ssh
        echo "${{ secrets.JUMP_SSH_KEY }}" > ~/.ssh/jump_key
        chmod 600 ~/.ssh/jump_key
        echo "${{ secrets.SSH_KEY }}" > ~/.ssh/dev_key
        chmod 600 ~/.ssh/dev_key
        cat <<EOF > ~/.ssh/config
        Host backend-server
            HostName ${{ secrets.SSH_HOST }}
            User ubuntu
            IdentityFile ~/.ssh/dev_key
            ProxyJump jump-server
            StrictHostKeyChecking no
            UserKnownHostsFile /dev/null
    
        Host jump-server
            HostName ${{ secrets.JUMP_SSH_HOST }}
            User ubuntu
            IdentityFile ~/.ssh/jump_key
            StrictHostKeyChecking no
            UserKnownHostsFile /dev/null
        EOF
  5. JAR 및 시크릿 파일 서버로 전송

    - run: |
        ssh -F ~/.ssh/config backend-server 'mkdir -p ~/backend'
        scp -F ~/.ssh/config backend.jar backend-server:/home/ubuntu/backend/backend.jar
        scp -F ~/.ssh/config ./secrets/secrets.properties backend-server:/home/ubuntu/backend/secrets.properties
  6. 백엔드 서버 재시작

    - run: |
        ssh -F ~/.ssh/config backend-server <<'EOF'
          set -eux
          cd ~/backend
    
          echo "▶️ [1] 실행 중인 애플리케이션 중지"
          PID=$(pgrep -f backend || true)
          if [ -n "$PID" ]; then
            kill "$PID"
            sleep 5
          else
            echo "실행 중인 프로세스 없음"
          fi
    
          nohup java -jar backend.jar \
            --spring.profiles.active=dev \
            --spring.config.additional-location=file:/home/ubuntu/backend/secrets.properties \
            > backend.log 2>&1 &
    
          sleep 5
          NEW_PID=$(pgrep -f backend || true)
          if [ -n "$NEW_PID" ]; then
            echo "✅ 정상 기동 완료 (PID: $NEW_PID)"
          else
            echo "❗ 기동 실패"
            exit 1
          fi
        EOF

요약

  • 브랜치: prod-temp 푸시 시 실행
  • 빌드: JDK 21 환경에서 Gradle 빌드
  • 시크릿 자동 구성: GCP Secret Manager에서 라벨 기반으로 추출
  • Jump 서버 경유 SSH 배포: backend-server로 JAR 전송 및 재기동
  • 유연한 환경 변수: DEPLOY_ENVSECRET_LABELS는 브랜치에 따라 자동 분기 처리

필요하다면 --spring.profiles.activeDEPLOY_ENV와 연동되게 바꿔줄 수도 있습니다. 예: --spring.profiles.active=${DEPLOY_ENV}

이 워크플로우를 프로덕션에도 확장하시겠어요?

alt text alt text

⚠️ **GitHub.com Fallback** ⚠️