pipeline { agent { label 'djb-vm' } options { timestamps() disableConcurrentBuilds() buildDiscarder(logRotator(numToKeepStr: '20', artifactNumToKeepStr: '20')) } 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('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/**' } } } stage('Build WAR') { steps { sh 'gradle build -x test --no-daemon' } post { success { sh ''' set -eu cd build/libs sha1sum eapim-portal.war eapim-portal-boot.war > SHA1SUMS sha256sum eapim-portal.war eapim-portal-boot.war > SHA256SUMS ''' archiveArtifacts artifacts: 'build/libs/eapim-portal.war,build/libs/eapim-portal-boot.war,build/libs/SHA1SUMS,build/libs/SHA256SUMS', fingerprint: true } } } stage('Stop Tomcat') { steps { sh ''' set +e systemctl --user stop eapim-portal 2>/dev/null 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 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 '{"job":"%s","build":%s,"result":"%s","url":"%s"}' \ "$JOB_NAME" "$BUILD_NUMBER" "SUCCESS" "$BUILD_URL") 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" ''' } failure { sh ''' set +e payload=$(printf '{"job":"%s","build":%s,"result":"%s","url":"%s"}' \ "$JOB_NAME" "$BUILD_NUMBER" "FAILURE" "$BUILD_URL") 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" ''' } } }