Skip to content

Merge pull request #18 from Nexters/feature/add-meme-quiz-serve-api #71

Merge pull request #18 from Nexters/feature/add-meme-quiz-serve-api

Merge pull request #18 from Nexters/feature/add-meme-quiz-serve-api #71

Workflow file for this run

name: Container Registry CI/CD Pipeline (Watchtower Auto-Deploy)
on:
push:
branches:
- master
workflow_dispatch:
inputs:
force_infra_deploy:
description: "Force infra deploy (use when GitHub Secrets changed)"
required: false
default: "false"
type: choice
options: ["false", "true"]
reason:
description: "Reason for manual deploy"
required: false
type: string
env:
REGISTRY_URL: ${{ secrets.NCP_REGISTRY_URL }}
IMAGE_NAME: meme-wiki-be
jobs:
build-and-push:
name: Build and Push to Registry
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up JDK 21
uses: actions/setup-java@v3
with:
java-version: '21'
distribution: 'temurin'
cache: gradle
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew clean build -x test
- name: Get commit SHA
id: vars
run: |
echo "SHORT_SHA=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
echo "TIMESTAMP=$(date +%Y%m%d-%H%M%S)" >> $GITHUB_OUTPUT
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to NCP Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY_URL }}
username: ${{ secrets.NCP_ACCESS_KEY }}
password: ${{ secrets.NCP_SECRET_KEY }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: true
tags: |
${{ env.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:latest
${{ env.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ steps.vars.outputs.SHORT_SHA }}
${{ env.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:${{ steps.vars.outputs.TIMESTAMP }}
cache-from: type=gha
cache-to: type=gha,mode=max
# Infrastructure changes detection and deployment
- name: Check for infrastructure changes
id: changes
run: |
BEFORE="${{ github.event.before }}"
AFTER="${{ github.sha }}"
if [ -z "$BEFORE" ] || [ "$BEFORE" = "$AFTER" ]; then
git fetch --depth=2 origin ${{ github.ref }} | cat
BEFORE=$(git rev-parse HEAD~1)
fi
echo "Comparing range: $BEFORE..$AFTER"
if git diff --name-only "$BEFORE" "$AFTER" | grep -E "(docker-compose\.yml|init-scripts/)" > /dev/null; then
echo "infra_changed=true" >> $GITHUB_OUTPUT
echo "🔧 Infrastructure changes detected"
else
echo "infra_changed=false" >> $GITHUB_OUTPUT
echo "📦 Code-only changes detected"
fi
- name: Deploy infrastructure changes
if: steps.changes.outputs.infra_changed == 'true' || (github.event_name == 'workflow_dispatch' && inputs.force_infra_deploy == 'true')
uses: appleboy/scp-action@master
with:
host: ${{ secrets.NCP_SERVER_HOST }}
username: root
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: "docker-compose.yml,init-scripts/"
target: "/home/ubuntu/app/"
overwrite: true
- name: Restart services for infrastructure changes
if: steps.changes.outputs.infra_changed == 'true' || (github.event_name == 'workflow_dispatch' && inputs.force_infra_deploy == 'true')
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.NCP_SERVER_HOST }}
username: root
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /home/ubuntu/app
echo "🔄 Restarting services (infra_changed=${{ steps.changes.outputs.infra_changed }}, force=${{ inputs.force_infra_deploy }})..."
# Export runtime env vars from GitHub Secrets (no .env file needed)
export MYSQL_ROOT_PASSWORD='${{ secrets.MYSQL_ROOT_PASSWORD }}'
export MYSQL_DATABASE='${{ secrets.MYSQL_DATABASE }}'
export MYSQL_USER='${{ secrets.MYSQL_USER }}'
export MYSQL_PASSWORD='${{ secrets.MYSQL_PASSWORD }}'
export NCP_REGISTRY_URL='${{ secrets.NCP_REGISTRY_URL }}'
export CLOUDFLARE_R2_ACCESS_KEY_ID='${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }}'
export CLOUDFLARE_R2_SECRET_ACCESS_KEY='${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }}'
export CLOUDFLARE_R2_ENDPOINT='${{ secrets.CLOUDFLARE_R2_ENDPOINT }}'
export CLOUDFLARE_R2_BUCKET_NAME='${{ secrets.CLOUDFLARE_R2_BUCKET_NAME }}'
docker compose pull app
docker compose up -d app
docker compose ps
echo "✅ App service restarted"
- name: Deployment completed
run: |
echo "✅ 이미지 배포 완료: ${{ env.REGISTRY_URL }}/${{ env.IMAGE_NAME }}:latest"
echo "event=${{ github.event_name }} infra_changed=${{ steps.changes.outputs.infra_changed }} force=${{ inputs.force_infra_deploy }}"
if [ "${{ steps.changes.outputs.infra_changed }}" == "true" ] || { [ "${{ github.event_name }}" == "workflow_dispatch" ] && [ "${{ inputs.force_infra_deploy }}" == "true" ]; }; then
echo "🔧 Infrastructure changes deployed via SSH"
echo "🐳 Services restarted with new configuration"
else
echo "🐳 Watchtower가 5분 내 자동 배포 시작"
fi