pipeline { agent any environment { DEPLOY_DIR = '/var/www/zioinfo' APP_DIR = '/opt/zioinfo/app' JAVA_HOME = '/usr/lib/jvm/java-21-openjdk-amd64' MVN = '/usr/bin/mvn' NODE_HOME = '/usr/bin' } options { buildDiscarder(logRotator(numToKeepStr: '5')) timeout(time: 20, unit: 'MINUTES') } stages { stage('Checkout') { steps { echo "브랜치: ${env.GIT_BRANCH ?: 'main'} | 커밋: ${env.GIT_COMMIT?.take(7) ?: '-'}" checkout scm } } stage('Frontend Build') { steps { dir('frontend') { sh ''' echo "=== [1/3] React 빌드 ===" npm ci --legacy-peer-deps --prefer-offline 2>/dev/null || npm install --legacy-peer-deps npm run build echo "빌드 결과: $(ls ../backend/src/main/resources/static/assets/ | wc -l) 파일" ''' } } } stage('Backend Build') { steps { dir('backend') { sh ''' echo "=== [2/3] Spring Boot 빌드 ===" ${MVN} clean package -DskipTests -q JAR=$(find target -name "*.jar" ! -name "*sources*" | head -1) echo "JAR: $JAR ($(du -sh $JAR | cut -f1))" ''' } } } stage('Deploy') { steps { sh ''' echo "=== [3/3] 배포 ===" JAR=$(find backend/target -name "*.jar" ! -name "*sources*" | head -1) # 앱 디렉터리 확인 mkdir -p ${APP_DIR} ${DEPLOY_DIR} # JAR 배포 cp "$JAR" ${APP_DIR}/app.jar # React 정적 파일 배포 cp -r backend/src/main/resources/static/. ${DEPLOY_DIR}/ # Spring Boot 서비스 재시작 systemctl restart zioinfo || true sleep 4 # 헬스체크 for i in 1 2 3 4 5; do HTTP=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/api/company 2>/dev/null) if [ "$HTTP" = "200" ]; then echo "배포 성공 (Spring Boot HTTP $HTTP)" exit 0 fi echo "헬스체크 ${i}/5 대기중 (HTTP: $HTTP)..." sleep 3 done echo "경고: Spring Boot 응답 없음 — 서비스 상태 확인 필요" ''' } } } post { success { echo "✅ 배포 완료: ${currentBuild.displayName} (${currentBuild.durationString})" } failure { echo "❌ 배포 실패: ${currentBuild.displayName} — 로그 확인 필요" } always { cleanWs(cleanWhenNotBuilt: false, cleanWhenSuccess: false) } } }