diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..60eebd3 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,325 @@ +pipeline { + agent any + + environment { + SSH_CREDENTIALS = 'cloudtopiaa' + REMOTE_SERVER = 'ubuntu@160.187.166.17' + PROJECT_NAME = 'Royal-Enfield-Backend' + DEPLOY_PATH = '/home/ubuntu/Royal-Enfield/Re_Backend' + GIT_CREDENTIALS = 'git-cred' + REPO_URL = 'https://git.tech4biz.wiki/laxmanhalaki/Re_Backend.git' + GIT_BRANCH = 'main' + NPM_PATH = '/home/ubuntu/.nvm/versions/node/v22.21.1/bin/npm' + NODE_PATH = '/home/ubuntu/.nvm/versions/node/v22.21.1/bin/node' + PM2_PATH = '/home/ubuntu/.nvm/versions/node/v22.21.1/bin/pm2' + PM2_APP_NAME = 'royal-enfield-backend' + APP_PORT = '5000' + EMAIL_RECIPIENT = 'laxman.halaki@tech4biz.org' + } + + options { + timeout(time: 20, unit: 'MINUTES') + disableConcurrentBuilds() + timestamps() + buildDiscarder(logRotator(numToKeepStr: '10', daysToKeepStr: '30')) + } + + stages { + stage('Pre-deployment Check') { + steps { + script { + echo "═══════════════════════════════════════════" + echo "🚀 Starting ${PROJECT_NAME} Deployment" + echo "═══════════════════════════════════════════" + echo "Server: ${REMOTE_SERVER}" + echo "Deploy Path: ${DEPLOY_PATH}" + echo "PM2 App: ${PM2_APP_NAME}" + echo "Build #: ${BUILD_NUMBER}" + echo "═══════════════════════════════════════════" + } + } + } + + stage('Pull Latest Code') { + steps { + sshagent(credentials: [SSH_CREDENTIALS]) { + withCredentials([usernamePassword(credentialsId: GIT_CREDENTIALS, usernameVariable: 'GIT_USER', passwordVariable: 'GIT_PASS')]) { + sh """ + ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 ${REMOTE_SERVER} << 'ENDSSH' +set -e + +echo "📦 Git Operations..." + +if [ -d "${DEPLOY_PATH}/.git" ]; then + cd ${DEPLOY_PATH} + + echo "Configuring git..." + git config --global --add safe.directory ${DEPLOY_PATH} + git config credential.helper store + + echo "Fetching updates..." + git fetch https://${GIT_USER}:${GIT_PASS}@git.tech4biz.wiki/laxmanhalaki/Re_Backend.git ${GIT_BRANCH} + + CURRENT_COMMIT=\$(git rev-parse HEAD) + LATEST_COMMIT=\$(git rev-parse FETCH_HEAD) + + if [ "\$CURRENT_COMMIT" = "\$LATEST_COMMIT" ]; then + echo "⚠️ Already up to date. No changes to deploy." + echo "Current: \$CURRENT_COMMIT" + else + echo "Pulling new changes..." + git reset --hard FETCH_HEAD + git clean -fd + echo "✓ Updated from \${CURRENT_COMMIT:0:7} to \${LATEST_COMMIT:0:7}" + fi +else + echo "Cloning repository..." + rm -rf ${DEPLOY_PATH} + mkdir -p /home/ubuntu/Royal-Enfield + cd /home/ubuntu/Royal-Enfield + git clone https://${GIT_USER}:${GIT_PASS}@git.tech4biz.wiki/laxmanhalaki/Re_Backend.git Re_Backend + cd ${DEPLOY_PATH} + git checkout ${GIT_BRANCH} + git config --global --add safe.directory ${DEPLOY_PATH} + echo "✓ Repository cloned successfully" +fi + +cd ${DEPLOY_PATH} +echo "Current commit: \$(git log -1 --oneline)" +ENDSSH + """ + } + } + } + } + + stage('Install Dependencies') { + steps { + sshagent(credentials: [SSH_CREDENTIALS]) { + sh """ + ssh -o StrictHostKeyChecking=no ${REMOTE_SERVER} << 'ENDSSH' +set -e +export PATH="/home/ubuntu/.nvm/versions/node/v22.21.1/bin:\$PATH" +cd ${DEPLOY_PATH} + +echo "🔧 Environment Check..." +echo "Node: \$(${NODE_PATH} -v)" +echo "NPM: \$(${NPM_PATH} -v)" + +echo "" +echo "📥 Installing Dependencies..." +${NPM_PATH} install --prefer-offline --no-audit --progress=false + +echo "" +echo "✅ Dependencies installed successfully!" +ENDSSH + """ + } + } + } + + stage('Build Application') { + steps { + sshagent(credentials: [SSH_CREDENTIALS]) { + sh """ + ssh -o StrictHostKeyChecking=no ${REMOTE_SERVER} << 'ENDSSH' +set -e +export PATH="/home/ubuntu/.nvm/versions/node/v22.21.1/bin:\$PATH" +cd ${DEPLOY_PATH} + +echo "🔨 Building application..." +${NPM_PATH} run build +echo "✅ Build completed successfully!" +ENDSSH + """ + } + } + } + + stage('Stop PM2 Process') { + steps { + sshagent(credentials: [SSH_CREDENTIALS]) { + sh """ + ssh -o StrictHostKeyChecking=no ${REMOTE_SERVER} << 'ENDSSH' +set -e +export PATH="/home/ubuntu/.nvm/versions/node/v22.21.1/bin:\$PATH" + +echo "🛑 Stopping existing PM2 process..." + +if ${PM2_PATH} list | grep -q "${PM2_APP_NAME}"; then + echo "Stopping ${PM2_APP_NAME}..." + ${PM2_PATH} stop ${PM2_APP_NAME} || true + ${PM2_PATH} delete ${PM2_APP_NAME} || true + echo "✓ Process stopped" +else + echo "No existing process found" +fi +ENDSSH + """ + } + } + } + + stage('Start with PM2') { + steps { + sshagent(credentials: [SSH_CREDENTIALS]) { + sh """ + ssh -o StrictHostKeyChecking=no ${REMOTE_SERVER} << 'ENDSSH' +set -e +export PATH="/home/ubuntu/.nvm/versions/node/v22.21.1/bin:\$PATH" +cd ${DEPLOY_PATH} + +echo "🚀 Starting application with PM2..." + +# Start with PM2 +${PM2_PATH} start ${NPM_PATH} --name "${PM2_APP_NAME}" -- start + +echo "" +echo "⏳ Waiting for application to start..." +sleep 5 + +# Save PM2 configuration +${PM2_PATH} save + +# Show PM2 status +echo "" +echo "📊 PM2 Process Status:" +${PM2_PATH} list + +# Show logs (last 20 lines) +echo "" +echo "📝 Application Logs:" +${PM2_PATH} logs ${PM2_APP_NAME} --lines 20 --nostream || true + +echo "" +echo "✅ Application started successfully!" +ENDSSH + """ + } + } + } + + stage('Health Check') { + steps { + sshagent(credentials: [SSH_CREDENTIALS]) { + sh """ + ssh -o StrictHostKeyChecking=no ${REMOTE_SERVER} << 'ENDSSH' +set -e +export PATH="/home/ubuntu/.nvm/versions/node/v22.21.1/bin:\$PATH" + +echo "🔍 Deployment Verification..." + +# Check if PM2 process is running +if ${PM2_PATH} list | grep -q "${PM2_APP_NAME}.*online"; then + echo "✓ PM2 process is running" +else + echo "✗ PM2 process is NOT running!" + ${PM2_PATH} logs ${PM2_APP_NAME} --lines 50 --nostream || true + exit 1 +fi + +# Check if port is listening +echo "" +echo "Checking if port ${APP_PORT} is listening..." +if ss -tuln | grep -q ":${APP_PORT} "; then + echo "✓ Application is listening on port ${APP_PORT}" +else + echo "⚠️ Port ${APP_PORT} not detected (may take a moment to start)" +fi + +# Show process info +echo "" +echo "📊 Process Information:" +${PM2_PATH} info ${PM2_APP_NAME} + +echo "" +echo "═══════════════════════════════════════════" +echo "✅ DEPLOYMENT SUCCESSFUL" +echo "═══════════════════════════════════════════" +ENDSSH + """ + } + } + } + } + + post { + always { + cleanWs() + } + success { + script { + def duration = currentBuild.durationString.replace(' and counting', '') + mail to: "${EMAIL_RECIPIENT}", + subject: "✅ ${PROJECT_NAME} - Deployment Successful #${BUILD_NUMBER}", + body: """ +Deployment completed successfully! + +Project: ${PROJECT_NAME} +Build: #${BUILD_NUMBER} +Duration: ${duration} +Server: ${REMOTE_SERVER} +PM2 App: ${PM2_APP_NAME} +Port: ${APP_PORT} + +Deployed at: ${new Date().format('yyyy-MM-dd HH:mm:ss')} + +Console: ${BUILD_URL}console + +Commands to manage: +- View logs: pm2 logs ${PM2_APP_NAME} +- Restart: pm2 restart ${PM2_APP_NAME} +- Stop: pm2 stop ${PM2_APP_NAME} +""" + } + } + failure { + script { + sshagent(credentials: [SSH_CREDENTIALS]) { + try { + def logs = sh( + script: """ssh -o StrictHostKeyChecking=no ${REMOTE_SERVER} ' + export PATH="/home/ubuntu/.nvm/versions/node/v22.21.1/bin:\$PATH" + ${PM2_PATH} logs ${PM2_APP_NAME} --lines 50 --nostream || echo "No logs available" + '""", + returnStdout: true + ).trim() + + mail to: "${EMAIL_RECIPIENT}", + subject: "❌ ${PROJECT_NAME} - Deployment Failed #${BUILD_NUMBER}", + body: """ +Deployment FAILED! + +Project: ${PROJECT_NAME} +Build: #${BUILD_NUMBER} +Server: ${REMOTE_SERVER} +Failed at: ${new Date().format('yyyy-MM-dd HH:mm:ss')} + +Console Log: ${BUILD_URL}console + +Recent PM2 Logs: +${logs} + +Action required immediately! +""" + } catch (Exception e) { + mail to: "${EMAIL_RECIPIENT}", + subject: "❌ ${PROJECT_NAME} - Deployment Failed #${BUILD_NUMBER}", + body: """ +Deployment FAILED! + +Project: ${PROJECT_NAME} +Build: #${BUILD_NUMBER} +Server: ${REMOTE_SERVER} +Failed at: ${new Date().format('yyyy-MM-dd HH:mm:ss')} + +Console Log: ${BUILD_URL}console + +Could not retrieve PM2 logs. Please check manually. +""" + } + } + } + } + } +} \ No newline at end of file