pipeline { agent any environment { REGISTRY_IMAGE = "plesk-agency-portal" IMAGE_LATEST = "${REGISTRY_IMAGE}:latest" IMAGE_BUILD = "${REGISTRY_IMAGE}:build-${BUILD_NUMBER}" } stages { stage('Checkout') { steps { checkout scm } } stage('Install dependencies') { steps { sh 'npm ci' } } // stage('Lint') { // steps { // script { // def hasLint = sh(script: "node -e \"const fs=require('fs');const p=require('./package.json');process.exit(p?.scripts?.lint?0:1)\"", returnStatus: true) // if (hasLint == 0) { // sh 'npm run lint' // } else { // echo 'No lint script configured; skipping lint stage.' // } // } // } // } stage('Build application') { steps { sh 'npm run build' } } stage('Build Docker image') { steps { sh 'docker build -t ${IMAGE_LATEST} -t ${IMAGE_BUILD} .' } } stage('Deploy') { steps { script { if (!env.DEPLOY_SSH_CREDENTIAL_ID) { error 'DEPLOY_SSH_CREDENTIAL_ID is required' } } sshagent(credentials: ["${env.DEPLOY_SSH_CREDENTIAL_ID}"]) { sh ''' set -euo pipefail : "${DEPLOY_SSH_HOST:?Missing DEPLOY_SSH_HOST}" : "${DEPLOY_SSH_USER:?Missing DEPLOY_SSH_USER}" : "${DEPLOY_PATH:?Missing DEPLOY_PATH}" rsync -az \ docker-compose.prod.yml \ scripts/deploy-prod.sh \ scripts/smoke-check.sh \ scripts/rollback-prod.sh \ ${DEPLOY_SSH_USER}@${DEPLOY_SSH_HOST}:${DEPLOY_PATH}/ docker save ${IMAGE_LATEST} ${IMAGE_BUILD} \ | ssh ${DEPLOY_SSH_USER}@${DEPLOY_SSH_HOST} 'docker load' ssh ${DEPLOY_SSH_USER}@${DEPLOY_SSH_HOST} \ "chmod +x ${DEPLOY_PATH}/deploy-prod.sh ${DEPLOY_PATH}/smoke-check.sh ${DEPLOY_PATH}/rollback-prod.sh && APP_IMAGE='${IMAGE_BUILD}' DEPLOY_PATH='${DEPLOY_PATH}' ${DEPLOY_PATH}/deploy-prod.sh" ''' } } } stage('Smoke check') { steps { sh 'chmod +x scripts/smoke-check.sh && scripts/smoke-check.sh ${APP_BASE_URL}' } } } }