pipeline { agent { label 'build-agent' // This matches the label you configured } environment { HARBOR_URL = 'harbor.myriadcara.com' // Fixed your URL HARBOR_PROJECT = 'my-todo-app' HARBOR_CREDS = 'harbor-credentials-id' K8S_CREDENTIALS_ID = 'k8s-kubeconfig' IMAGE_TAG = "${env.BUILD_ID}" } stages { stage('Parallel Build & Deploy') { parallel { stage('Backend Service') { environment { SERVICE_NAME = 'todo-backend' DIR = 'backend' FULL_IMAGE_PATH = "${HARBOR_URL}/${HARBOR_PROJECT}/${SERVICE_NAME}:${IMAGE_TAG}" } stages { stage('Backend: Test') { steps { container('node') { dir("${env.DIR}") { sh 'npm install' sh 'npm test || true' } } } } stage('Backend: Push & Deploy') { steps { dir("${env.DIR}") { script { // Build & Push container('docker') { sh "docker build -t ${FULL_IMAGE_PATH} ." withCredentials([usernamePassword(credentialsId: "${HARBOR_CREDS}", usernameVariable: 'USER', passwordVariable: 'PASS')]) { sh "docker login ${HARBOR_URL} -u ${USER} -p ${PASS}" sh "docker push ${FULL_IMAGE_PATH}" } } // K8s Deploy container('kubectl') { sh "sed 's|IMAGE_PATH_PLACEHOLDER|${FULL_IMAGE_PATH}|g' k8s-deployment.yaml > backend-k8s-applied.yaml" sh "kubectl apply -f backend-k8s-applied.yaml" sh "kubectl rollout status deployment/${SERVICE_NAME}" } } } } } } } stage('Frontend Service') { environment { SERVICE_NAME = 'todo-frontend' DIR = 'frontend' FULL_IMAGE_PATH = "${HARBOR_URL}/${HARBOR_PROJECT}/${SERVICE_NAME}:${IMAGE_TAG}" } stages { stage('Frontend: Test') { steps { container('node') { dir("${env.DIR}") { sh 'npm install' sh 'npm test || true' } } } } stage('Frontend: Push & Deploy') { steps { dir("${env.DIR}") { script { // Build & Push container('docker') { sh "docker build -t ${FULL_IMAGE_PATH} ." withCredentials([usernamePassword(credentialsId: "${HARBOR_CREDS}", usernameVariable: 'USER', passwordVariable: 'PASS')]) { sh "docker login ${HARBOR_URL} -u ${USER} -p ${PASS}" sh "docker push ${FULL_IMAGE_PATH}" } } // K8s Deploy container('kubectl') { sh "sed 's|IMAGE_PATH_PLACEHOLDER|${FULL_IMAGE_PATH}|g' k8s-deployment.yaml > frontend-k8s-applied.yaml" sh "kubectl apply -f frontend-k8s-applied.yaml" sh "kubectl rollout status deployment/${SERVICE_NAME}" } } } } } } } } } } post { always { container('docker') { sh "docker logout ${HARBOR_URL} || true" } sh "rm -f backend/backend-k8s-applied.yaml frontend/frontend-k8s-applied.yaml" } } }