[PROD] Build Gradle and Deploy #17
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: "[PROD] Build Gradle and Deploy" | |
| on: | |
| release: | |
| types: [published] | |
| workflow_dispatch: | |
| inputs: | |
| tag_name: | |
| description: 'Docker Tag Name (e.g., v1.0.0)' | |
| required: true | |
| default: 'latest' | |
| jobs: | |
| # --- Job 1: 빌드 및 이미지 푸시 (쓰기 권한) --- | |
| build-and-push: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write | |
| outputs: | |
| image_tag: ${{ steps.image_meta.outputs.image_tag }} | |
| steps: | |
| - name: Checkout the code | |
| uses: actions/checkout@v4 | |
| with: | |
| token: ${{ secrets.SUBMODULE_ACCESS_TOKEN }} | |
| submodules: true | |
| # --- Java, Gradle 설정 --- | |
| - name: Set up JDK 17 | |
| uses: actions/setup-java@v4 | |
| with: | |
| java-version: '17' | |
| distribution: 'temurin' | |
| - name: Setup Gradle | |
| uses: gradle/actions/setup-gradle@v3 | |
| - name: Grant execute permission for Gradle wrapper | |
| run: chmod +x ./gradlew | |
| - name: Build with Gradle | |
| run: ./gradlew bootJar | |
| # --- Docker 설정 --- | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| with: | |
| platforms: linux/arm64 | |
| - name: Log in to GitHub Container Registry (GHCR) | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| # --- 이미지 메타데이터 정의 (Prod용 이미지 이름) --- | |
| - name: Define image name and tag | |
| id: image_meta | |
| run: | | |
| OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') | |
| # Trigger가 Release인 경우: Release의 Tag Name (예: v1.0.0) 사용 | |
| if [ "${{ github.event_name }}" == "release" ]; then | |
| IMAGE_TAG="${{ github.ref_name }}" | |
| # Trigger가 수동(workflow_dispatch)인 경우: 입력받은 tag_name 사용 | |
| else | |
| IMAGE_TAG="${{ inputs.tag_name }}" | |
| fi | |
| echo "Docker Image Tag: $IMAGE_TAG" | |
| echo "image_name=ghcr.io/${OWNER_LOWERCASE}/solid-connection-server" >> $GITHUB_OUTPUT | |
| echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT | |
| # --- Docker 빌드 및 푸시 --- | |
| - name: Build, push, and cache Docker image | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| platforms: linux/arm64 | |
| push: true | |
| tags: ${{ format('{0}:{1}', steps.image_meta.outputs.image_name, steps.image_meta.outputs.image_tag) }} | |
| cache-from: type=registry,ref=${{ steps.image_meta.outputs.image_name }}:buildcache | |
| cache-to: type=registry,ref=${{ steps.image_meta.outputs.image_name }}:buildcache,mode=max | |
| # --- 이미지 정리 --- | |
| - name: Clean up old image versions from GHCR | |
| uses: snok/container-retention-policy@v2 | |
| with: | |
| token: ${{ secrets.PACKAGE_DELETE_TOKEN }} | |
| image-names: solid-connection-server | |
| delete-untagged: true | |
| keep-n-tags: 5 | |
| account-type: org | |
| org-name: ${{ github.repository_owner }} | |
| cut-off: '7 days ago UTC' | |
| # --- Job 2: 배포 (읽기 권한) --- | |
| deploy: | |
| needs: build-and-push | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: read | |
| steps: | |
| # 설정 파일 전송을 위해 코드 체크아웃 (서브모듈 불필요) | |
| - name: Checkout config files | |
| uses: actions/checkout@v4 | |
| with: | |
| sparse-checkout: | | |
| docker-compose.prod.yml | |
| docs/infra-config | |
| sparse-checkout-cone-mode: false | |
| # --- 설정 파일 전송 --- | |
| - name: Copy config files to remote | |
| run: | | |
| echo "${{ secrets.PRIVATE_KEY }}" > deploy_key.pem | |
| chmod 600 deploy_key.pem | |
| scp -i deploy_key.pem \ | |
| -o StrictHostKeyChecking=no \ | |
| ./docker-compose.prod.yml \ | |
| ./docs/infra-config/config.alloy \ | |
| ./docs/infra-config/nginx.prod.conf \ | |
| ${{ secrets.USERNAME }}@${{ secrets.HOST }}:/home/${{ secrets.USERNAME }}/solid-connection-prod/ | |
| # --- 서버에서 Docker Pull 및 재시작 --- | |
| - name: Run docker compose and apply nginx config | |
| run: | | |
| ssh -i deploy_key.pem \ | |
| -o StrictHostKeyChecking=no \ | |
| ${{ secrets.USERNAME }}@${{ secrets.HOST }} \ | |
| ' | |
| set -e | |
| # 1. 변수 설정 (이전 Job의 Output 사용) | |
| export OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr "[:upper:]" "[:lower:]") | |
| export IMAGE_TAG_ONLY="${{ needs.build-and-push.outputs.image_tag }}" | |
| export FULL_IMAGE_NAME="ghcr.io/${OWNER_LOWERCASE}/solid-connection-server:${IMAGE_TAG_ONLY}" | |
| # 2. 서버가 GHCR에 로그인 (GITHUB_TOKEN 사용) | |
| # App Token 대신 현재 워크플로우의 임시 토큰을 사용합니다. | |
| echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin | |
| # 3. docker pull | |
| echo "Pulling new image: $FULL_IMAGE_NAME" | |
| docker pull $FULL_IMAGE_NAME | |
| # 4. alloy 설정 및 Nginx 설정 적용 | |
| cd /home/${{ secrets.USERNAME }}/solid-connection-prod | |
| mkdir -p ./docs/infra-config | |
| if [ -d "./docs/infra-config/config.alloy" ]; then | |
| echo "Removing directory created by Docker..." | |
| rm -rf ./docs/infra-config/config.alloy | |
| fi | |
| mv -f ./config.alloy ./docs/infra-config/config.alloy | |
| mkdir -p ./nginx | |
| mv ./nginx.prod.conf ./nginx/default.conf | |
| sudo cp ./nginx/default.conf /etc/nginx/conf.d/default.conf | |
| sudo nginx -t | |
| sudo nginx -s reload | |
| # 5. Docker Compose 재시작 | |
| echo "Restarting Docker Compose with tag: $IMAGE_TAG_ONLY" | |
| docker compose -f docker-compose.prod.yml down | |
| OWNER_LOWERCASE=$OWNER_LOWERCASE IMAGE_TAG=$IMAGE_TAG_ONLY docker compose -f docker-compose.prod.yml up -d | |
| # 6. 정리 | |
| docker image prune -f | |
| echo "Deployment finished successfully." | |
| ' |