package com.jdk import com.utils.CommonUtils import com.constants.ConfigConstants import com.utils.ServerParser /** * JDK API 服务类 * 负责加载配置、管理分支和服务配置、设置环境参数 * 适配新的配置文件格式,支持多环境、多服务配置 * * 主要功能: * 1. 加载环境配置和主配置文件 * 2. 解析分支和服务配置 * 3. 设置Jenkins流水线参数 * 4. 提供环境相关的配置获取方法 * * @version 2.0.0 * @since 2025-09-09 */ class ResolverService implements Serializable { // Jenkins流水线脚本对象,用于执行Jenkins相关操作 def script // 主配置文件内容(解析后的YAML数据) def config // 组织名称 def orgName // 环境配置文件内容 def envConfig // 主配置文件路径 def jobConfigFile /** * 服务器解析器实例 * 负责解析服务器引用配置和索引处理 * 类型: ServerParser 自定义服务器解析工具类 */ def serverParser /** * 构造函数 * 初始化服务类实例 * * @param script Jenkins流水线脚本对象,提供echo、error等方法 * @param orgName 组织名称,用于标识项目归属 */ ResolverService(script, orgName) { this.script = script this.orgName = orgName this.config = [:] this.envConfig = [:] // 初始化服务器解析器,用于处理服务器引用和索引 this.serverParser = new ServerParser(script) } /** * 加载所有配置文件 * 按顺序加载环境配置和主配置文件 * * @throws Exception 如果配置文件加载失败 */ void loadConfigurations() { script.echo "🚀 开始加载配置文件..." // 首先加载环境配置文件(.env.yml) loadEnvConfig() // 然后加载主配置文件(根据环境配置中的路径) loadJobConfig() script.echo "✅ 所有配置文件加载完成" } /** * 加载环境配置文件的方法 * 从.jenkins/.env.yml读取环境配置,包含主配置文件路径等基本信息 * * @return 返回当前对象实例,支持链式调用 * @throws Exception 如果文件存在但解析失败 */ def loadEnvConfig() { try { // 环境配置文件相对路径 def envFilePath = '.jenkins/.env.yml' script.echo "📁 环境配置文件路径: ${envFilePath}" if (script.fileExists(envFilePath)) { // 读取并解析YAML格式的环境配置文件 envConfig = script.readYaml(file: envFilePath) // 从环境配置中获取主配置文件路径 jobConfigFile = ".pipeline-files/config-file/" + envConfig.jobConfigFile script.echo "✅ 成功加载环境配置文件" // 打印所有环境配置项(调试用) if (!envConfig.isEmpty()) { script.echo "📋 环境配置内容:" envConfig.each { key, value -> script.echo " ${key}: ${value}" } } } else { script.echo "⚠️ 警告: 未找到环境配置文件 .env.yml,使用默认配置" } } catch (Exception e) { script.echo "⚠️ 警告: .env.yml 文件无效,使用默认配置: ${e.message}" // 不抛出异常,允许继续执行 } return this } /** * 加载主配置文件的方法 * 读取新的配置文件格式,包含common、branchConfig、serviceConfig等部分 * * @return 返回当前对象实例,支持链式调用 * @throws Exception 如果文件不存在或解析失败 */ def loadJobConfig() { try { // 检查主配置文件是否存在 if (!script.fileExists(jobConfigFile)) { script.error("❌ 错误: 配置文件不存在: ${jobConfigFile},请检查文件路径或创建配置文件") } // 读取并解析YAML格式的主配置文件 this.config = script.readYaml(file: jobConfigFile) script.echo "✅ 成功加载主配置文件: ${jobConfigFile}" // 打印配置详情(调试用) printConfigSummary() } catch (Exception e) { script.error("❌ 错误: 加载配置文件失败: ${jobConfigFile}. 错误详情: ${e.message}") } return this } /** * 打印主配置文件的详细内容 * 格式化输出所有配置信息,便于调试和验证 */ def printConfigSummary() { script.echo "=" * 70 script.echo "📊 主配置文件详细内容" script.echo "=" * 70 if (!this.config) { script.echo "⚠️ 配置文件内容为空" return } // 打印通用配置信息 if (this.config.common) { script.echo "🌐 通用配置:" script.echo "-" * 50 script.echo " 部署脚本: ${this.config.common.deployScript ?: '未设置'}" script.echo " 部署路径: ${this.config.common.deployPath ?: '未设置'}" // 打印注册表配置 if (this.config.common.registry) { script.echo " 注册表配置:" this.config.common.registry.each { registryName, registryConfig -> script.echo " ${registryName}: ${registryConfig.registry}" } } script.echo "" } // 打印环境配置信息 if (this.config.common?.profiles) { script.echo "🏭 环境配置 (共 ${this.config.common.profiles.size()} 个环境):" script.echo "-" * 50 this.config.common.profiles.each { envName, envConfig -> script.echo " ${envName.toUpperCase()} 环境:" script.echo " 服务器数量: ${envConfig.servers ? envConfig.servers.size() : 0}" script.echo " 部署策略: ${envConfig.deploymentStrategy ?: 'rolling'}" script.echo " JVM参数: ${envConfig.envVars?.JAVA_OPTS ?: '未设置'}" script.echo " 健康检查: ${envConfig.healthCheckPath ?: '/actuator/health'}" script.echo "" } } // 打印分支构建配置信息 if (this.config.branchConfig) { script.echo "🌿 分支构建配置 (共 ${this.config.branchConfig.size()} 个分支):" script.echo "-" * 50 this.config.branchConfig.each { branchName, branchConfig -> script.echo " ${branchName} 分支:" script.echo " Jenkins代理: ${branchConfig.jenkinsAgent ?: '未设置'}" script.echo " Maven配置集: ${branchConfig.maven?.maven ?: '未设置'}" } } // 打印服务配置信息 if (this.config.serviceConfig) { script.echo "🔧 服务配置 (共 ${this.config.serviceConfig.size()} 个服务):" script.echo "-" * 50 this.config.serviceConfig.each { serviceName, serviceConfig -> script.echo " ${serviceName} 服务:" script.echo " 编程语言: ${serviceConfig.programLang ?: '未设置'}" script.echo " 语言版本: ${serviceConfig.programLangVersion ?: '未设置'}" script.echo " 容器名称: ${serviceConfig.containerName ?: '未设置'}" script.echo " POM路径: ${serviceConfig.pomFilePath ?: '未设置'}" script.echo " 服务路径: ${serviceConfig.servicePath ?: '未设置'}" script.echo " 容器名称: ${serviceConfig.containerName ?: '未设置'}" script.echo " JAR包名称: ${serviceConfig.jarName ?: '未设置'}" script.echo " 服务端口: ${serviceConfig.port ?: '未设置'}" } } script.echo "=" * 70 } /** * 获取当前分支的配置 * 根据当前Jenkins作业的分支名称查找对应的分支配置 * * @return 分支配置对象(Map类型) * @throws Exception 如果分支配置不存在 */ def getBranchConfig() { // 获取当前Jenkins作业的分支名称 def branchName = script.env.BRANCH_NAME if (!branchName) { script.error("❌ 错误: 无法获取分支名称,env.BRANCH_NAME 为空。请检查流水线配置") } script.echo "🌿 正在查找分支配置: ${branchName}" // 检查分支配置是否存在 if (!config.branchConfig || config.branchConfig.isEmpty()) { script.error("❌ 错误: 分支配置列表为空或未定义。请检查配置文件结构") } // 根据分支名称获取配置 def branchConfig = config.branchConfig[branchName] if (branchConfig) { script.echo "✅ 成功匹配分支配置:" script.echo " - Jenkins代理: ${branchConfig.jenkinsAgent ?: '未设置'}" script.echo " - Maven配置集: ${branchConfig.mavenSet ?: '未设置'}" script.echo " - 构建参数: ${branchConfig.buildArgs ?: '默认参数'}" } else { // 构建友好的错误信息,列出所有可用分支 def availableBranches = config.branchConfig.keySet().join(', ') script.error("❌ 错误: 找不到分支 '${branchName}' 的配置。可用分支: ${availableBranches}") } return branchConfig } /** * 获取指定服务的配置信息 * 根据服务名称从serviceConfig中查找对应的服务配置 * * @param serviceName 服务名称,需要与配置文件中serviceConfig的键匹配 * @return 服务配置对象(Map类型) * @throws Exception 如果服务配置不存在 */ def getServiceConfig(serviceName) { if (!serviceName) { script.error("❌ 错误: 服务名称参数不能为空") } script.echo "🔧 正在查找服务配置: ${serviceName}" // 检查服务配置是否存在 if (!config.serviceConfig || config.serviceConfig.isEmpty()) { script.error("❌ 错误: 服务配置列表为空或未定义,请检查配置文件结构") } // 根据服务名称获取配置 def serviceConfig = config.serviceConfig[serviceName] if (serviceConfig) { script.echo "✅ 成功找到服务配置: ${serviceName}" script.echo " - 容器名称: ${serviceConfig.containerName ?: '未设置'}" script.echo " - 服务路径: ${serviceConfig.servicePath ?: '未设置'}" script.echo " - 服务端口: ${serviceConfig.port ?: '未设置'}" script.echo " - JAR包名称: ${serviceConfig.jarName ?: '未设置'}" } else { // 构建友好的错误信息,列出所有可用服务 def availableServices = config.serviceConfig.keySet().join(', ') script.error("❌ 错误: 找不到服务 '${serviceName}' 的配置。可用服务: ${availableServices}") } return serviceConfig } /** * 设置管道参数 * 整合分支配置、服务配置和环境配置,生成完整的流水线参数 * * @return 参数映射表,包含所有必要的部署参数 */ def setupParameters() { script.echo "⚙️ 开始设置管道参数..." // 获取当前分支配置 def branchConfig = getBranchConfig() // 从Jenkins作业名称中提取服务名称 // 格式通常为: "组织名/服务名" 或 "服务名" def serviceName = script.env.JOB_NAME?.tokenize('/')?.get(0) script.echo "📦 服务名称: ${serviceName}" // 获取服务配置 def serviceConfig = getServiceConfig(serviceName) // 根据分支类型获取环境配置 def profiles = getBranchProfiles(branchConfig) script.echo "🌍 环境配置: ${profiles}" // 生成唯一的镜像标签,格式: {环境}-{构建ID} def imageTag = CommonUtils.generateImageTag(script.env.PROFILES, script.env.BUILD_ID) script.echo "自定义镜像标签:${imageTag}" // 构建完整的参数映射表 def params = [ // 构建相关参数 jenkinsAgent : branchConfig.jenkinsAgent, MAVEN_SET : branchConfig.maven?.mavenSet, skipTests : branchConfig.maven?.skipTests, goals : branchConfig.maven?.goals, dockerFile : branchConfig.docker?.dockerFile ?: '.jenkins/Dockerfile', buildOptions : branchConfig.docker?.buildOptions, // 服务相关参数 projectName : serviceConfig.containerName, packageName : serviceConfig?.packageName, servicePath : serviceConfig.servicePath, jarName : serviceConfig.jarName, jarFile : serviceConfig.jarName, jarFilePath : "${serviceConfig.servicePath}/target", port : serviceConfig.port, pomFilePath : serviceConfig.pomFilePath, deployServer : serviceConfig.deployServer, // 环境相关参数 PROFILES : profiles.default_profile, availableProfiles : profiles.available_profiles, imageTags : [imageTag], // Git配置 gitUrl : config.common?.git?.url, gitCredentialsId : config.common?.git?.credentialsId, gitBranch : script.env.BRANCH_NAME, // 钉钉配置 dingTalkCredentialsId: config.common?.dingtalk?.credentialsId, // 其他参数 envConfig : this.envConfig, orgName : this.orgName, branchConfig : branchConfig, serviceConfig : serviceConfig ] // 获取分支环境变量配置 getEnvironmentConfig(params) // 设置容器基础镜像 params.baseImage = "${params.registry}/${params.registryProject}-base/${params.registryImage}" script.echo "基础参数:${params}" // 设置Jenkins参数(仅对标准流水线) setupJenkinsParameters(profiles.available_profiles as List) script.echo "✅ 管道参数设置完成" // 返回参数 return params } /** * 获取指定环境的全部配置参数 * 从通用配置中提取指定环境的所有参数,包括服务器列表、环境变量、部署策略等 * * @param params 参数映射表(会被修改),用于存储提取的配置信息 * @return 包含指定环境全部参数的Map */ def getEnvironmentConfig(params) { try { // 从参数中获取环境名称,如果没有设置则使用默认值"dev" // 使用Elvis操作符 ?: 提供默认值,避免空指针异常 def envName = params.PROFILES ?: "dev" // 将环境名称转换为小写,确保与配置中的key匹配(配置通常使用小写) // 例如:将"DEV"转换为"dev","Prod"转换为"prod" def envKey = envName.toLowerCase() script.echo "🔍 开始获取 ${envKey} 环境的全部配置参数..." // ========================================================================== // 添加通知配置 // ========================================================================== if (config.common?.notification) { params.notification = config.common.notification script.echo "📧 通知配置已加载" } // ========================================================================== // 添加短信配置 - 详细配置信息 // ========================================================================== if (config.common?.sms) { // 确保sms配置存在 params.sms = config.common.sms script.echo "📱 短信服务配置详情:" script.echo " - 服务商: ${params.sms.provider ?: '未设置'}" script.echo " - 凭据ID: ${params.sms.credentialsId ?: '未设置'}" script.echo " - 默认签名: ${params.sms.signName ?: '未设置'}" // 打印所有模板配置 if (params.sms.templates) { script.echo " - 可用模板:" params.sms.templates.each { templateName, templateConfig -> def templateCode = templateConfig.templateCode ?: '未设置' def templateSign = templateConfig.signName ?: params.sms.signName ?: '未设置' script.echo " 📋 ${templateName}: ${templateCode} (签名: ${templateSign})" } } else { script.echo " - 模板: 未配置" } } else { script.echo "📱 短信服务: 未配置" } // ========================================================================== // 添加构建策略配置 // ========================================================================== if (config.common?.buildStrategy) { params.buildStrategy = config.common.buildStrategy script.echo "⚡ 构建策略:" script.echo " - 重试次数: ${params.buildStrategy.retryCount}" script.echo " - 超时时间: ${params.buildStrategy.timeoutMinutes}分钟" script.echo " - 启用缓存: ${params.buildStrategy.enableCaching}" } // 安全地获取环境配置 - 使用Map方式访问 // 使用安全导航操作符 ?. 避免空指针异常: // - config.common?:如果config为null则返回null,不会抛出异常 // - .profiles?:如果common为null则返回null // - ."${envKey}":动态访问指定环境的配置 def envConfig = config.common?.profiles?."${envKey}" if (!envConfig) { def availableProfiles = config?.common?.profiles?.keySet() ?: [] throw new Exception("未找到 ${envKey} 环境的配置,可用环境: ${availableProfiles.join(', ')}") } script.echo "✅ 找到 ${envKey} 环境配置,开始提取参数..." // ========================================================================== // 提取服务器配置 // ========================================================================== // 检查环境配置是否存在且包含服务器列表,并且服务器列表不为空 // envConfig?.servers:安全访问servers属性 // !envConfig.servers.empty:检查servers列表是否非空 if (envConfig?.servers && !envConfig.servers.empty) { // 使用环境配置中的服务器列表更新参数对象 // 将找到的服务器列表赋值给params.servers,供后续部署使用 params.servers = envConfig.servers // 输出日志信息,显示成功找到服务器配置 // 使用表情符号增强可读性,显示服务器数量 script.echo "🖥️ 服务器配置: 共 ${envConfig.servers.size()} 台服务器" // 打印服务器详情(用于调试和验证) // 使用eachWithIndex迭代服务器列表,同时获取索引和服务器对象 envConfig.servers.eachWithIndex { server, index -> // 输出每台服务器的详细信息 // ${index + 1}:显示序号(从1开始) // ${server.serverName}:服务器名称标识 // ${server.serverIP}:${server.serverPort}:服务器的IP地址和端口号 script.echo " ${index + 1}. ${server.serverName} (${server.serverIP}:${server.serverPort})" } } else { // 如果没有找到对应环境的服务器配置或服务器列表为空 // 输出警告信息,提示用户检查配置 script.echo "⚠️ 警告: 未找到 ${envName} 环境的服务器配置" params.servers = [] // 注意:这里没有设置params.servers,调用方需要处理这种情况 // 可能的处理方式:使用默认服务器、终止部署流程或提示用户输入 } // ========================================================================== // 提取目标服务器配置 // ========================================================================== // 解析部署服务器引用,获取目标服务器列表 // 使用ServerParser处理复杂的服务器引用表达式 def targetServers = serverParser.parseTargetServers(params) params.targetServers = targetServers script.echo "🎯 部署目标服务器数量: ${targetServers.size()}" // ========================================================================== // 提取环境变量配置 // ========================================================================== if (envConfig?.envVars && !envConfig.envVars.empty) { params.envVars = envConfig.envVars script.echo "🌡️ 环境变量: 共 ${envConfig.envVars.size()} 个" envConfig.envVars.each { key, value -> script.echo " ${key}=${value}" } } else { script.echo "⚠️ 警告: ${envKey} 环境没有配置环境变量" params.envVars = [:] } // ========================================================================== // 提取部署策略配置 // ========================================================================== if (envConfig?.deploymentStrategy) { params.deploymentStrategy = envConfig.deploymentStrategy script.echo "🎯 部署策略: ${envConfig.deploymentStrategy}" } if (envConfig?.deploymentTimeout) { params.deploymentTimeout = envConfig.deploymentTimeout script.echo "⏱️ 部署超时: ${envConfig.deploymentTimeout} 秒" } if (envConfig?.maxParallel) { params.maxParallel = envConfig.maxParallel script.echo "🔀 最大并行数: ${envConfig.maxParallel}" } if (envConfig?.retryAttempts) { params.retryAttempts = envConfig.retryAttempts script.echo "🔄 重试次数: ${envConfig.retryAttempts}" } if (envConfig?.canaryPercentage) { params.canaryPercentage = envConfig.canaryPercentage script.echo "📊 金丝雀比例: ${envConfig.canaryPercentage}%" } // ========================================================================== // 提取健康检查配置 // ========================================================================== if (envConfig?.healthCheckEnabled) { params.healthCheckEnabled = envConfig.healthCheckEnabled script.echo "❤️ 启用健康检查: ${envConfig.healthCheckEnabled}" } if (envConfig?.healthCheckPath) { params.healthCheckPath = envConfig.healthCheckPath script.echo "❤️ 健康检查路径: ${envConfig.healthCheckPath}" } if (envConfig?.healthCheckTimeout) { params.healthCheckTimeout = envConfig.healthCheckTimeout script.echo "⏱️ 健康检查超时: ${envConfig.healthCheckTimeout} 秒" } if (envConfig?.healthCheckRetries) { params.healthCheckRetries = envConfig.healthCheckRetries script.echo "❤️ 健康检查重试次数: ${envConfig.healthCheckRetries}" } if (envConfig?.healthCheckInterval) { params.healthCheckInterval = envConfig.healthCheckInterval script.echo "🔄 健康检查间隔: ${envConfig.healthCheckInterval} 秒" } if (envConfig?.successThreshold) { params.successThreshold = envConfig.successThreshold script.echo "✅ 成功阈值: ${envConfig.successThreshold} 次" } // ========================================================================== // 提取回滚配置(生产环境特有) // ========================================================================== if (envConfig?.rollbackEnabled != null) { params.rollbackEnabled = envConfig.rollbackEnabled script.echo "↩️ 自动回滚: ${envConfig.rollbackEnabled}" } if (envConfig?.rollbackOnFailure != null) { params.rollbackOnFailure = envConfig.rollbackOnFailure script.echo "❌ 失败时回滚: ${envConfig.rollbackOnFailure}" } if (envConfig?.rollbackTimeout) { params.rollbackTimeout = envConfig.rollbackTimeout script.echo "⏱️ 回滚超时: ${envConfig.rollbackTimeout} 秒" } // // ========================================================================== // // 提取通知配置(生产环境特有) // // ========================================================================== // if (envConfig?.notifications) { // params.notifications = envConfig.notifications // script.echo "📧 通知配置:" // if (envConfig.notifications.slackChannel) { // script.echo " Slack频道: ${envConfig.notifications.slackChannel}" // } // if (envConfig.notifications.email) { // script.echo " 邮件地址: ${envConfig.notifications.email}" // } // if (envConfig.notifications.recipients) { // script.echo " 额外收件人: ${envConfig.notifications.recipients.join(', ')}" // } // script.echo " 通知时机: 开始=${envConfig.notifications.onStart}, 成功=${envConfig.notifications.onSuccess}, 失败=${envConfig.notifications.onFailure}" // } // ========================================================================== // 添加通用配置 // ========================================================================== params.deployScript = config.common?.deployScript params.deployPath = config.common?.deployPath script.echo "📜 部署脚本: ${params.deployScript}" script.echo "📁 部署路径: ${params.deployPath}" // ========================================================================== // 添加镜像仓库配置 // ========================================================================== if (config.common?.registrys) { params.registrys = config.common?.registrys script.echo "🐳 镜像仓库配置:" params.registrys.each { registryName, registryConfig -> script.echo " ${registryName}: ${registryConfig.registry}" } } // ========================================================================== // 添加环境分支镜像仓库配置 // ========================================================================== def registryConfig = config.common?.registrys?."${envConfig.registry}" params.registry = registryConfig?.registry ?: "192.168.10.102:8001" params.registryCredential = registryConfig?.registryCredential ?: "xiaomayi-hub-credentials" params.registryProject = registryConfig?.registryProject ?: "xiaomayi" params.registryImage = registryConfig?.registryImage ?: "jdk:17.0.16-centos8-dos" params.registryType = registryConfig.registryType ?: "harbor" params.imageFullName = "${params.registry}/${params.registryProject}/${params.projectName}" script.echo "✅ ${envKey} 环境全部参数获取完成" // 返回配置 return params } catch (Exception e) { script.echo "❌ 获取环境配置失败: ${e.message}" throw e } } /** * 设置 Jenkins 作业参数 * 为标准流水线作业创建环境选择参数和服务器选择参数 * 根据可用环境配置动态生成下拉选择框,支持环境和服务器的两级选择 * * @param availableProfiles 可用的环境配置列表 * - 类型: List 环境名称列表(如:['dev', 'test', 'prod']) * - 来源: 通常从配置文件中解析得到的环境配置键值 * - 要求: 列表不能为空,且必须与配置文件中的环境名称匹配 * * @note 在多分支流水线中会自动跳过参数设置(因为多分支通常根据分支自动确定环境) * @note 在标准流水线中会创建用户可交互的选择参数 * * @example 生成的参数: * - PROFILES: 环境选择下拉框(dev/test/prod) * - SERVERS: 服务器选择下拉框(根据选择的环境动态显示对应服务器) */ private void setupJenkinsParameters(List availableProfiles) { // 检查可用环境列表是否为空 if (!availableProfiles || availableProfiles.isEmpty()) { script.echo "⚠️ 可用环境配置列表为空,跳过参数设置" return } // 获取当前分支名称,用于判断流水线类型 def branchName = script.env.BRANCH_NAME ?: '' // 判断是否为多分支流水线(分支名通常包含斜杠,如: feature/xxx) boolean isMultibranchPipeline = branchName.contains('/') if (isMultibranchPipeline) { script.echo "🔧 检测到多分支流水线,跳过参数设置(分支: ${branchName})" script.echo "💡 多分支流水线通常根据分支名称自动确定目标环境" return } script.echo "🔧 标准流水线作业,设置部署环境参数" script.echo "📋 可用环境选项: ${availableProfiles.join(', ')}" try { // ========================================================================== // 创建环境选择参数 // ========================================================================== def profileParameter = script.choice( choices: availableProfiles.join('\n'), // 下拉选项,每行一个选择项 description: '请选择要部署的目标环境', // 参数描述,显示在Jenkins界面上 name: 'PROFILES' // 参数名称,后续通过params.PROFILES访问 ) // ========================================================================== // 创建服务器选择参数(动态生成所有环境的服务器选项) // ========================================================================== def allServers = getAllServersForParameters(availableProfiles) def serverChoices = generateServerChoices(allServers) def serverParameter = script.choice( choices: serverChoices.join('\n'), // 服务器下拉选项 description: '请选择要部署的目标服务器(格式:环境-服务器名-IP)', // 参数描述 name: 'SERVERS' // 参数名称 ) // ========================================================================== // 设置Jenkins作业参数 // ========================================================================== script.properties([ script.parameters([ profileParameter, // 环境选择参数 serverParameter // 服务器选择参数 ]) ]) script.echo "✅ 成功设置部署参数:" script.echo " - PROFILES: 环境选择(${availableProfiles.size()} 个选项)" script.echo " - SERVERS: 服务器选择(${serverChoices.size()} 个选项)" } catch (Exception e) { script.echo "⚠️ 设置 Jenkins 参数失败: ${e.message}" script.echo "💡 这可能是因为没有权限修改作业配置,或者参数格式不正确" // 不抛出异常,避免影响后续流程,参数设置失败通常不会阻断部署 } } /** * 获取所有环境的服务器信息用于参数生成 * 从配置文件中提取每个环境的服务器列表,用于构建服务器选择参数 * 自动过滤空字符串和无效的环境名称 * * @param availableProfiles 可用环境列表,可能包含空字符串或无效值 * @return Map 各环境的服务器列表映射(只包含有效环境) */ private Map getAllServersForParameters(List availableProfiles) { def allServers = [:] // 过滤掉空字符串和null值,只处理有效的环境名称 def validProfiles = availableProfiles.findAll { profile -> profile != null && profile.trim() != '' } script.echo "🔍 有效环境列表: ${validProfiles.join(', ')}" script.echo "🗑️ 已过滤空环境: ${availableProfiles.size() - validProfiles.size()} 个" validProfiles.each { profile -> try { // 安全地获取环境配置中的服务器列表 // 使用安全导航操作符避免空指针异常 def envConfig = config?.common?.profiles?."${profile}" if (envConfig?.servers) { allServers[profile] = envConfig.servers script.echo " 📡 ${profile} 环境: ${envConfig.servers.size()} 台服务器" // 可选:输出服务器详情用于调试 envConfig.servers.eachWithIndex { server, index -> script.echo " ${index + 1}. ${server.serverName} (${server.serverIP}:${server.serverPort})" } } else { script.echo " ⚠️ ${profile} 环境: 无服务器配置或服务器列表为空" allServers[profile] = [] } } catch (Exception e) { script.echo " ❌ 获取 ${profile} 环境服务器失败: ${e.message}" script.echo " 🐛 错误详情: ${e.getStackTrace().find { it.contains('getAllServersForParameters') } ?: '未知位置'}" allServers[profile] = [] } } // 检查是否有任何有效环境配置了服务器 def environmentsWithServers = allServers.count { it.value && !it.value.empty } script.echo "📊 统计: ${environmentsWithServers} 个环境配置了服务器,${allServers.size() - environmentsWithServers} 个环境无服务器" return allServers } /** * 生成服务器选择选项 * 创建格式化的服务器选择项,便于用户识别和选择 * * @param allServers 所有环境的服务器映射 * @return List 格式化后的服务器选项列表 */ private List generateServerChoices(Map allServers) { def choices = [] // 添加默认选项 choices.add("auto-自动选择(根据环境默认服务器)") // 为每个环境的每台服务器生成选项 allServers.each { profile, servers -> if (servers && !servers.empty) { servers.each { server -> // 格式化选项:环境-服务器名-IP:端口 def displayName = "${profile}-${server.serverName}-${server.serverIP}:${server.serverPort}" choices.add(displayName) } } else { // 如果某个环境没有服务器,添加提示选项 choices.add("${profile}-无可用服务器") } } return choices } /** * 根据分支配置获取对应的环境配置文件和默认配置文件 * @param branchConfig 分支配置信息,包含分支类型等 * @return Map 包含可用配置列表和默认配置 */ private def getBranchProfiles(branchConfig) { // 获取当前分支名称 def branchName = script.env.BRANCH_NAME ?: '' // 1. 优先从常量配置中获取该分支类型对应的可用配置 def availableProfiles = ConfigConstants.BRANCH_PROFILES[branchName] // 2. 如果常量配置中没有找到,根据分支类型选择不同的默认配置源 if (!availableProfiles) { availableProfiles = (branchName == 'master') ? envConfig.masterProfiles : // master分支使用特殊配置 envConfig.Profiles // 其他分支使用通用配置 } // 确保availableProfiles不为null,如果是null则转为空列表 availableProfiles = availableProfiles ?: [] // 3. 获取默认配置,优先从常量配置中获取 def defaultProfile = ConfigConstants.DEFAULT_PROFILES[branchName] // 4. 如果常量配置中没有默认配置,则从可用配置中选择 if (!defaultProfile) { defaultProfile = availableProfiles.find { it } ? // 查找第一个非空配置 availableProfiles[0] : // 如果都为空则取第一个 null // 如果没有可用配置则返回null } return [ available_profiles: availableProfiles, default_profile : defaultProfile ] } }