// ============================================================================= // Jenkinsfile - Backend API // ERP Suite - Node.js + Express + TypeScript // ============================================================================= pipeline { agent any environment { // Configuración del proyecto PROJECT_NAME = 'erp-construccion-backend' DOCKER_REGISTRY = 'registry.isem.digital' DOCKER_IMAGE = "${DOCKER_REGISTRY}/${PROJECT_NAME}" DOCKER_TAG = "${BUILD_NUMBER}" // Configuración de Kubernetes K8S_NAMESPACE = 'erp-production' K8S_DEPLOYMENT = "${PROJECT_NAME}" // Node.js NODE_ENV = 'production' } options { timeout(time: 30, unit: 'MINUTES') disableConcurrentBuilds() buildDiscarder(logRotator(numToKeepStr: '10')) } stages { stage('Checkout') { steps { checkout scm script { env.GIT_COMMIT_SHORT = sh( script: 'git rev-parse --short HEAD', returnStdout: true ).trim() } } } stage('Install Dependencies') { steps { sh 'npm ci --production=false' } } stage('Lint') { steps { sh 'npm run lint' } } stage('Test') { steps { sh 'npm test -- --coverage --ci' } post { always { junit 'coverage/junit.xml' publishHTML([ allowMissing: false, alwaysLinkToLastBuild: true, keepAll: true, reportDir: 'coverage/lcov-report', reportFiles: 'index.html', reportName: 'Coverage Report' ]) } } } stage('Build') { steps { sh 'npm run build' } } stage('Docker Build') { steps { script { docker.build("${DOCKER_IMAGE}:${DOCKER_TAG}", "--target production .") docker.build("${DOCKER_IMAGE}:latest", "--target production .") } } } stage('Docker Push') { steps { script { docker.withRegistry("https://${DOCKER_REGISTRY}", 'docker-registry-credentials') { docker.image("${DOCKER_IMAGE}:${DOCKER_TAG}").push() docker.image("${DOCKER_IMAGE}:latest").push() } } } } stage('Deploy to Kubernetes') { when { branch 'main' } steps { withKubeConfig([credentialsId: 'k8s-credentials', namespace: "${K8S_NAMESPACE}"]) { sh """ kubectl set image deployment/${K8S_DEPLOYMENT} \ ${K8S_DEPLOYMENT}=${DOCKER_IMAGE}:${DOCKER_TAG} \ -n ${K8S_NAMESPACE} kubectl rollout status deployment/${K8S_DEPLOYMENT} \ -n ${K8S_NAMESPACE} \ --timeout=300s """ } } } } post { success { slackSend( color: 'good', message: "✅ Build #${BUILD_NUMBER} successful: ${PROJECT_NAME} deployed to ${K8S_NAMESPACE}" ) } failure { slackSend( color: 'danger', message: "❌ Build #${BUILD_NUMBER} failed: ${PROJECT_NAME}" ) } always { cleanWs() } } }