Merge pull request #276 from Coffect/feat/jun-follower-following-list-up #239
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: deploy-main | |
| on: | |
| push: | |
| branches: | |
| - main | |
| workflow_dispatch: | |
| jobs: | |
| deploy: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout Repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 2 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v3 | |
| with: | |
| node-version: '18' | |
| cache: 'npm' | |
| - name: Configure SSH | |
| run: | | |
| mkdir -p ~/.ssh | |
| echo "${{ secrets.EC2_SSH_KEY }}" > ~/.ssh/id_rsa | |
| chmod 600 ~/.ssh/id_rsa | |
| cat > ~/.ssh/config << EOF | |
| Host playground-umc-8th | |
| HostName ${{ secrets.EC2_HOST }} | |
| User ubuntu | |
| IdentityFile ~/.ssh/id_rsa | |
| StrictHostKeyChecking no | |
| UserKnownHostsFile /dev/null | |
| LogLevel ERROR | |
| EOF | |
| - name: Test SSH Connection | |
| run: | | |
| echo "🔍 SSH 연결 테스트 중..." | |
| # SSH 연결 테스트 (여러 번 시도) | |
| for i in {1..3}; do | |
| echo "SSH 연결 시도 $i/3..." | |
| if ssh -o ConnectTimeout=10 playground-umc-8th "echo '✅ SSH Connection Successful ($i/3)'"; then | |
| echo "✅ SSH 연결 성공" | |
| break | |
| else | |
| if [ $i -eq 3 ]; then | |
| echo "❌ SSH 연결 실패 - 연결 정보 확인 필요" | |
| echo "디버깅 정보:" | |
| echo "- SSH 키 권한 확인: $(ls -la ~/.ssh/id_rsa)" | |
| echo "- SSH 설정 확인:" | |
| cat ~/.ssh/config | |
| exit 1 | |
| else | |
| echo "⚠️ 연결 실패, 재시도 중..." | |
| sleep 2 | |
| fi | |
| fi | |
| done | |
| - name: Clean Old Logs and Backups | |
| run: | | |
| ssh playground-umc-8th ' | |
| cd /home/ubuntu/coffect-BE | |
| echo "🧹 이전 로그 및 백업 파일 정리 중..." | |
| # nohup.out 백업 파일들 모두 삭제 | |
| rm -f nohup.out.backup.* 2>/dev/null || true | |
| echo "✅ 이전 백업 파일들 삭제 완료" | |
| # 현재 nohup.out 파일도 삭제 (새로 시작하기 위해) | |
| if [ -f nohup.out ]; then | |
| echo "📄 기존 nohup.out 파일 삭제 중..." | |
| rm -f nohup.out | |
| echo "✅ 기존 nohup.out 삭제 완료" | |
| fi | |
| # logs 디렉토리가 있다면 오래된 로그 정리 (선택사항) | |
| if [ -d logs ]; then | |
| echo "📁 logs 디렉토리 정리 중..." | |
| # 7일 이상 된 로그 파일 삭제 | |
| find logs -type f -mtime +7 -delete 2>/dev/null || true | |
| echo "✅ 오래된 로그 파일 정리 완료" | |
| fi | |
| # 디스크 공간 확인 | |
| echo "💾 현재 디스크 사용량:" | |
| df -h . | head -2 | |
| # 정리 후 파일 목록 확인 | |
| echo "📋 정리 후 파일 목록:" | |
| ls -la | grep -E "(nohup|log)" || echo "로그 관련 파일 없음" | |
| ' | |
| - name: Analyze Changes and Dependencies | |
| id: analyze | |
| run: | | |
| # 변경된 파일들 분석 (안전한 방식) | |
| CHANGED_FILES=$(git diff HEAD^1 --name-only | tr '\n' ' ') | |
| echo "changed-files=${CHANGED_FILES}" >> $GITHUB_OUTPUT | |
| # package.json/package-lock.json 변경 확인 (수정된 부분) | |
| PACKAGE_CHANGED=$(git diff HEAD^1 --name-only | grep -E "(package\.json|package-lock\.json)" | tr '\n' ' ' | sed 's/[[:space:]]*$//') | |
| if [ ! -z "$PACKAGE_CHANGED" ]; then | |
| echo "package-changed=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "package-changed=false" >> $GITHUB_OUTPUT | |
| fi | |
| # 소스 코드 변경 확인 | |
| SOURCE_CHANGED=$(git diff HEAD^1 --name-only | grep -E "\.(ts|js)$" || echo "") | |
| if [ ! -z "$SOURCE_CHANGED" ]; then | |
| echo "source-changed=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "source-changed=false" >> $GITHUB_OUTPUT | |
| fi | |
| # Prisma 스키마 변경 확인 | |
| PRISMA_CHANGED=$(git diff HEAD^1 --name-only | grep "prisma/" || echo "") | |
| if [ ! -z "$PRISMA_CHANGED" ]; then | |
| echo "prisma-changed=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "prisma-changed=false" >> $GITHUB_OUTPUT | |
| fi | |
| # 원격 dependencies 상태 확인 | |
| REMOTE_DEPS_EXISTS=$(ssh playground-umc-8th "test -d /home/ubuntu/coffect-BE/node_modules && echo 'true' || echo 'false'") | |
| echo "remote-deps-exists=${REMOTE_DEPS_EXISTS}" >> $GITHUB_OUTPUT | |
| # package-lock.json 해시 비교 | |
| DEPS_INSTALL_NEEDED="false" | |
| if [ "$REMOTE_DEPS_EXISTS" = "false" ] || [ "$PACKAGE_CHANGED" = "true" ]; then | |
| DEPS_INSTALL_NEEDED="true" | |
| else | |
| REMOTE_LOCK_HASH=$(ssh playground-umc-8th "test -f /home/ubuntu/coffect-BE/package-lock.json && md5sum /home/ubuntu/coffect-BE/package-lock.json | cut -d' ' -f1 || echo 'none'") | |
| LOCAL_LOCK_HASH=$(md5sum package-lock.json | cut -d' ' -f1) | |
| if [ "$REMOTE_LOCK_HASH" != "$LOCAL_LOCK_HASH" ]; then | |
| DEPS_INSTALL_NEEDED="true" | |
| fi | |
| fi | |
| echo "deps-install-needed=${DEPS_INSTALL_NEEDED}" >> $GITHUB_OUTPUT | |
| echo "=== 변경 분석 결과 ===" | |
| echo "Dependencies 설치 필요: ${DEPS_INSTALL_NEEDED}" | |
| echo "Package 변경: ${PACKAGE_CHANGED}" | |
| echo "소스 변경: $([ ! -z "$SOURCE_CHANGED" ] && echo '있음' || echo '없음')" | |
| echo "Prisma 변경: $([ ! -z "$PRISMA_CHANGED" ] && echo '있음' || echo '없음')" | |
| echo "Prisma Client 생성 조건: $([ "$PRISMA_CHANGED" != "" ] || [ "$DEPS_INSTALL_NEEDED" = "true" ] || [ "$SOURCE_CHANGED" != "" ] && echo '실행됨' || echo '건너뜀')" | |
| - name: Efficient File Sync | |
| run: | | |
| ssh playground-umc-8th ' | |
| # 백업 및 디렉토리 준비 | |
| mkdir -p /home/ubuntu/coffect-BE-backup /home/ubuntu/coffect-BE | |
| # 빠른 백업 (중요 파일만) | |
| if [ -d /home/ubuntu/coffect-BE ]; then | |
| cp /home/ubuntu/coffect-BE/.env /home/ubuntu/coffect-BE-backup/ 2>/dev/null || true | |
| cp /home/ubuntu/coffect-BE/package-lock.json /home/ubuntu/coffect-BE-backup/ 2>/dev/null || true | |
| fi | |
| ' | |
| # 변경된 파일이 있는지 확인 | |
| CHANGED_COUNT=$(git diff HEAD^1 --name-only | wc -l) | |
| if [ "$CHANGED_COUNT" -gt 0 ]; then | |
| echo "📁 변경된 파일들을 효율적으로 동기화 중... (${CHANGED_COUNT}개 파일)" | |
| rsync -avz --progress \ | |
| --exclude 'node_modules' \ | |
| --exclude '.git' \ | |
| --exclude 'logs' \ | |
| --exclude 'dist' \ | |
| --exclude '.env' \ | |
| --exclude 'nohup.out*' \ | |
| ./ playground-umc-8th:/home/ubuntu/coffect-BE/ | |
| else | |
| echo "📁 변경된 파일이 없어 동기화를 건너뜁니다." | |
| fi | |
| - name: Smart Dependencies Installation | |
| if: steps.analyze.outputs.deps-install-needed == 'true' | |
| run: | | |
| ssh playground-umc-8th ' | |
| cd /home/ubuntu/coffect-BE | |
| echo "📦 Dependencies 효율적 설치 중..." | |
| # package.json 파일 무결성 확인 및 복구 | |
| echo "🔍 package.json 파일 확인 중..." | |
| if [ -f package.json ]; then | |
| # JSON 유효성 검사 | |
| if node -e "JSON.parse(require(\"fs\").readFileSync(\"package.json\", \"utf8\"))" 2>/dev/null; then | |
| echo "✅ package.json 파일이 유효합니다" | |
| else | |
| echo "❌ package.json 파일이 손상되었습니다. 백업에서 복구 시도..." | |
| # 백업에서 복구 시도 | |
| if [ -f /home/ubuntu/coffect-BE-backup/package.json ]; then | |
| cp /home/ubuntu/coffect-BE-backup/package.json . | |
| echo "✅ 백업에서 package.json 복구 완료" | |
| else | |
| echo "❌ 백업 파일도 없습니다. 배포 중단" | |
| exit 1 | |
| fi | |
| fi | |
| fi | |
| # CPU 과부하 방지를 위한 설정 | |
| export NODE_OPTIONS="--max-old-space-size=768" | |
| export NPM_CONFIG_AUDIT=false | |
| export NPM_CONFIG_FUND=false | |
| export NPM_CONFIG_PROGRESS=false | |
| export NPM_CONFIG_PREFER_OFFLINE=true | |
| # 기존 node_modules 및 package-lock.json 정리 | |
| echo "🧹 기존 dependencies 정리 중..." | |
| rm -rf node_modules package-lock.json 2>/dev/null || true | |
| # npm 설치 최적화 | |
| echo "🆕 Dependencies 클린 설치..." | |
| npm ci --no-audit --no-fund --prefer-offline --no-optional | |
| echo "✅ Dependencies 설치 완료" | |
| ' | |
| - name: Generate Prisma Client | |
| if: steps.analyze.outputs.prisma-changed == 'true' || steps.analyze.outputs.deps-install-needed == 'true' || steps.analyze.outputs.source-changed == 'true' | |
| run: | | |
| ssh playground-umc-8th ' | |
| cd /home/ubuntu/coffect-BE | |
| echo "🔧 Prisma 클라이언트 생성 중..." | |
| export NODE_OPTIONS="--max-old-space-size=512" | |
| # MySQL Prisma 클라이언트 생성 | |
| echo "📋 MySQL Prisma 클라이언트 생성..." | |
| npx prisma generate --schema=prisma/mysql/schema.prisma | |
| # MongoDB Prisma 클라이언트 생성 | |
| echo "📋 MongoDB Prisma 클라이언트 생성..." | |
| npx prisma generate --schema=prisma/mongodb/schema.prisma | |
| echo "✅ Prisma 클라이언트 생성 완료" | |
| ' | |
| - name: Fix Source Code Imports | |
| if: steps.analyze.outputs.source-changed == 'true' || steps.analyze.outputs.deps-install-needed == 'true' | |
| run: | | |
| ssh playground-umc-8th ' | |
| cd /home/ubuntu/coffect-BE | |
| echo "🔍 Prisma import 경로 수정 중..." | |
| # 효율적인 파일 수정 (안전한 sed 패턴 사용) | |
| find src/ -name "*.ts" -type f | while read file; do | |
| if grep -q "generated/prisma" "$file" 2>/dev/null; then | |
| echo "수정: $file" | |
| # from import 수정 | |
| sed -i "s|from [\"'\''].*generated/prisma[\"'\'']|from '\''@prisma/client'\''|g" "$file" | |
| # require 수정 (안전한 패턴) | |
| sed -i "s|require([\"'\''].*generated/prisma[\"'\''])|require('\''@prisma/client'\'')|g" "$file" | |
| fi | |
| done | |
| echo "✅ Import 경로 수정 완료" | |
| ' | |
| - name: Create Environment File | |
| run: | | |
| ssh playground-umc-8th " | |
| # 기본 환경 변수들 생성 | |
| cat > /home/ubuntu/coffect-BE/.env << 'EOF' | |
| DATABASE_NAME=${{ secrets.DATABASE_NAME }} | |
| DATABASE_Endpoint=${{ secrets.DATABASE_Endpoint }} | |
| DATABASE_HOST=${{ secrets.DATABASE_HOST }} | |
| DATABASE_PORT=${{ secrets.DATABASE_PORT }} | |
| DATABASE_USERNAME=${{ secrets.DATABASE_USERNAME }} | |
| DATABASE_PASSWORD=${{ secrets.DATABASE_PASSWORD }} | |
| EC2_PORT=${{ secrets.EC2_PORT }} | |
| JWT_SECRET=${{ secrets.JWT_SECRET }} | |
| JWT_REFRESH=${{ secrets.JWT_REFRESH }} | |
| S3_ACCESS_KEY=${{ secrets.S3_ACCESS_KEY }} | |
| S3_SECRET_KEY=${{ secrets.S3_SECRET_KEY }} | |
| S3_NAME=${{ secrets.S3_NAME }} | |
| ENV=${{ secrets.ENV }} | |
| FIREBASE_PROJECT_ID=${{ secrets.FIREBASE_PROJECT_ID }} | |
| FIREBASE_CLIENT_EMAIL=${{ secrets.FIREBASE_CLIENT_EMAIL }} | |
| FIREBASE_PRIVATE_KEY=${{ secrets.FIREBASE_PRIVATE_KEY }} | |
| MONGODB_URL=${{ secrets.MONGODB_URL }} | |
| EOF | |
| " | |
| - name: Fix Prisma Configuration | |
| run: | | |
| ssh playground-umc-8th ' | |
| cd /home/ubuntu/coffect-BE | |
| echo "🔧 Prisma 설정 확인 및 수정 중..." | |
| # package.json에서 start 스크립트 확인 | |
| echo "📋 package.json start 스크립트:" | |
| cat package.json | grep -A 5 -B 5 "scripts" | |
| # package.json start 스크립트 수정 | |
| echo "🔧 package.json start 스크립트 수정 중..." | |
| # 백업 | |
| cp package.json package.json.backup | |
| # start 스크립트를 수정하여 스키마 경로를 명시적으로 지정 | |
| cat package.json | jq '\''.scripts.start = "npm run prisma && npm run build && node ./dist/index.js"'\'' > package.json.tmp && mv package.json.tmp package.json | |
| # 수정된 내용 확인 | |
| echo "📋 수정된 start 스크립트:" | |
| cat package.json | grep -A 5 -B 5 "scripts" | |
| echo "✅ Prisma 설정 수정 완료" | |
| ' | |
| - name: Smart Build Process | |
| if: steps.analyze.outputs.source-changed == 'true' || steps.analyze.outputs.deps-install-needed == 'true' | |
| run: | | |
| ssh playground-umc-8th ' | |
| cd /home/ubuntu/coffect-BE | |
| echo "🏗️ 효율적 빌드 프로세스 시작..." | |
| export NODE_OPTIONS="--max-old-space-size=1024" | |
| # 기존 dist 제거 (필요시에만) | |
| if [ -d dist ]; then | |
| rm -rf dist | |
| fi | |
| # 빌드 실행 (package.json의 build 스크립트 사용) | |
| echo "📋 빌드 시작..." | |
| if npm run build; then | |
| echo "✅ 빌드 성공" | |
| ls -la dist/ | head -3 | |
| else | |
| echo "❌ 빌드 실패" | |
| exit 1 | |
| fi | |
| ' | |
| - name: Stop Existing Application | |
| run: | | |
| ssh playground-umc-8th ' | |
| set -e # 에러 시 즉시 종료하지 않도록 제거 | |
| cd /home/ubuntu/coffect-BE || { echo "디렉토리 이동 실패"; mkdir -p /home/ubuntu/coffect-BE; cd /home/ubuntu/coffect-BE; } | |
| echo "🛑 기존 애플리케이션 정리 중..." | |
| # SSH 연결 상태 확인 | |
| echo "SSH 연결 상태: OK" | |
| echo "현재 디렉토리: $(pwd)" | |
| echo "사용자: $(whoami)" | |
| # PID 파일 기반 종료 (안전한 방식) | |
| if [ -f app.pid ]; then | |
| PID=$(cat app.pid) | |
| echo "PID 파일 발견: $PID" | |
| if ps -p $PID > /dev/null 2>&1; then | |
| echo "애플리케이션 종료 중 (PID: $PID)..." | |
| kill -TERM $PID 2>/dev/null || echo "TERM 신호 전송 실패" | |
| sleep 3 | |
| if ps -p $PID > /dev/null 2>&1; then | |
| echo "강제 종료 실행..." | |
| kill -KILL $PID 2>/dev/null || echo "KILL 신호 전송 실패" | |
| fi | |
| else | |
| echo "PID $PID 프로세스가 이미 종료됨" | |
| fi | |
| rm -f app.pid | |
| else | |
| echo "PID 파일 없음" | |
| fi | |
| # 포트 기반 프로세스 정리 (더 안전한 방식) | |
| if [ ! -z "${{ secrets.EC2_PORT }}" ]; then | |
| echo "포트 ${{ secrets.EC2_PORT }} 프로세스 확인 중..." | |
| # lsof가 있는 경우에만 실행 | |
| if command -v lsof >/dev/null 2>&1; then | |
| PORT_PIDS=$(lsof -ti:${{ secrets.EC2_PORT }} 2>/dev/null || echo "") | |
| if [ ! -z "$PORT_PIDS" ]; then | |
| echo "포트 프로세스 발견: $PORT_PIDS" | |
| for pid in $PORT_PIDS; do | |
| echo "프로세스 $pid 종료 중..." | |
| kill -TERM $pid 2>/dev/null || echo "TERM 신호 실패: $pid" | |
| done | |
| sleep 2 | |
| for pid in $PORT_PIDS; do | |
| if ps -p $pid > /dev/null 2>&1; then | |
| echo "강제 종료: $pid" | |
| kill -KILL $pid 2>/dev/null || echo "KILL 신호 실패: $pid" | |
| fi | |
| done | |
| else | |
| echo "포트 사용 중인 프로세스 없음" | |
| fi | |
| else | |
| echo "lsof 명령어 없음 - 포트 정리 건너뜀" | |
| fi | |
| fi | |
| # Node.js 프로세스 정리 (더 안전한 방식) | |
| echo "Node.js 프로세스 정리 중..." | |
| # pkill 대신 더 안전한 방식 사용 | |
| ps aux | grep -E "(coffect-BE|npm.*dev|node.*dist)" | grep -v grep | awk "{print \$2}" | while read pid; do | |
| if [ ! -z "$pid" ]; then | |
| echo "Node.js 프로세스 종료: $pid" | |
| kill -TERM $pid 2>/dev/null || echo "프로세스 $pid 종료 실패" | |
| fi | |
| done | |
| sleep 2 | |
| echo "✅ 정리 완료" | |
| ' || { echo "프로세스 정리 중 일부 오류 발생했지만 계속 진행"; exit 0; } | |
| - name: Install Required Tools | |
| run: | | |
| ssh playground-umc-8th ' | |
| echo "🔧 필수 도구 설치 확인 중..." | |
| # nohup 설치 확인 및 설치 | |
| if ! command -v nohup &> /dev/null; then | |
| echo "📦 nohup이 설치되지 않았습니다. 설치 중..." | |
| sudo apt-get update -qq | |
| sudo apt-get install -y coreutils | |
| echo "✅ nohup 설치 완료" | |
| else | |
| echo "✅ nohup이 이미 설치되어 있습니다" | |
| fi | |
| # netstat 설치 확인 및 설치 | |
| if ! command -v netstat &> /dev/null; then | |
| echo "📦 netstat이 설치되지 않았습니다. 설치 중..." | |
| sudo apt-get install -y net-tools | |
| echo "✅ netstat 설치 완료" | |
| else | |
| echo "✅ netstat이 이미 설치되어 있습니다" | |
| fi | |
| # lsof 설치 확인 및 설치 | |
| if ! command -v lsof &> /dev/null; then | |
| echo "📦 lsof가 설치되지 않았습니다. 설치 중..." | |
| sudo apt-get install -y lsof | |
| echo "✅ lsof 설치 완료" | |
| else | |
| echo "✅ lsof가 이미 설치되어 있습니다" | |
| fi | |
| echo "✅ 모든 필수 도구 설치 완료" | |
| ' | |
| - name: Start Application with nohup | |
| run: | | |
| ssh -o ConnectTimeout=30 playground-umc-8th ' | |
| set +e | |
| cd /home/ubuntu/coffect-BE || { echo "디렉토리 이동 실패"; exit 1; } | |
| mkdir -p logs | |
| echo "🚀 애플리케이션 시작 중..." | |
| echo "=== 환경 변수 확인 ===" | |
| echo "NODE_ENV: production" | |
| echo "PORT: ${{ secrets.EC2_PORT }}" | |
| echo "현재 사용자: $(whoami)" | |
| echo "현재 디렉토리: $(pwd)" | |
| # 기존 nohup.out 파일 완전 삭제 (백업하지 않음) | |
| if [ -f nohup.out ]; then | |
| echo "🗑️ 기존 nohup.out 파일 삭제 중..." | |
| rm -f nohup.out | |
| echo "✅ 기존 nohup.out 삭제 완료" | |
| fi | |
| # 백업 파일들도 모두 삭제 | |
| echo "🗑️ 모든 nohup 백업 파일 삭제 중..." | |
| rm -f nohup.out.backup.* 2>/dev/null || true | |
| echo "✅ 백업 파일 삭제 완료" | |
| echo "📋 시작 전 확인사항:" | |
| echo "- package.json 존재: $([ -f package.json ] && echo "✅" || echo "❌")" | |
| echo "- node_modules 존재: $([ -d node_modules ] && echo "✅" || echo "❌")" | |
| echo "- dist 디렉토리 존재: $([ -d dist ] && echo "✅" || echo "❌")" | |
| # Prisma 스키마 파일 확인 | |
| echo "📋 Prisma 스키마 파일 확인:" | |
| if [ -f prisma/mysql/schema.prisma ]; then | |
| echo "✅ MySQL 스키마 존재" | |
| else | |
| echo "❌ MySQL 스키마 없음" | |
| fi | |
| if [ -f prisma/mongodb/schema.prisma ]; then | |
| echo "✅ MongoDB 스키마 존재" | |
| else | |
| echo "❌ MongoDB 스키마 없음" | |
| fi | |
| echo "🚀 nohup으로 애플리케이션 시작..." | |
| # Prisma 클라이언트를 먼저 생성하고 애플리케이션 시작 | |
| echo "🔧 Prisma 클라이언트 생성 중..." | |
| # 환경 변수를 직접 설정하여 nohup 실행 (수정된 방식) | |
| NODE_ENV=production \ | |
| PORT=${{ secrets.EC2_PORT }} \ | |
| DATABASE_HOST=${{ secrets.DATABASE_HOST }} \ | |
| DATABASE_PORT=${{ secrets.DATABASE_PORT }} \ | |
| DATABASE_NAME=${{ secrets.DATABASE_NAME }} \ | |
| DATABASE_USERNAME=${{ secrets.DATABASE_USERNAME }} \ | |
| DATABASE_PASSWORD="${{ secrets.DATABASE_PASSWORD }}" \ | |
| JWT_SECRET="${{ secrets.JWT_SECRET }}" \ | |
| JWT_REFRESH="${{ secrets.JWT_REFRESH }}" \ | |
| S3_ACCESS_KEY="${{ secrets.S3_ACCESS_KEY }}" \ | |
| S3_SECRET_KEY="${{ secrets.S3_SECRET_KEY }}" \ | |
| S3_NAME="${{ secrets.S3_NAME }}" \ | |
| ENV="${{ secrets.ENV }}" \ | |
| FIREBASE_PROJECT_ID="${{ secrets.FIREBASE_PROJECT_ID }}" \ | |
| FIREBASE_CLIENT_EMAIL="${{ secrets.FIREBASE_CLIENT_EMAIL }}" \ | |
| FIREBASE_PRIVATE_KEY="${{ secrets.FIREBASE_PRIVATE_KEY }}" \ | |
| MONGODB_URL="${{ secrets.MONGODB_URL }}" \ | |
| nohup sh -c " | |
| echo \"=== 애플리케이션 시작 \$(date) ===\" | |
| echo \"Prisma 클라이언트 생성 중...\" | |
| # MySQL Prisma 클라이언트 생성 | |
| if [ -f prisma/mysql/schema.prisma ]; then | |
| echo \"MySQL Prisma 클라이언트 생성 중...\" | |
| npx prisma generate --schema=prisma/mysql/schema.prisma || echo \"MySQL Prisma 생성 실패\" | |
| fi | |
| # MongoDB Prisma 클라이언트 생성 | |
| if [ -f prisma/mongodb/schema.prisma ]; then | |
| echo \"MongoDB Prisma 클라이언트 생성 중...\" | |
| npx prisma generate --schema=prisma/mongodb/schema.prisma || echo \"MongoDB Prisma 생성 실패\" | |
| fi | |
| echo \"빌드 시작...\" | |
| npm run build || { echo \"빌드 실패\"; exit 1; } | |
| echo \"애플리케이션 시작...\" | |
| node ./dist/index.js | |
| " > nohup.out 2>&1 & | |
| APP_PID=$! | |
| echo $APP_PID > app.pid | |
| echo "✅ 애플리케이션 시작됨 (PID: $APP_PID)" | |
| echo "⏳ nohup.out 파일 생성 대기 중..." | |
| for j in {1..10}; do | |
| if [ -f nohup.out ]; then | |
| echo "✅ nohup.out 파일 생성 확인됨 (시도 $j/10)" | |
| echo "📄 nohup.out 초기 내용:" | |
| head -10 nohup.out 2>/dev/null || echo "아직 내용 없음" | |
| break | |
| else | |
| echo "⏳ nohup.out 생성 대기... ($j/10)" | |
| sleep 1 | |
| fi | |
| done | |
| if [ ! -f nohup.out ]; then | |
| echo "⚠️ nohup.out 파일이 생성되지 않았습니다" | |
| echo "현재 디렉토리 파일 목록:" | |
| ls -la | grep -E "(nohup|log)" || echo "로그 파일 없음" | |
| fi | |
| echo "⏳ 프로세스 상태 확인 중..." | |
| for i in {1..25}; do | |
| if ps -p $APP_PID > /dev/null 2>&1; then | |
| echo "✅ 프로세스 정상 실행 중 (확인 $i/25)" | |
| if [ -f nohup.out ] && [ -s nohup.out ]; then | |
| echo "📄 nohup.out 최신 내용:" | |
| tail -5 nohup.out 2>/dev/null || echo "nohup.out 읽기 실패" | |
| fi | |
| # 더 긴 시간 기다리기 (Prisma 생성 + 빌드 시간 고려) | |
| if [ ! -z "${{ secrets.EC2_PORT }}" ] && command -v netstat >/dev/null 2>&1; then | |
| if netstat -ln 2>/dev/null | grep -q ":${{ secrets.EC2_PORT }}"; then | |
| echo "✅ 포트 ${{ secrets.EC2_PORT }} 바인딩 확인" | |
| break | |
| else | |
| echo "⏳ 포트 바인딩 대기 중... (확인 $i/25)" | |
| fi | |
| else | |
| if [ $i -ge 15 ]; then | |
| echo "✅ 프로세스 실행 확인 완료" | |
| break | |
| fi | |
| fi | |
| else | |
| echo "❌ 프로세스 실행 실패 (확인 $i/25)" | |
| echo "=== 상세 에러 분석 ===" | |
| if [ -f nohup.out ]; then | |
| echo "📄 nohup.out 전체 내용:" | |
| cat nohup.out 2>/dev/null || echo "nohup.out 읽기 실패" | |
| else | |
| echo "❌ nohup.out 파일이 존재하지 않습니다" | |
| echo "📁 현재 디렉토리 내용:" | |
| ls -la | head -10 | |
| fi | |
| echo "=== 시스템 상태 ===" | |
| echo "💾 메모리 사용량:" | |
| free -h 2>/dev/null || echo "메모리 정보 없음" | |
| echo "💾 디스크 사용량:" | |
| df -h . 2>/dev/null || echo "디스크 정보 없음" | |
| echo "❌ 프로세스 시작 실패 - 종료" | |
| exit 1 | |
| fi | |
| sleep 3 | |
| done | |
| if ps -p $APP_PID > /dev/null 2>&1; then | |
| echo "✅ 애플리케이션 성공적으로 시작됨" | |
| echo "📊 프로세스 정보:" | |
| ps -p $APP_PID -o pid,ppid,cmd,etime 2>/dev/null || echo "프로세스 정보 조회 실패" | |
| if [ -f nohup.out ]; then | |
| echo "📄 nohup.out 파일 상태:" | |
| ls -lh nohup.out | |
| if [ -s nohup.out ]; then | |
| echo "📄 nohup.out 최신 내용 (마지막 10줄):" | |
| tail -10 nohup.out 2>/dev/null || echo "nohup.out 읽기 실패" | |
| else | |
| echo "⚠️ nohup.out 파일이 비어있습니다" | |
| fi | |
| else | |
| echo "⚠️ nohup.out 파일이 존재하지 않습니다" | |
| fi | |
| else | |
| echo "❌ 애플리케이션 시작 최종 실패" | |
| echo "=== 최종 디버깅 정보 ===" | |
| echo "📁 현재 디렉토리 내용:" | |
| ls -la 2>/dev/null || echo "디렉토리 내용 확인 불가" | |
| if [ -f nohup.out ]; then | |
| echo "📄 nohup.out 최종 내용:" | |
| cat nohup.out 2>/dev/null || echo "nohup.out 읽기 실패" | |
| fi | |
| exit 1 | |
| fi | |
| ' | |
| - name: Quick Health Check | |
| run: | | |
| ssh playground-umc-8th ' | |
| cd /home/ubuntu/coffect-BE | |
| echo "🏥 상세한 헬스 체크..." | |
| # 프로세스 상태 확인 | |
| if [ -f app.pid ]; then | |
| PID=$(cat app.pid) | |
| if kill -0 $PID 2>/dev/null; then | |
| echo "✅ 프로세스 실행 중 (PID: $PID)" | |
| # 프로세스 상세 정보 | |
| echo "📊 프로세스 정보:" | |
| ps -p $PID -o pid,ppid,cmd,etime,pcpu,pmem | |
| # nohup.out 파일 확인 | |
| if [ -f nohup.out ]; then | |
| echo "📄 nohup.out 파일 상태:" | |
| ls -lh nohup.out | |
| echo "📄 nohup.out 최신 내용:" | |
| tail -5 nohup.out 2>/dev/null || echo "nohup.out 읽기 실패" | |
| else | |
| echo "⚠️ nohup.out 파일이 존재하지 않습니다" | |
| fi | |
| # 포트 바인딩 확인 | |
| if [ ! -z "${{ secrets.EC2_PORT }}" ]; then | |
| echo "🔍 포트 ${{ secrets.EC2_PORT }} 바인딩 확인:" | |
| netstat -ln 2>/dev/null | grep ":${{ secrets.EC2_PORT }}" || echo "포트 바인딩 없음" | |
| # HTTP 응답 테스트 (더 긴 시간) | |
| echo "🌐 HTTP 응답 테스트..." | |
| for i in {1..5}; do | |
| echo "시도 $i/5:" | |
| # 외부 IP 테스트 | |
| if curl -f -s -m 10 http://${{ secrets.EC2_HOST }}:${{ secrets.EC2_PORT }}/ > /dev/null 2>&1; then | |
| echo "✅ 외부 IP 응답 성공" | |
| break | |
| else | |
| echo "❌ 외부 IP 응답 실패" | |
| fi | |
| if [ $i -lt 5 ]; then | |
| echo "⏳ 3초 대기 후 재시도..." | |
| sleep 3 | |
| fi | |
| done | |
| # 최종 상태 확인 | |
| if curl -f -s -m 5 http://localhost:${{ secrets.EC2_PORT }}/ > /dev/null 2>&1; then | |
| echo "✅ 서버 정상 응답 확인" | |
| else | |
| echo "⚠️ 서버 응답 없음 - 로그 확인" | |
| if [ -f nohup.out ]; then | |
| echo "📄 nohup.out 최신 내용:" | |
| tail -10 nohup.out 2>/dev/null || echo "nohup.out 읽기 실패" | |
| fi | |
| # 프로세스는 살아있지만 응답이 없는 경우 | |
| if kill -0 $PID 2>/dev/null; then | |
| echo "⚠️ 프로세스는 실행 중이지만 서버 응답이 없습니다" | |
| echo "이는 애플리케이션 초기화 중이거나 포트 바인딩 문제일 수 있습니다" | |
| else | |
| echo "❌ 프로세스가 종료되었습니다" | |
| exit 1 | |
| fi | |
| fi | |
| else | |
| echo "⚠️ 포트 미설정 - 프로세스 상태만 확인" | |
| fi | |
| else | |
| echo "❌ 프로세스 실행 실패" | |
| if [ -f nohup.out ]; then | |
| echo "=== nohup.out 에러 내용 ===" | |
| cat nohup.out 2>/dev/null || echo "nohup.out 읽기 실패" | |
| fi | |
| exit 1 | |
| fi | |
| else | |
| echo "❌ PID 파일 없음" | |
| exit 1 | |
| fi | |
| ' | |
| - name: Deployment Summary | |
| if: always() | |
| run: | | |
| ssh playground-umc-8th ' | |
| cd /home/ubuntu/coffect-BE | |
| echo "📊 배포 완료 요약" | |
| echo "====================" | |
| # 프로세스 상태 | |
| if [ -f app.pid ]; then | |
| PID=$(cat app.pid) | |
| if kill -0 $PID 2>/dev/null; then | |
| echo "✅ 애플리케이션 실행 중 (PID: $PID)" | |
| else | |
| echo "❌ 애플리케이션 중지됨" | |
| fi | |
| else | |
| echo "❌ PID 파일 없음" | |
| fi | |
| # nohup.out 파일 상태 | |
| if [ -f nohup.out ]; then | |
| echo "✅ nohup.out 파일 존재 (크기: $(ls -lh nohup.out | awk \"{print \$5}\"))" | |
| echo "📄 nohup.out 마지막 3줄:" | |
| tail -3 nohup.out 2>/dev/null || echo "nohup.out 읽기 실패" | |
| else | |
| echo "❌ nohup.out 파일 없음" | |
| fi | |
| # 백업 파일 정리 확인 | |
| echo "" | |
| echo "🧹 nohup 백업 파일 정리 상태:" | |
| BACKUP_COUNT=$(ls -la | grep -c "nohup.out.backup" || echo "0") | |
| if [ "$BACKUP_COUNT" -eq "0" ]; then | |
| echo "✅ 백업 파일 없음 (정리 완료)" | |
| else | |
| echo "⚠️ 백업 파일 $BACKUP_COUNT개 존재" | |
| ls -la | grep "nohup.out.backup" | head -5 | |
| fi | |
| # 포트 상태 (빠른 확인) | |
| if [ ! -z "${{ secrets.EC2_PORT }}" ]; then | |
| if netstat -ln 2>/dev/null | grep -q ":${{ secrets.EC2_PORT }}"; then | |
| echo "✅ 포트 ${{ secrets.EC2_PORT }} 리스닝 중" | |
| else | |
| echo "⚠️ 포트 ${{ secrets.EC2_PORT }} 대기 중" | |
| fi | |
| fi | |
| echo "" | |
| echo "📄 nohup.out 파일 실시간 모니터링 명령어:" | |
| echo " tail -f nohup.out" | |
| echo "" | |
| echo "⏰ 배포 완료: $(date)" | |
| ' |