name: Build & Deploy on: push: branches: [main] env: DEPLOY_HOST: 192.168.1.18 DEPLOY_PORT: 32023 APP_DIR: /home/apps/signal-batch APP_PORT: 18090 CONTEXT_PATH: /signal-batch jobs: build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Install JDK 17 + Maven run: | apt-get update -qq apt-get install -y -qq openjdk-17-jdk-headless maven openssh-client jq > /dev/null 2>&1 java -version mvn --version - name: Build with Maven run: | mvn -B clean package -DskipTests \ -Dmaven.compiler.release=17 ls -lh target/vessel-batch-aggregation.jar - name: Deploy to production server env: DEPLOY_KEY: ${{ secrets.DEPLOY_SSH_KEY }} run: | # SSH 키 설정 mkdir -p ~/.ssh echo "$DEPLOY_KEY" > ~/.ssh/id_deploy chmod 600 ~/.ssh/id_deploy ssh-keyscan -p $DEPLOY_PORT $DEPLOY_HOST >> ~/.ssh/known_hosts 2>/dev/null || true SSH_CMD="ssh -p $DEPLOY_PORT -i ~/.ssh/id_deploy -o StrictHostKeyChecking=no root@$DEPLOY_HOST" SCP_CMD="scp -P $DEPLOY_PORT -i ~/.ssh/id_deploy -o StrictHostKeyChecking=no" # JAR 전송 echo "=== Uploading JAR ===" $SCP_CMD target/vessel-batch-aggregation.jar root@$DEPLOY_HOST:$APP_DIR/vessel-batch-aggregation.jar.new # 안전 배포: 활성 Job 확인 → 종료 → JAR 교체 → 기동 echo "=== Safe Deploy ===" $SSH_CMD bash -s << 'DEPLOY' set -e APP_DIR=/home/apps/signal-batch BASE_URL="http://localhost:18090/signal-batch" SAFE_COUNT=0 MAX_WAIT=300 # 1단계: 활성 Job 없음 3초 연속 확인 echo "--- Waiting for running jobs to complete ---" for i in $(seq 1 $MAX_WAIT); do RESPONSE=$(curl -sf "$BASE_URL/admin/batch/job/running" 2>/dev/null || echo "UNAVAILABLE") if [ "$RESPONSE" = "UNAVAILABLE" ]; then echo "App not responding — proceeding with deploy" SAFE_COUNT=3 break fi RUNNING=$(echo "$RESPONSE" | jq 'length' 2>/dev/null || echo "0") if [ "$RUNNING" = "0" ]; then SAFE_COUNT=$((SAFE_COUNT + 1)) echo "No running jobs ($SAFE_COUNT/3)" if [ $SAFE_COUNT -ge 3 ]; then echo "Safe to deploy!" break fi else [ $SAFE_COUNT -gt 0 ] && echo "Active job detected — resetting count" SAFE_COUNT=0 fi sleep 1 done if [ $SAFE_COUNT -lt 3 ]; then echo "WARNING: Timeout waiting for jobs. Proceeding anyway." fi # 2단계: 서비스 중지 (graceful shutdown) echo "--- Stopping service ---" systemctl stop signal-batch || true # systemd TimeoutStopSec=180 에서 graceful shutdown 완료 대기 # 3단계: JAR 교체 echo "--- Replacing JAR ---" mkdir -p $APP_DIR/backup if [ -f $APP_DIR/vessel-batch-aggregation.jar ]; then cp $APP_DIR/vessel-batch-aggregation.jar $APP_DIR/backup/vessel-batch-aggregation.jar.$(date +%Y%m%d-%H%M%S) fi mv $APP_DIR/vessel-batch-aggregation.jar.new $APP_DIR/vessel-batch-aggregation.jar restorecon -v $APP_DIR/vessel-batch-aggregation.jar 2>/dev/null || true # 백업 정리 (최근 5개만 유지) ls -t $APP_DIR/backup/vessel-batch-aggregation.jar.* 2>/dev/null | tail -n +6 | xargs rm -f 2>/dev/null || true # 4단계: 서비스 기동 echo "--- Starting service ---" systemctl start signal-batch # 5단계: 기동 확인 (최대 90초 — 64GB 힙 AlwaysPreTouch) for i in $(seq 1 90); do if curl -sf "$BASE_URL/actuator/health/liveness" > /dev/null 2>&1; then echo "Service started successfully (${i}s)" curl -s "$BASE_URL/actuator/health" exit 0 fi sleep 1 done echo "WARNING: Startup timeout. Recent logs:" journalctl -u signal-batch --no-pager -n 50 exit 1 DEPLOY - name: Cleanup if: always() run: rm -f ~/.ssh/id_deploy