def PIPELINE_ID = "${env.BUILD_NUMBER}" def getImageTag() { def dateFormat = new java.text.SimpleDateFormat('yyyyMMddHHmmss') def currentDate = new Date() return dateFormat.format(currentDate) } podTemplate( label: "${PIPELINE_ID}", serviceAccount: 'jenkins', containers: [ containerTemplate(name: 'podman', image: "mgoltzsche/podman", ttyEnabled: true, command: 'cat', privileged: true), containerTemplate(name: 'gradle', image: 'gradle:jdk17', ttyEnabled: true, command: 'cat'), containerTemplate(name: 'azure-cli', image: 'hiondal/azure-kubectl:latest', command: 'cat', ttyEnabled: true) ] ) { node(PIPELINE_ID) { def props def imageTag = getImageTag() def environment = params.ENVIRONMENT ?: 'dev' def services = ['api-gateway', 'user-service', 'bill-service', 'product-service', 'kos-mock'] stage("Get Source") { checkout scm props = readProperties file: "deployment/cicd/config/deploy_env_vars_${environment}" } stage("Setup AKS") { container('azure-cli') { withCredentials([azureServicePrincipal('azure-credentials')]) { sh """ az login --service-principal -u \$AZURE_CLIENT_ID -p \$AZURE_CLIENT_SECRET -t \$AZURE_TENANT_ID az aks get-credentials --resource-group \${props.resource_group} --name \${props.cluster_name} --overwrite-existing kubectl create namespace phonebill-\${environment} --dry-run=client -o yaml | kubectl apply -f - """ } } } stage('Build & SonarQube Analysis') { container('gradle') { withSonarQubeEnv('SonarQube') { sh """ chmod +x gradlew ./gradlew build -x test # 각 서비스별 테스트 및 분석 ./gradlew :api-gateway:test :api-gateway:jacocoTestReport :api-gateway:sonar \\ -Dsonar.projectKey=phonebill-api-gateway-\${environment} \\ -Dsonar.projectName=phonebill-api-gateway ./gradlew :user-service:test :user-service:jacocoTestReport :user-service:sonar \\ -Dsonar.projectKey=phonebill-user-service-\${environment} \\ -Dsonar.projectName=phonebill-user-service ./gradlew :bill-service:test :bill-service:jacocoTestReport :bill-service:sonar \\ -Dsonar.projectKey=phonebill-bill-service-\${environment} \\ -Dsonar.projectName=phonebill-bill-service ./gradlew :product-service:test :product-service:jacocoTestReport :product-service:sonar \\ -Dsonar.projectKey=phonebill-product-service-\${environment} \\ -Dsonar.projectName=phonebill-product-service ./gradlew :kos-mock:test :kos-mock:jacocoTestReport :kos-mock:sonar \\ -Dsonar.projectKey=phonebill-kos-mock-\${environment} \\ -Dsonar.projectName=phonebill-kos-mock """ } } } stage('Quality Gate') { timeout(time: 10, unit: 'MINUTES') { def qg = waitForQualityGate() if (qg.status != 'OK') { error "Pipeline aborted due to quality gate failure: \${qg.status}" } } } stage('Build & Push Images') { container('podman') { withCredentials([usernamePassword( credentialsId: 'acr-credentials', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD' )]) { sh "podman login acrdigitalgarage01.azurecr.io --username \$USERNAME --password \$PASSWORD" services.each { service -> sh """ podman build \\ --build-arg BUILD_LIB_DIR="\${service}/build/libs" \\ --build-arg ARTIFACTORY_FILE="\${service}.jar" \\ -f deployment/container/Dockerfile \\ -t acrdigitalgarage01.azurecr.io/phonebill/\${service}:\${environment}-\${imageTag} . podman push acrdigitalgarage01.azurecr.io/phonebill/\${service}:\${environment}-\${imageTag} """ } } } } stage('Update Kustomize & Deploy') { container('azure-cli') { sh """ # Kustomize 설치 curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash sudo mv kustomize /usr/local/bin/ # 환경별 디렉토리로 이동 cd deployment/cicd/kustomize/overlays/\${environment} # 이미지 태그 업데이트 kustomize edit set image acrdigitalgarage01.azurecr.io/phonebill/api-gateway:\${environment}-\${imageTag} kustomize edit set image acrdigitalgarage01.azurecr.io/phonebill/user-service:\${environment}-\${imageTag} kustomize edit set image acrdigitalgarage01.azurecr.io/phonebill/bill-service:\${environment}-\${imageTag} kustomize edit set image acrdigitalgarage01.azurecr.io/phonebill/product-service:\${environment}-\${imageTag} kustomize edit set image acrdigitalgarage01.azurecr.io/phonebill/kos-mock:\${environment}-\${imageTag} # 매니페스트 적용 kubectl apply -k . echo "Waiting for deployments to be ready..." kubectl -n phonebill-\${environment} wait --for=condition=available deployment/\${environment}-api-gateway --timeout=300s kubectl -n phonebill-\${environment} wait --for=condition=available deployment/\${environment}-user-service --timeout=300s kubectl -n phonebill-\${environment} wait --for=condition=available deployment/\${environment}-bill-service --timeout=300s kubectl -n phonebill-\${environment} wait --for=condition=available deployment/\${environment}-product-service --timeout=300s kubectl -n phonebill-\${environment} wait --for=condition=available deployment/\${environment}-kos-mock --timeout=300s """ } } stage('Health Check') { container('azure-cli') { sh """ echo "🔍 Health Check starting..." # API Gateway Health Check GATEWAY_POD=\$(kubectl get pod -n phonebill-\${environment} -l app=api-gateway -o jsonpath='{.items[0].metadata.name}') kubectl -n phonebill-\${environment} exec \$GATEWAY_POD -- curl -f http://localhost:8080/actuator/health || exit 1 echo "✅ All services are healthy!" """ } } } }