// ============================================================================= // Jenkinsfile - Frontend Web // ERP Suite - React + Vite + TypeScript // ============================================================================= pipeline { agent any environment { // Configuración del proyecto PROJECT_NAME = 'erp-construccion-frontend-web' 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: 20, unit: 'MINUTES') disableConcurrentBuilds() buildDiscarder(logRotator(numToKeepStr: '10')) } stages { stage('Checkout') { steps { checkout scm } } stage('Install Dependencies') { steps { sh 'npm ci' } } stage('Lint') { steps { sh 'npm run lint' } } stage('Type Check') { steps { sh 'npm run type-check' } } stage('Build') { steps { // Inyectar variables de entorno de producción withCredentials([ string(credentialsId: 'api-url-production', variable: 'VITE_API_URL') ]) { sh 'npm run build' } } } stage('Docker Build') { steps { script { docker.build("${DOCKER_IMAGE}:${DOCKER_TAG}", ".") docker.build("${DOCKER_IMAGE}:latest", ".") } } } 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=180s """ } } } stage('Invalidate CDN Cache') { when { branch 'main' } steps { // Ejemplo con CloudFlare withCredentials([ string(credentialsId: 'cloudflare-api-token', variable: 'CF_TOKEN'), string(credentialsId: 'cloudflare-zone-id', variable: 'CF_ZONE') ]) { sh """ curl -X POST "https://api.cloudflare.com/client/v4/zones/${CF_ZONE}/purge_cache" \ -H "Authorization: Bearer ${CF_TOKEN}" \ -H "Content-Type: application/json" \ --data '{"purge_everything":true}' """ } } } } post { success { slackSend( color: 'good', message: "✅ Frontend deployed: ${PROJECT_NAME} v${BUILD_NUMBER}" ) } failure { slackSend( color: 'danger', message: "❌ Frontend build failed: ${PROJECT_NAME}" ) } always { cleanWs() } } }