/** * UAT: Checkout -> Maven -> (optional) push images to Harbor -> deploy jar + docker restart. * * Jenkins Job: Pipeline script from SCM * Script Path: docs/jenkins/Jenkinsfile-uat-build-deploy.groovy * * Harbor (153.68): when PUSH_TO_HARBOR=true, push e.g. * 39.105.153.68/alien_cloud/gateway:uat-build- * Production promote jobs use SOURCE_TAG=uat-build-. */ pipeline { agent any options { buildDiscarder(logRotator(numToKeepStr: '15')) timestamps() timeout(time: 90, unit: 'MINUTES') } parameters { string( name: 'GIT_BRANCH', defaultValue: 'uat-20260202', trim: true, description: 'Git branch, must match remote (e.g. uat-20260202)' ) booleanParam(name: 'FORCE_UPDATE', defaultValue: true, description: 'mvn -U') booleanParam(name: 'ALLOW_SNAPSHOTS', defaultValue: true, description: 'allow SNAPSHOT deps') booleanParam( name: 'PUSH_TO_HARBOR', defaultValue: false, description: 'After Maven: docker build + push to 39.105.153.68/alien_cloud (tag uat-build-)' ) choice( name: 'HARBOR_PUSH_SCOPE', choices: ['gateway-only', 'all-java-services'], description: 'Only used when PUSH_TO_HARBOR=true' ) string(name: 'HARBOR_REGISTRY', defaultValue: '39.105.153.68', trim: true) string(name: 'HARBOR_PROJECT', defaultValue: 'alien_cloud', trim: true) } environment { MAVEN_HOME = tool '3.6.3' PATH = "${MAVEN_HOME}/bin:${env.PATH}" GIT_URL = 'http://8.152.195.41:3000/alien/alien_cloud' GIT_CREDENTIALS = 'zhanghaomimapingzheng' HARBOR_CREDENTIALS = 'harbor-robot-alien' UAT_HARBOR_IMAGE_TAG = "uat-build-${env.BUILD_NUMBER}" DOCKERFILE_JAVA = 'docs/jenkins/produ/docker/Dockerfile.java-service' } stages { stage('Checkout') { steps { script { def branch = (params.GIT_BRANCH ?: 'uat-20260202').trim() if (!branch) { error('GIT_BRANCH is required') } env.GIT_BRANCH = branch echo ">>> Checkout branch: ${env.GIT_BRANCH}" git branch: "${env.GIT_BRANCH}", credentialsId: "${env.GIT_CREDENTIALS}", url: "${env.GIT_URL}" sh """ set -e git fetch origin git reset --hard origin/${env.GIT_BRANCH} git log -1 --oneline """ } } } stage('Prepare Maven Settings') { steps { script { writeFile file: 'settings.xml', text: """ repo-mix central Maven Central https://repo.maven.apache.org/maven2 truealways false spring-milestones Spring Milestones https://repo.spring.io/milestone truealways false spring-snapshots Spring Snapshots https://repo.spring.io/snapshot false truealways central https://repo.maven.apache.org/maven2 true false spring-milestones https://repo.spring.io/milestone true false repo-mix """ } } } stage('Maven Build') { steps { script { def updateFlag = params.FORCE_UPDATE ? '-U' : '' retry(2) { sh """ set -e mvn -version unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY ALL_PROXY all_proxy no_proxy NO_PROXY || true export MAVEN_OPTS="-Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true -Dmaven.wagon.http.ssl.ignore.validity.dates=true" rm -rf /root/.m2/repository/org/springframework/cloud/spring-cloud-dependencies/Hoxton.SR1 || true rm -rf /root/.m2/repository/org/springframework/boot/spring-boot-dependencies/2.3.2.RELEASE || true rm -rf ${WORKSPACE}/.m2/repository/org/springframework/cloud/spring-cloud-dependencies/Hoxton.SR1 || true rm -rf ${WORKSPACE}/.m2/repository/org/springframework/boot/spring-boot-dependencies/2.3.2.RELEASE || true mvn clean package -DskipTests -s settings.xml ${updateFlag} -e -Dmaven.repo.local=${WORKSPACE}/.m2/repository """ } } } } stage('Push images to Harbor') { when { expression { return params.PUSH_TO_HARBOR == true } } steps { script { def reg = params.HARBOR_REGISTRY.trim() def proj = params.HARBOR_PROJECT.trim() def tag = env.UAT_HARBOR_IMAGE_TAG def baseImage = "${reg}/${proj}/base/openjdk8-ffmpeg:v1" def dockerfile = env.DOCKERFILE_JAVA def harborServices = [ [module: 'alien-gateway', repo: 'gateway', port: '8000', withLib: false], [module: 'alien-store', repo: 'store', port: '50014', withLib: true], [module: 'alien-second', repo: 'second', port: '50015', withLib: false], [module: 'alien-store-platform', repo: 'store-platform', port: '50016', withLib: false], [module: 'alien-lawyer', repo: 'lawyer', port: '50017', withLib: true], [module: 'alien-job', repo: 'job', port: '50108', withLib: false], [module: 'alien-dining', repo: 'dining', port: '50019', withLib: false], ] if (params.HARBOR_PUSH_SCOPE == 'gateway-only') { harborServices = harborServices.findAll { it.repo == 'gateway' } } withCredentials([usernamePassword( credentialsId: env.HARBOR_CREDENTIALS, usernameVariable: 'HARBOR_USER', passwordVariable: 'HARBOR_PASS', )]) { sh """ set -e echo "\${HARBOR_PASS}" | docker login ${reg} -u "\${HARBOR_USER}" --password-stdin """ harborServices.each { svc -> def jarName = "${svc.module}-1.0.0.jar" def imageRef = "${reg}/${proj}/${svc.repo}:${tag}" sh """ set -e test -f ${WORKSPACE}/${svc.module}/target/${jarName} cd ${WORKSPACE}/${svc.module} rm -rf .jenkins_docker_ctx && mkdir -p .jenkins_docker_ctx/lib cp -f target/${jarName} .jenkins_docker_ctx/${jarName} if [ -d target/lib ]; then cp -rf target/lib/. .jenkins_docker_ctx/lib/ else touch .jenkins_docker_ctx/lib/.keep fi cd .jenkins_docker_ctx docker build -f ${WORKSPACE}/${dockerfile} \\ --build-arg BASE_IMAGE=${baseImage} \\ --build-arg JAR_FILE=${jarName} \\ --build-arg SERVER_PORT=${svc.port} \\ --build-arg WITH_LIB=${svc.withLib} \\ -t ${imageRef} . docker push ${imageRef} echo ">>> pushed ${imageRef}" """ } } echo ">>> Harbor tag for prod promote: SOURCE_TAG=${tag}" } } } stage('Deploy Services') { steps { script { def services = [ 'alien-gateway:gateway-uat', 'alien-job:job-uat', 'alien-lawyer:lawyer-uat', 'alien-second:second-uat', 'alien-store:store-uat', 'alien-dining:dining-uat', 'alien-store-platform:store-platform-uat', ] for (item in services) { def parts = item.split(':') def moduleName = parts[0] def dirName = parts[1] def sourceJar = "${env.WORKSPACE}/${moduleName}/target/${moduleName}-1.0.0.jar" def sourceLib = "${env.WORKSPACE}/${moduleName}/target/lib" def targetDir = "/app_deploy_uat/${dirName}" sh """ set -e echo ">>> Deploy module: ${moduleName}" if [ -f "${sourceJar}" ]; then mkdir -p "${targetDir}" if [ -d "${sourceLib}" ]; then rm -rf "${targetDir}/lib" cp -rf "${sourceLib}" "${targetDir}" fi cp -f "${sourceJar}" "${targetDir}/" if docker ps -a --format '{{.Names}}' | grep -wq "${dirName}"; then docker restart "${dirName}" echo ">>> [${dirName}] restarted" else echo ">>> [${dirName}] container missing, jar copied only" fi else echo ">>> [${dirName}] jar missing, skip" fi """ } } } } } post { always { sh 'rm -f settings.xml || true' } success { script { if (params.PUSH_TO_HARBOR) { echo ">>> Harbor images tagged: ${env.UAT_HARBOR_IMAGE_TAG}" echo ">>> Prod promote: SOURCE_TAG=${env.UAT_HARBOR_IMAGE_TAG}" } } } } }