diff --git a/Jenkinsfile b/Jenkinsfile index 944a67f..5767e80 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -7,13 +7,11 @@ pipeline { IMAGE_TAG = "${env.BUILD_NUMBER}" K8S_CRED_ID = 'k8s-config' - // Full image refs FRONTEND_IMAGE = '192.168.108.200:80/library/scrum-frontend' BACKEND_IMAGE = '192.168.108.200:80/library/scrum-backend' - // Path to the app inside the workspace - APP_DIR = 'scrum-manager' - K8S_OVERLAY = 'scrum-manager/k8s/overlays/on-premise' + // Workspace root IS the project root — no subdirectory needed + K8S_OVERLAY = 'k8s/overlays/on-premise' } options { @@ -24,62 +22,49 @@ pipeline { stages { - // 1. CHECKOUT - stage('Checkout') { steps { checkout scm - echo "Building commit: ${env.GIT_COMMIT?.take(8) ?: 'local'}" + echo "Workspace: ${env.WORKSPACE}" + sh 'ls -la' // quick sanity check — confirm Dockerfile is here } } - // 2. UNIT TESTS (backend + frontend in parallel) - stage('Test') { parallel { stage('Backend Tests') { steps { - dir("${APP_DIR}/server") { - sh ''' - npm ci - npm test -- --reporter=verbose 2>&1 || true - ''' + dir('server') { // server/ relative to workspace root + sh 'npm ci && npm test -- --reporter=verbose 2>&1 || true' } } } stage('Frontend Tests') { steps { - dir("${APP_DIR}") { - sh ''' - npm ci - npm test -- --reporter=verbose 2>&1 || true - ''' - } + // frontend lives at workspace root + sh 'npm ci && npm test -- --reporter=verbose 2>&1 || true' } } } } - // 3. BUILD DOCKER IMAGES (parallel) - stage('Build Images') { parallel { stage('Build Frontend') { steps { - dir("${APP_DIR}") { - sh """ - docker build \ - -f Dockerfile \ - -t ${FRONTEND_IMAGE}:${IMAGE_TAG} \ - -t ${FRONTEND_IMAGE}:latest \ - . - """ - } + // Dockerfile is at workspace root + sh """ + docker build \ + -f Dockerfile \ + -t ${FRONTEND_IMAGE}:${IMAGE_TAG} \ + -t ${FRONTEND_IMAGE}:latest \ + . + """ } } stage('Build Backend') { steps { - dir("${APP_DIR}/server") { + dir('server') { // server/Dockerfile sh """ docker build \ -f Dockerfile \ @@ -93,8 +78,6 @@ pipeline { } } - // 4. PUSH TO HARBOR - stage('Push to Harbor') { steps { withCredentials([usernamePassword( @@ -105,11 +88,9 @@ pipeline { sh """ echo \$HARBOR_PASS | docker login ${HARBOR_URL} -u \$HARBOR_USER --password-stdin - # Frontend docker push ${FRONTEND_IMAGE}:${IMAGE_TAG} docker push ${FRONTEND_IMAGE}:latest - # Backend docker push ${BACKEND_IMAGE}:${IMAGE_TAG} docker push ${BACKEND_IMAGE}:latest """ @@ -117,15 +98,10 @@ pipeline { } } - // 5. PATCH KUSTOMIZE IMAGE TAGS - // (writes the exact build tag into the overlay - // so K8s pulls the right image, not :latest) - stage('Patch Image Tags') { steps { dir("${K8S_OVERLAY}") { sh """ - # Requires kustomize v4+ on the Jenkins agent kustomize edit set image \ scrum-frontend=${FRONTEND_IMAGE}:${IMAGE_TAG} \ scrum-backend=${BACKEND_IMAGE}:${IMAGE_TAG} @@ -134,66 +110,38 @@ pipeline { } } - // 6. DEPLOY TO KUBERNETES - stage('Deploy to K8s') { steps { withKubeConfig([credentialsId: "${K8S_CRED_ID}"]) { - script { - echo "Applying kustomize overlay → scrum-manager namespace" + sh "kubectl apply -k ${K8S_OVERLAY}" - // Apply the full kustomize overlay (namespace, PV, secrets, deployments, ingress) - sh "kubectl apply -k ${K8S_OVERLAY}" + sh "kubectl rollout status deployment/mysql -n scrum-manager --timeout=120s" + sh "kubectl rollout status deployment/backend -n scrum-manager --timeout=120s" + sh "kubectl rollout status deployment/frontend -n scrum-manager --timeout=120s" - // ── Wait for rollouts ────────────────────────────── - echo "Waiting for MySQL..." - sh """ - kubectl rollout status deployment/mysql \ - -n scrum-manager --timeout=120s - """ - - echo "Waiting for Backend..." - sh """ - kubectl rollout status deployment/backend \ - -n scrum-manager --timeout=120s - """ - - echo "Waiting for Frontend..." - sh """ - kubectl rollout status deployment/frontend \ - -n scrum-manager --timeout=120s - """ - - echo "✅ All deployments rolled out successfully." - } + echo "✅ All deployments rolled out." } } } - // 7. SMOKE TEST (quick sanity check via K8s) - stage('Smoke Test') { steps { withKubeConfig([credentialsId: "${K8S_CRED_ID}"]) { sh """ - # Hit the backend health endpoint from inside the cluster - # using a one-shot pod so no NodePort/Ingress dependency - kubectl run smoke-test-${BUILD_NUMBER} \ + kubectl run smoke-${BUILD_NUMBER} \ --image=curlimages/curl:latest \ --restart=Never \ --rm \ --attach \ -n scrum-manager \ -- curl -sf http://backend:3001/api/health \ - && echo "Backend health check PASSED" \ - || echo "Backend health check FAILED (non-blocking)" + && echo "Health check PASSED" \ + || echo "Health check FAILED (non-blocking)" """ } } } - // 8. CLEAN UP LOCAL IMAGES - stage('Clean Up') { steps { sh """ @@ -206,26 +154,26 @@ pipeline { } } - // POST ACTIONS - post { success { - echo """ - ╔══════════════════════════════════════════════╗ - ║ ✅ scrum-manager deployed successfully ║ - ║ Build : #${env.BUILD_NUMBER} ║ - ║ Tag : ${IMAGE_TAG} ║ - ║ URL : http://scrum.local ║ - ╚══════════════════════════════════════════════╝ - """ + echo "✅ Build #${env.BUILD_NUMBER} deployed → http://scrum.local" } failure { - echo "❌ Pipeline failed. Check logs above." - // Optional: add mail/Slack notification here + echo "❌ Pipeline failed. Check stage logs above." } always { - // Make sure we're logged out of Harbor - sh 'docker logout ${HARBOR_URL} || true' + sh "docker logout ${HARBOR_URL} || true" } } -} \ No newline at end of file +} +``` + +**What changed and why:** + +The core fix is that `APP_DIR = 'scrum-manager'` was removed entirely. Your Jenkins job clones the repo and the workspace root lands directly inside the project, giving you this layout: +``` +$WORKSPACE/ +├── Dockerfile ← frontend image +├── server/ +│ └── Dockerfile ← backend image +└── k8s/overlays/... \ No newline at end of file