diff --git a/Jenkinsfile.deploy b/Jenkinsfile.deploy index 69a0e3d..9d6057f 100644 --- a/Jenkinsfile.deploy +++ b/Jenkinsfile.deploy @@ -1,5 +1,5 @@ pipeline { - agent { label 'djb-vm' } + agent none options { timestamps() @@ -8,213 +8,153 @@ pipeline { } environment { - JAVA_HOME = '/apps/opts/jdk8' - JAVA_HOME_TOMCAT = '/apps/opts/jdk17' - GRADLE_HOME = '/apps/opts/gradle-8.7' - GRADLE_USER_HOME = '/apps/opts/gradle-home' - NODE_HOME = '/apps/opts/node-v24' - PATH = "/apps/opts/jdk8/bin:/apps/opts/gradle-8.7/bin:/apps/opts/node-v24/bin:/apps/opts/bin:${env.PATH}" GIT_SSH_COMMAND = 'ssh -o StrictHostKeyChecking=accept-new' - CATALINA_BASE = '/prod/eapim/devportal' - CATALINA_HOME = '/prod/eapim/apache-tomcat-9.0.116' - CATALINA_PID = '/prod/eapim/devportal/temp/catalina.pid' - DEPLOY_HTTP_PORT = '39130' WEBHOOK_URL = 'http://172.30.1.50:18000/api/hooks/01ba51b01d3c4c98ae8f3183a23a84ed713197857d024b5da4f303458195eb32' } stages { - stage('Checkout') { - steps { - checkout scm + stage('Build (djb-vm)') { + agent { label 'djb-vm' } + environment { + JAVA_HOME = '/apps/opts/jdk8' + GRADLE_HOME = '/apps/opts/gradle-8.7' + GRADLE_USER_HOME = '/apps/opts/gradle-home' + NODE_HOME = '/apps/opts/node-v24' + PATH = "/apps/opts/jdk8/bin:/apps/opts/gradle-8.7/bin:/apps/opts/node-v24/bin:/apps/opts/bin:${env.PATH}" } - } - - stage('Checkout dependencies') { - steps { - sh ''' - set -eu - cd "$WORKSPACE/.." - - if [ ! -d elink-portal-common/.git ]; then - rm -rf elink-portal-common - git clone --depth=1 --branch master \ - ssh://git@172.30.1.50:2222/djb-eapim/elink-portal-common.git \ - elink-portal-common - else - git -C elink-portal-common fetch --depth=1 origin master - git -C elink-portal-common reset --hard origin/master - git -C elink-portal-common clean -fdx - fi - - mkdir -p eapim-online - if [ ! -d eapim-online/elink-online-core-jpa/.git ]; then - rm -rf eapim-online/elink-online-core-jpa - git clone --depth=1 --branch master \ - ssh://git@172.30.1.50:2222/djb-eapim/elink-online-core-jpa.git \ - eapim-online/elink-online-core-jpa - else - git -C eapim-online/elink-online-core-jpa fetch --depth=1 origin master - git -C eapim-online/elink-online-core-jpa reset --hard origin/master - git -C eapim-online/elink-online-core-jpa clean -fdx - fi - ''' - } - } - - stage('Verify toolchain') { - steps { - sh ''' - set -eu - java -version - gradle --version - ''' - } - } - - stage('Test') { - steps { - sh 'gradle clean test --no-daemon' - } - post { - always { - junit allowEmptyResults: true, testResults: 'build/test-results/test/*.xml' - archiveArtifacts allowEmptyArchive: true, artifacts: 'build/reports/tests/test/**,build/test-results/test/**' + stages { + stage('Checkout') { + steps { checkout scm } + } + stage('Checkout dependencies') { + steps { + sh ''' + set -eu + cd "$WORKSPACE/.." + if [ ! -d elink-portal-common/.git ]; then + rm -rf elink-portal-common + git clone --depth=1 --branch master \ + ssh://git@172.30.1.50:2222/djb-eapim/elink-portal-common.git elink-portal-common + else + git -C elink-portal-common fetch --depth=1 origin master + git -C elink-portal-common reset --hard origin/master + git -C elink-portal-common clean -fdx + fi + mkdir -p eapim-online + if [ ! -d eapim-online/elink-online-core-jpa/.git ]; then + rm -rf eapim-online/elink-online-core-jpa + git clone --depth=1 --branch master \ + ssh://git@172.30.1.50:2222/djb-eapim/elink-online-core-jpa.git eapim-online/elink-online-core-jpa + else + git -C eapim-online/elink-online-core-jpa fetch --depth=1 origin master + git -C eapim-online/elink-online-core-jpa reset --hard origin/master + git -C eapim-online/elink-online-core-jpa clean -fdx + fi + ''' + } + } + stage('Verify toolchain') { + steps { sh 'set -eu; java -version; gradle --version' } + } + stage('Test') { + steps { sh 'gradle clean test --no-daemon -Pprofile=weblogic' } + post { + always { + junit allowEmptyResults: true, testResults: 'build/test-results/test/*.xml' + archiveArtifacts allowEmptyArchive: true, artifacts: 'build/reports/tests/test/**,build/test-results/test/**' + } + } + } + stage('Build WAR') { + steps { sh 'gradle build -x test --no-daemon -Pprofile=weblogic' } + post { + success { + sh ''' + set -eu + cd build/libs + for f in eapim-portal.war eapim-portal-boot.war; do + sha1sum "$f" > "$f.sha1"; sha256sum "$f" > "$f.sha256"; md5sum "$f" > "$f.md5" + done + ''' + archiveArtifacts artifacts: 'build/libs/eapim-portal.war,build/libs/eapim-portal-boot.war,build/libs/*.sha1,build/libs/*.sha256,build/libs/*.md5', fingerprint: true + stash name: 'war', includes: 'build/libs/eapim-portal.war' + } + } } } } - stage('Build WAR') { - steps { - sh 'gradle build -x test --no-daemon' + stage('Deploy (weblogic)') { + agent { label 'weblogic' } + environment { + JENKINS_NODE_COOKIE = 'dontKillMe' // background weblogic를 빌드 종료 시 죽이지 않게 + WL_HOME = '/prod/eapim/devportal' + WL_DEPLOY_DIR = '/prod/eapim/devportal/war' + WL_WAR_NAME = 'eapim-portal.war' + WL_HTTP_PORT = '39130' + WL_NOHUP = '/logs/weblogic/domains/eapimDomain/nohup.devSvr11.out' } - post { - success { - sh ''' - set -eu - cd build/libs - for f in eapim-portal.war eapim-portal-boot.war; do - sha1sum "$f" > "$f.sha1" - sha256sum "$f" > "$f.sha256" - md5sum "$f" > "$f.md5" - done - ''' - archiveArtifacts artifacts: 'build/libs/eapim-portal.war,build/libs/eapim-portal-boot.war,build/libs/eapim-portal.war.sha1,build/libs/eapim-portal.war.sha256,build/libs/eapim-portal.war.md5,build/libs/eapim-portal-boot.war.sha1,build/libs/eapim-portal-boot.war.sha256,build/libs/eapim-portal-boot.war.md5', fingerprint: true + stages { + stage('Stop WebLogic') { + steps { + sh '"$WL_HOME/stopDev11.sh"' // 동기: 완전 종료까지 블록, 미기동 시에도 안전 + } } - } - } + stage('Deploy WAR') { + steps { + unstash 'war' + sh ''' + set -eu + cp build/libs/eapim-portal.war "$WL_DEPLOY_DIR/$WL_WAR_NAME" + ls -la "$WL_DEPLOY_DIR" + ''' + } + } + stage('Start WebLogic and readiness') { + steps { + sh ''' + set -eu + "$WL_HOME/startDev11.sh" # nohup & 로 백그라운드 기동, 즉시 리턴 - stage('Stop Tomcat') { - steps { - sh ''' - set +e - systemctl --user stop eapim-portal 2>/dev/null + DEADLINE=$(($(date +%s) + 300)) + STATUS=000 + while [ "$(date +%s)" -lt "$DEADLINE" ]; do + STATUS=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 3 \ + "http://localhost:$WL_HTTP_PORT/health/ready" 2>/dev/null || echo "000") + [ "$STATUS" = "200" ] && { echo "Readiness OK (/health/ready)"; break; } + sleep 3 + done - if [ -f "$CATALINA_PID" ] && kill -0 "$(cat "$CATALINA_PID")" 2>/dev/null; then - JAVA_HOME="$JAVA_HOME_TOMCAT" "$CATALINA_HOME/bin/shutdown.sh" 30 -force || true - for i in $(seq 1 30); do - [ -f "$CATALINA_PID" ] && kill -0 "$(cat "$CATALINA_PID")" 2>/dev/null || break - sleep 1 - done - fi - rm -f "$CATALINA_PID" - ''' - } - } - - stage('Deploy ROOT.war') { - steps { - sh ''' - set -eu - DEPLOY_DIR="$CATALINA_BASE/webapps" - rm -rf "$DEPLOY_DIR/ROOT" "$DEPLOY_DIR/ROOT.war" - cp build/libs/eapim-portal.war "$DEPLOY_DIR/ROOT.war" - ls -la "$DEPLOY_DIR" - ''' - } - } - - stage('Start Tomcat and readiness') { - steps { - sh ''' - set -eu - LOG="$CATALINA_BASE/logs/catalina.$(date +%Y-%m-%d).log" - BEFORE=0 - [ -f "$LOG" ] && BEFORE=$(stat -c %s "$LOG") - - systemctl --user start eapim-portal - - DEADLINE=$(($(date +%s) + 120)) - LIVE_OK=0 - STATUS=000 - - while [ "$(date +%s)" -lt "$DEADLINE" ]; do - if [ "$LIVE_OK" = "0" ]; then - LIVE=$(curl -sS -o /dev/null -w '%{http_code}' --max-time 3 \ - "http://localhost:$DEPLOY_HTTP_PORT/health" 2>/dev/null || echo "000") - if [ "$LIVE" = "200" ]; then - echo "Liveness OK (/health)" - LIVE_OK=1 + if [ "$STATUS" != "200" ]; then + echo "Readiness failed within 300s, last HTTP=$STATUS" + [ -f "$WL_NOHUP" ] && tail -120 "$WL_NOHUP" + exit 1 fi - fi - - if [ "$LIVE_OK" = "1" ]; then - STATUS=$(curl -sS -o /tmp/eapim-ready-body.json -w '%{http_code}' --max-time 3 \ - "http://localhost:$DEPLOY_HTTP_PORT/health/ready" 2>/dev/null || echo "000") - if [ "$STATUS" = "200" ]; then - echo "Readiness OK (/health/ready)" - cat /tmp/eapim-ready-body.json - echo - break - fi - fi - - if [ -f "$LOG" ] && tail -c +$((BEFORE+1)) "$LOG" | grep -qE "Application listener .* Exception|SEVERE.*startup.Catalina"; then - echo "Startup error detected in log" - tail -c +$((BEFORE+1)) "$LOG" | tail -80 - exit 1 - fi - sleep 2 - done - - if [ "$STATUS" != "200" ]; then - echo "Readiness probe failed within 120s, last HTTP status: $STATUS" - [ -f /tmp/eapim-ready-body.json ] && cat /tmp/eapim-ready-body.json && echo - [ -f "$LOG" ] && tail -c +$((BEFORE+1)) "$LOG" | tail -100 - exit 1 - fi - - echo "--- key boot log lines ---" - tail -c +$((BEFORE+1)) "$LOG" | grep -E "Server startup|Deployment of web" | head -10 || true - ''' + ''' + } + } } } } post { success { - sh ''' - set +e - payload=$(printf '{"text":"[%s #%s](%s) SUCCESS","attachments":[{"color":"good","fields":[{"title":"Job","value":"%s","short":true},{"title":"Build","value":"%s","short":true},{"title":"Result","value":"SUCCESS","short":true}]}]}' \ - "$JOB_NAME" "$BUILD_NUMBER" "$BUILD_URL" "$JOB_NAME" "$BUILD_NUMBER") - curl -sS --fail --max-time 5 \ - -H 'Content-Type: application/json' \ - -X POST \ - --data "$payload" \ - "$WEBHOOK_URL" >/dev/null || echo "Webhook delivery failed for SUCCESS" - ''' + node('weblogic') { + sh ''' + set +e + payload=$(printf '{"text":"[%s #%s](%s) SUCCESS"}' "$JOB_NAME" "$BUILD_NUMBER" "$BUILD_URL") + curl -sS --fail --max-time 5 -H 'Content-Type: application/json' -X POST --data "$payload" "$WEBHOOK_URL" >/dev/null || echo "Webhook failed" + ''' + } } failure { - sh ''' - set +e - payload=$(printf '{"text":"[%s #%s](%s) FAILURE","attachments":[{"color":"danger","fields":[{"title":"Job","value":"%s","short":true},{"title":"Build","value":"%s","short":true},{"title":"Result","value":"FAILURE","short":true}]}]}' \ - "$JOB_NAME" "$BUILD_NUMBER" "$BUILD_URL" "$JOB_NAME" "$BUILD_NUMBER") - curl -sS --fail --max-time 5 \ - -H 'Content-Type: application/json' \ - -X POST \ - --data "$payload" \ - "$WEBHOOK_URL" >/dev/null || echo "Webhook delivery failed for FAILURE" - ''' + node('weblogic') { + sh ''' + set +e + payload=$(printf '{"text":"[%s #%s](%s) FAILURE"}' "$JOB_NAME" "$BUILD_NUMBER" "$BUILD_URL") + curl -sS --fail --max-time 5 -H 'Content-Type: application/json' -X POST --data "$payload" "$WEBHOOK_URL" >/dev/null || echo "Webhook failed" + ''' + } } } - }