diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..61af3de --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,156 @@ +pipeline { + agent any + + environment { + HARBOR_URL = '192.168.108.200:80' + HARBOR_PROJECT = 'vaishnavi-ecommerce' + IMAGE_TAG = "${env.BUILD_NUMBER}" + K8S_CRED_ID = 'k8s-config' + K8S_NAMESPACE = 'vaishnavi-ecommerce' + K8S_OVERLAY = 'k8s' + + APP_NAME = 'ecommerce-frontend' + IMAGE = '192.168.108.200:80/vaishnavi-ecommerce/ecommerce-frontend' + + // SONAR_HOST_URL = 'http://sonarqube.example.com:9000' // ← update this + // SONAR_PROJECT = 'ecommerce-frontend' + } + + options { + buildDiscarder(logRotator(numToKeepStr: '10')) + timeout(time: 30, unit: 'MINUTES') + disableConcurrentBuilds() + } + + stages { + + stage('Checkout') { + steps { + checkout scm + echo "Workspace: ${env.WORKSPACE}" + sh 'ls -la' + } + } + + stage('Test') { + steps { + sh 'npm ci && npm test -- --reporter=verbose 2>&1 || true' + } + } + + // ─── SonarQube stages disabled until credentials are resolved ─── + // stage('SonarQube Analysis') { + // steps { + // withSonarQubeEnv('SonarQube') { + // sh """ + // npx sonar-scanner \ + // -Dsonar.projectKey=${SONAR_PROJECT} \ + // -Dsonar.projectName='eCommerce Frontend' \ + // -Dsonar.sources=src \ + // -Dsonar.host.url=${SONAR_HOST_URL} + // """ + // } + // } + // } + + // stage('Quality Gate') { + // steps { + // timeout(time: 5, unit: 'MINUTES') { + // waitForQualityGate abortPipeline: false + // } + // } + // } + + + stage('Build Image') { + steps { + sh """ + docker build \ + -f Dockerfile \ + -t ${IMAGE}:${IMAGE_TAG} \ + -t ${IMAGE}:latest \ + . + """ + } + } + + stage('Push to Harbor') { + steps { + withCredentials([usernamePassword( + credentialsId: 'harbor-creds', + usernameVariable: 'HARBOR_USER', + passwordVariable: 'HARBOR_PASS' + )]) { + sh """ + echo \$HARBOR_PASS | docker login ${HARBOR_URL} -u \$HARBOR_USER --password-stdin + + docker push ${IMAGE}:${IMAGE_TAG} + docker push ${IMAGE}:latest + """ + } + } + } + + stage('Patch Image Tag') { + steps { + dir("${K8S_OVERLAY}") { + sh """ + kustomize edit set image \ + ecommerce-frontend=${IMAGE}:${IMAGE_TAG} + """ + } + } + } + + stage('Deploy to K8s') { + steps { + withKubeConfig([credentialsId: "${K8S_CRED_ID}"]) { + sh "kubectl apply -k ${K8S_OVERLAY}" + + sh "kubectl rollout status deployment/ecommerce-frontend -n ${K8S_NAMESPACE} --timeout=180s" + + echo "✅ Frontend deployed successfully." + } + } + } + + stage('Smoke Test') { + steps { + withKubeConfig([credentialsId: "${K8S_CRED_ID}"]) { + sh """ + kubectl run smoke-${BUILD_NUMBER} \ + --image=curlimages/curl:latest \ + --restart=Never \ + --rm \ + --attach \ + -n ${K8S_NAMESPACE} \ + -- curl -sf http://ecommerce-frontend:80 \ + && echo "Health check PASSED" \ + || echo "Health check FAILED (non-blocking)" + """ + } + } + } + + stage('Clean Up') { + steps { + sh """ + docker rmi ${IMAGE}:${IMAGE_TAG} || true + docker rmi ${IMAGE}:latest || true + """ + } + } + } + + post { + success { + echo "✅ Build #${env.BUILD_NUMBER} — eCommerce Frontend deployed to namespace '${K8S_NAMESPACE}'" + } + failure { + echo "❌ Pipeline failed. Check stage logs above." + } + always { + sh "docker logout ${HARBOR_URL} || true" + } + } +} \ No newline at end of file