[Feat] 커뮤니티, 댓글, 사진 신고 기능 개발 #256
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: Planup Dev CI/CD | |
| on: | |
| push: | |
| branches: [ develop ] | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| - name: Set up JDK 17 | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: 'temurin' | |
| java-version: '17' | |
| - name: Cache Gradle dependencies | |
| uses: actions/cache@v3 | |
| with: | |
| path: | | |
| ~/.gradle/caches | |
| ~/.gradle/wrapper | |
| key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} | |
| restore-keys: | | |
| gradle-${{ runner.os }}- | |
| - name: Grant execute permission for Gradlew | |
| run: chmod +x gradlew | |
| - name: Build with Gradle | |
| run: ./gradlew build -x test --no-daemon --parallel --build-cache | |
| - name: Upload Build Artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: build-files | |
| path: | | |
| build/libs/*.jar | |
| Dockerfile | |
| docker-compose.yml | |
| monitoring/ | |
| nginx/ | |
| deploy: | |
| needs: build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| - name: Download Build Artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: build-files | |
| - name: Deploy to EC2 with Docker | |
| shell: bash | |
| env: | |
| EC2_SSH_KEY: ${{ secrets.EC2_SSH_KEY }} | |
| EC2_USERNAME: ${{ secrets.EC2_USERNAME }} | |
| EC2_HOST: ${{ secrets.EC2_HOST }} | |
| DB_PORT: ${{ secrets.DB_PORT }} | |
| DB_NAME: ${{ secrets.DB_NAME }} | |
| DB_USER: ${{ secrets.DB_USER }} | |
| DB_PASSWORD: ${{ secrets.DB_PASSWORD }} | |
| JWT_SECRET: ${{ secrets.JWT_SECRET }} | |
| AWS_ACCESS_KEY: ${{ secrets.AWS_ACCESS_KEY }} | |
| AWS_SECRET_KEY: ${{ secrets.AWS_SECRET_KEY }} | |
| AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }} | |
| MAIL_USERNAME: ${{ secrets.MAIL_USERNAME }} | |
| MAIL_PASSWORD: ${{ secrets.MAIL_PASSWORD }} | |
| REST_API_KEY: ${{ secrets.REST_API_KEY }} | |
| GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }} | |
| APP_FRONTEND_URL: ${{ secrets.APP_FRONTEND_URL }} | |
| GRAFANA_ADMIN_PASSWORD: ${{ secrets.GRAFANA_ADMIN_PASSWORD }} | |
| run: | | |
| echo "$EC2_SSH_KEY" > private_key.pem | |
| chmod 600 private_key.pem | |
| # .env 파일 생성 | |
| cat <<EOF > .env | |
| # 데이터베이스 설정 | |
| DB_HOST=mysql | |
| DB_PORT=${DB_PORT} | |
| DB_NAME=${DB_NAME} | |
| DB_USER=${DB_USER} | |
| DB_PASSWORD=${DB_PASSWORD} | |
| # Redis 설정 | |
| SPRING_DATA_REDIS_HOST=redis | |
| SPRING_DATA_REDIS_PORT=6379 | |
| # JWT 설정 | |
| JWT_SECRET=${JWT_SECRET} | |
| # AWS 설정 | |
| AWS_ACCESS_KEY=${AWS_ACCESS_KEY} | |
| AWS_SECRET_KEY=${AWS_SECRET_KEY} | |
| AWS_S3_BUCKET=${AWS_S3_BUCKET} | |
| # 메일 설정 | |
| MAIL_HOST=smtp.gmail.com | |
| MAIL_USERNAME=${MAIL_USERNAME} | |
| MAIL_PASSWORD=${MAIL_PASSWORD} | |
| # 카카오 OAuth | |
| REST_API_KEY=${REST_API_KEY} | |
| KAKAO_REDIRECT_URI=http://${EC2_HOST}/test/kakao/callback | |
| # Google Gemini | |
| GOOGLE_API_KEY=${GOOGLE_API_KEY} | |
| # 애플리케이션 설정 | |
| APP_DOMAIN=http://${EC2_HOST} | |
| APP_FRONTEND_URL=http://localhost:3000 | |
| APP_FRONTEND_URLS=http://localhost:3000,http://localhost:3001,http://${EC2_HOST}:3000 | |
| SPRING_PROFILES_ACTIVE=dev | |
| # Grafana 설정 | |
| GRAFANA_ADMIN_USER=admin | |
| GRAFANA_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD} | |
| EOF | |
| # 배포 디렉토리 생성 | |
| ssh -i private_key.pem -o StrictHostKeyChecking=no ${EC2_USERNAME}@${EC2_HOST} \ | |
| "mkdir -p /home/${EC2_USERNAME}/planup/build/libs /home/${EC2_USERNAME}/planup/monitoring /home/${EC2_USERNAME}/planup/nginx/conf.d" | |
| # 파일 전송 전에 디스크 정리 | |
| echo "=== Cleaning up disk space before transfer ===" | |
| ssh -i private_key.pem -o StrictHostKeyChecking=no ${EC2_USERNAME}@${EC2_HOST} << 'CLEANUP' | |
| cd /home/${EC2_USERNAME}/planup | |
| echo "Current disk usage:" | |
| df -h | |
| echo "Stopping existing containers..." | |
| docker-compose down 2>/dev/null || true | |
| echo "Cleaning Docker resources..." | |
| # docker system prune -af --volumes 2>/dev/null || true | |
| docker image prune -af || true | |
| docker builder prune -af || true | |
| echo "Removing old build files..." | |
| rm -rf /home/${EC2_USERNAME}/planup/build/libs/*.jar 2>/dev/null || true | |
| echo "Disk usage after cleanup:" | |
| df -h | |
| CLEANUP | |
| # 파일 전송 | |
| echo "=== Transferring files to EC2 ===" | |
| rsync -avz -e "ssh -i private_key.pem -o StrictHostKeyChecking=no" \ | |
| Dockerfile ${EC2_USERNAME}@${EC2_HOST}:/home/${EC2_USERNAME}/planup/ | |
| rsync -avz -e "ssh -i private_key.pem -o StrictHostKeyChecking=no" \ | |
| docker-compose.yml ${EC2_USERNAME}@${EC2_HOST}:/home/${EC2_USERNAME}/planup/ | |
| rsync -avz -e "ssh -i private_key.pem -o StrictHostKeyChecking=no" \ | |
| .env ${EC2_USERNAME}@${EC2_HOST}:/home/${EC2_USERNAME}/planup/ | |
| rsync -avz -e "ssh -i private_key.pem -o StrictHostKeyChecking=no" \ | |
| build/libs/*.jar ${EC2_USERNAME}@${EC2_HOST}:/home/${EC2_USERNAME}/planup/build/libs/ | |
| rsync -avz -e "ssh -i private_key.pem -o StrictHostKeyChecking=no" \ | |
| monitoring/ ${EC2_USERNAME}@${EC2_HOST}:/home/${EC2_USERNAME}/planup/monitoring/ | |
| rsync -avz -e "ssh -i private_key.pem -o StrictHostKeyChecking=no" \ | |
| nginx/ ${EC2_USERNAME}@${EC2_HOST}:/home/${EC2_USERNAME}/planup/nginx/ | |
| # Docker Compose 배포 스크립트 | |
| cat <<DEPLOY_SCRIPT > deploy.sh | |
| #!/bin/bash | |
| set -e | |
| cd /home/${EC2_USERNAME}/planup | |
| echo "=== Checking disk space ===" | |
| df -h | |
| echo "=== Stopping existing containers ===" | |
| docker compose down || true | |
| echo "=== Cleaning old images ===" | |
| docker image prune -af || true | |
| echo "=== Building and starting containers ===" | |
| docker compose up -d --build | |
| echo "=== Waiting for services to be healthy ===" | |
| echo "Initial startup delay: 60 seconds..." | |
| sleep 60 | |
| echo "=== Checking application health ===" | |
| MAX_ATTEMPTS=6 | |
| ATTEMPT=1 | |
| while [ \$ATTEMPT -le \$MAX_ATTEMPTS ]; do | |
| if curl -f http://localhost/actuator/health > /dev/null 2>&1; then | |
| echo "✓ Application is healthy!" | |
| break | |
| fi | |
| if [ \$ATTEMPT -eq \$MAX_ATTEMPTS ]; then | |
| echo "✗ Health check failed after \$MAX_ATTEMPTS attempts" | |
| else | |
| echo "Attempt \$ATTEMPT/\$MAX_ATTEMPTS: Waiting 10 more seconds..." | |
| fi | |
| ATTEMPT=\$((ATTEMPT + 1)) | |
| sleep 10 | |
| done | |
| echo "=== Container status ===" | |
| docker compose ps | |
| echo "=== Application logs (last 100 lines) ===" | |
| docker compose logs --tail=100 app | |
| echo "=== Final health check ===" | |
| curl -f http://localhost/actuator/health || echo "Health check failed" | |
| echo "=== Final disk space ===" | |
| df -h | |
| echo "=== Deployment completed ===" | |
| DEPLOY_SCRIPT | |
| # 배포 스크립트 전송 및 실행 | |
| scp -i private_key.pem -o StrictHostKeyChecking=no deploy.sh ${EC2_USERNAME}@${EC2_HOST}:/home/${EC2_USERNAME}/planup/ | |
| ssh -i private_key.pem -o StrictHostKeyChecking=no ${EC2_USERNAME}@${EC2_HOST} \ | |
| "chmod +x /home/${EC2_USERNAME}/planup/deploy.sh && /home/${EC2_USERNAME}/planup/deploy.sh" | |
| rm -f private_key.pem .env deploy.sh |