/** * 开发环境(deve):Checkout -> Maven(按需模块)-> 拷贝 jar -> docker compose 启停 * * Jenkins Job 配置: * - Pipeline script from SCM * - Repository: http://8.152.195.41:3000/alien/alien_cloud * - Script Path: docs/devops/dev/java/Jenkinsfile * - 分支默认 deve(构建参数 GIT_BRANCH 可覆盖) * * 宿主机目录:/deve/java(docker-compose.yml 与 gateway/store/... 子目录) * Jenkins 容器须能访问该路径(建议挂载 /deve/java:/deve/java)及 docker.sock * * 容器名:gateway-dev、store-dev…(compose 内 services 键仍为 gateway、store…) */ def getServiceDefinitions() { return [ [module: 'alien-gateway', dir: 'gateway', composeService: 'gateway', container: 'gateway-dev', withLib: false], [module: 'alien-store', dir: 'store', composeService: 'store', container: 'store-dev', withLib: true], [module: 'alien-second', dir: 'second', composeService: 'second', container: 'second-dev', withLib: false], [module: 'alien-store-platform', dir: 'store-platform', composeService: 'store-platform', container: 'store-platform-dev', withLib: false], [module: 'alien-lawyer', dir: 'lawyer', composeService: 'lawyer', container: 'lawyer-dev', withLib: false], [module: 'alien-job', dir: 'job', composeService: 'job', container: 'job-dev', withLib: false], [module: 'alien-dining', dir: 'dining', composeService: 'dining', container: 'dining-dev', withLib: true], ] } def deployParamName(String composeService) { return 'DEPLOY_' + composeService.replace('-', '_') } def collectSelectedServices(Map buildParams) { def selected = [] getServiceDefinitions().each { svc -> def paramName = deployParamName(svc.composeService) if (buildParams[paramName]) { selected.add(svc) } } return selected } def deployOneService(String workspace, String deployRoot, Map svc) { def sourceJar = "${workspace}/${svc.module}/target/${svc.module}-1.0.0.jar" def sourceLib = "${workspace}/${svc.module}/target/lib" def targetDir = "${deployRoot}/${svc.dir}" sh """ set -e echo ">>> Deploy module: ${svc.module} -> ${targetDir}" if [ ! -f "${sourceJar}" ]; then echo ">>> [${svc.dir}] jar missing, skip copy" exit 0 fi mkdir -p "${targetDir}" if [ "${svc.withLib}" = "true" ] && [ -d "${sourceLib}" ]; then rm -rf "${targetDir}/lib" cp -rf "${sourceLib}" "${targetDir}/lib" fi cp -f "${sourceJar}" "${targetDir}/" echo ">>> [${svc.dir}] jar copied" """ } def composeStop(String deployRoot, List composeServices) { if (composeServices == null || composeServices.isEmpty()) { return } def svcList = composeServices.join(' ') sh """ set -e cd "${deployRoot}" test -f docker-compose.yml echo ">>> docker compose stop ${svcList}" docker compose stop ${svcList} """ } def startOrRestartServices(String deployRoot, List composeServices) { if (composeServices == null || composeServices.isEmpty()) { return } def svcList = composeServices.join(' ') sh """ set -e cd "${deployRoot}" test -f docker-compose.yml echo ">>> docker compose up -d ${svcList}" docker compose up -d ${svcList} echo ">>> docker compose restart ${svcList}" docker compose restart ${svcList} """ } pipeline { agent any options { buildDiscarder(logRotator(numToKeepStr: '2', artifactNumToKeepStr: '2')) disableConcurrentBuilds() timestamps() timeout(time: 60, unit: 'MINUTES') } parameters { string( name: 'GIT_BRANCH', defaultValue: 'deve', trim: true, description: '构建分支,默认 deve,可在「Build with Parameters」中修改' ) booleanParam( name: 'STOP_ALL', defaultValue: false, description: '为 true 时:先停止全部 dev 微服务,再按下方勾选部署;此时 gateway 必须勾选' ) // 多选复选框(Declarative 须逐项声明,不可用 each 动态生成) booleanParam(name: 'DEPLOY_gateway', defaultValue: true, description: 'alien-gateway -> gateway-dev') booleanParam(name: 'DEPLOY_store', defaultValue: true, description: 'alien-store -> store-dev') booleanParam(name: 'DEPLOY_second', defaultValue: true, description: 'alien-second -> second-dev') booleanParam(name: 'DEPLOY_store_platform', defaultValue: false, description: 'alien-store-platform -> store-platform-dev') booleanParam(name: 'DEPLOY_lawyer', defaultValue: false, description: 'alien-lawyer -> lawyer-dev') booleanParam(name: 'DEPLOY_job', defaultValue: false, description: 'alien-job -> job-dev') booleanParam(name: 'DEPLOY_dining', defaultValue: false, description: 'alien-dining -> dining-dev') } 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 = '5e058e17-8089-45e0-a802-596d91758b4d' DEPLOY_ROOT = '/deve/java' MAVEN_LOCAL_REPO = '/var/jenkins_home/.m2/repository' } stages { stage('Validate') { steps { script { def selected = collectSelectedServices(params) if (selected.isEmpty()) { error('请至少勾选一个微服务') } if (params.STOP_ALL && !params.DEPLOY_gateway) { error('STOP_ALL=true 时 gateway 必须勾选') } env.SELECTED_COMPOSE_SERVICES = selected.collect { it.composeService }.join(' ') env.SELECTED_MAVEN_MODULES = selected.collect { it.module }.join(',') echo ">>> Branch: ${params.GIT_BRANCH}" echo ">>> STOP_ALL: ${params.STOP_ALL}" echo ">>> Selected compose services: ${env.SELECTED_COMPOSE_SERVICES}" } } } stage('Checkout') { steps { script { def branch = (params.GIT_BRANCH ?: 'deve').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('Stop All Dev Services') { when { expression { return params.STOP_ALL } } steps { script { def allServices = getServiceDefinitions().collect { it.composeService } composeStop(env.DEPLOY_ROOT, allServices) } } } stage('Maven Build') { steps { sh """ set -e cat > settings.xml <<'EOF' aliyunmaven * Aliyun Maven https://maven.aliyun.com/repository/public EOF echo ">>> Maven modules: ${SELECTED_MAVEN_MODULES}" mvn clean package -DskipTests -s settings.xml -pl ${SELECTED_MAVEN_MODULES} -am """ } } stage('Deploy Services') { steps { script { def selected = collectSelectedServices(params) selected.each { svc -> deployOneService(env.WORKSPACE, env.DEPLOY_ROOT, svc) } } } } stage('Start Dev Services') { steps { script { def selected = collectSelectedServices(params) def composeServices = selected.collect { it.composeService } startOrRestartServices(env.DEPLOY_ROOT, composeServices) } } } } post { always { sh 'rm -f settings.xml || true' echo '>>> 开发环境构建结束' } failure { echo '>>> 构建失败,已部署的 jar 不会自动回滚,请检查日志' } } }