diff --git a/src/com/nexus/DeploymentService.groovy b/src/com/nexus/DeploymentService.groovy new file mode 100644 index 0000000..9181b87 --- /dev/null +++ b/src/com/nexus/DeploymentService.groovy @@ -0,0 +1,149 @@ +package com.nexus + +import com.nexus.stages.BuildService +import com.nexus.stages.DeployService + +/** + * 部署服务类 - CI/CD流水线核心协调器 + * 负责执行各个CI/CD阶段的业务逻辑,不直接创建Jenkins stage + * 提供模块化的构建、部署、验证功能,作为流水线步骤的抽象层 + * + * 设计原则: + * - 单一职责:每个方法只负责一个特定的功能 + * - 错误隔离:每个阶段的异常不会影响其他阶段 + * - 可重用性:方法可以在不同的流水线中重用 + * - 可扩展性:易于添加新的部署阶段或功能 + * - 可维护性:清晰的代码结构和职责分离 + * + * 主要职责: + * 1. 协调各个部署阶段服务的执行 + * 2. 提供统一的参数传递接口 + * 3. 处理阶段间的依赖关系 + * 4. 提供错误处理和回滚机制 + * + * @see Serializable 实现序列化接口,支持Jenkins流水线的暂停和恢复 + */ +class DeploymentService implements Serializable { + + /** + * Jenkins pipeline脚本对象 + * 用于访问Jenkins DSL方法,如sh、echo、error等 + * 类型: Object (通常是Jenkins pipeline的script对象) + */ + def script + + /** + * 环境配置信息 + * 存储环境特定的配置参数,如服务器列表、环境变量等 + * 类型: Map 键值对配置映射 + */ + def envConfig + + // ========================================================================== + // 各个阶段的服务实例(依赖注入) + // ========================================================================== + + /** + * 构建阶段服务实例 + * 负责Maven项目的编译和打包操作 + * 类型: BuildService 专门处理构建逻辑的服务类 + */ + def buildService + + /** + * 部署阶段服务实例 + * 负责将应用部署到目标服务器 + * 类型: DeployService 专门处理部署逻辑的服务类 + */ + def deployService + + /** + * 构造函数 - 初始化部署服务 + * 创建各个阶段的服务实例,建立服务依赖关系 + * + * @param script Jenkins pipeline脚本对象(必须) + * - 用途:用于在各个服务中访问Jenkins DSL方法 + * - 示例:在Pipeline中通过`this`传递当前脚本上下文 + * + * @param envConfig 环境配置信息(可选) + * - 类型:Map 键值对配置映射 + * - 默认值:空Map [:] + * - 内容:服务器列表、环境变量、部署策略等配置 + * - 示例:[ + * servers: [[serverIP: "192.168.1.1", serverPort: 22]], + * envVars: [JAVA_OPTS: "-Xms1g -Xmx1g"], + * deploymentStrategy: "rolling" + * ] + */ + DeploymentService(script, envConfig = [:]) { + // 初始化基础属性 + this.script = script + this.envConfig = envConfig + + // 初始化各个阶段服务(依赖注入模式) + // 通过分离关注点,提高代码的可测试性和可维护性 + this.buildService = new BuildService(script, envConfig) + this.deployService = new DeployService(script, envConfig) + + script.echo "🔧 DeploymentService 初始化完成" + } + + /** + * 执行构建阶段逻辑 + * 委托给BuildService处理Maven项目的编译和打包 + * 这是CI/CD流水线的第一个阶段,负责源代码到产物的转换 + * + * @param params 管道参数Map,包含构建所需的所有配置信息,必须包含: + * - MAVEN_SET: String - Maven设置文件ID + * - PROFILES: String - Maven构建环境profiles + * - jarFilePath: String - JAR文件输出路径 + * - jarFile: String - 生成的JAR文件名 + * - skipTests: Boolean - 是否跳过测试(默认true) + * - goals: String - Maven执行目标(默认"clean package") + * - pomFilePath: String - POM文件路径(默认pom.xml) + * + * @throws Exception 当Maven构建失败时抛出异常,中断流水线 + * + * @example 使用示例: + * def params = [ + * MAVEN_SET: "nexus-maven-dev", + * PROFILES: "dev", + * jarFilePath: "target", + * jarFile: "app.jar" + * ] + * deploymentService.executeBuildStage(params) + */ + def executeBuildStage(params) { + // ☕ 开始构建阶段... + buildService.executeBuildStage(params) + } + + /** + * 执行部署阶段逻辑 + * 委托给DeployService处理应用部署到目标服务器 + * 这是CI/CD流水线的第三个阶段,负责将容器部署到环境 + * + * @param params 管道参数Map,包含部署所需的所有配置信息,必须包含: + * - servers: List - 服务器列表数组 + * - deployServer: String - 部署服务器引用 + * - projectName: String - 项目名称 + * - PROFILES: String - 环境名称 + * 可选字段: + * - deployScript: String - 部署脚本文件名 + * - deployPath: String - 部署脚本路径 + * - envVars: Map - 环境变量配置 + * - deploymentStrategy: String - 部署策略 + * + * @throws Exception 当部署失败时抛出异常,支持自动回滚 + * + * @note 支持多种部署模式: + * - 单服务器部署:deployServer = "servers[0]" + * - 多服务器部署:deployServer = "servers[0,1,2]" + * - 自动选择:deployServer = "auto" + */ + def executeDeployStage(params) { + // 🚀 开始部署阶段... + deployService.executeDeployStage(params) + } + +} \ No newline at end of file diff --git a/src/com/nexus/ResolverService.groovy b/src/com/nexus/ResolverService.groovy new file mode 100644 index 0000000..ba60ac3 --- /dev/null +++ b/src/com/nexus/ResolverService.groovy @@ -0,0 +1,649 @@ +package com.nexus + +import com.utils.CommonUtils +import com.constants.ConfigConstants + +/** + * JDK API 服务类 - 增强Nexus私库上传支持 + * 负责加载配置、管理分支和服务配置、设置环境参数 + * 适配新的配置文件格式,支持多环境、多服务配置和Nexus发布配置 + * + * 主要功能: + * 1. 加载环境配置和主配置文件 + * 2. 解析分支和服务配置 + * 3. 设置Jenkins流水线参数 + * 4. 提供环境相关的配置获取方法 + * 5. 支持Nexus私库上传配置解析 + * + * @version 2.1.0 + * @since 2025-09-09 + */ +class ResolverService implements Serializable { + + // Jenkins流水线脚本对象,用于执行Jenkins相关操作 + def script + + // 主配置文件内容(解析后的YAML数据) + def config + + // 组织名称 + def orgName + + // 环境配置文件内容 + def envConfig + + // 主配置文件路径 + def jobConfigFile + + /** + * 构造函数 + * 初始化服务类实例 + * + * @param script Jenkins流水线脚本对象,提供echo、error等方法 + * @param orgName 组织名称,用于标识项目归属 + */ + ResolverService(script, orgName) { + this.script = script + this.orgName = orgName + this.config = [:] + this.envConfig = [:] + } + + /** + * 加载所有配置文件 + * 按顺序加载环境配置和主配置文件 + * + * @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 + + // Nexus配置 + if (this.config.common.nexus) { + script.echo "🔗 Nexus仓库配置:" + this.config.common.nexus.each { nexusName, nexusConfig -> + script.echo " ${nexusName}: ${nexusConfig.url}" + script.echo " 类型: ${nexusConfig.type}, 策略: ${nexusConfig.policy}" + } + } + + // 构建策略配置 + if (this.config.common.buildStrategy) { + script.echo "⚡ 构建策略:" + script.echo " 重试次数: ${this.config.common.buildStrategy.retryCount}" + script.echo " 超时时间: ${this.config.common.buildStrategy.timeoutMinutes}分钟" + script.echo " 启用缓存: ${this.config.common.buildStrategy.enableCaching}" + } + + // 发布策略配置 + if (this.config.common.publishStrategy) { + script.echo "🚀 发布策略:" + script.echo " 版本策略: ${this.config.common.publishStrategy.versionPolicy}" + script.echo " 自动发布: ${this.config.common.publishStrategy.autoPublish}" + script.echo " 签名构件: ${this.config.common.publishStrategy.signArtifacts}" + } + 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 " Nexus配置: ${envConfig.nexus ?: 'default'}" + script.echo " 版本后缀: ${envConfig.versionSuffix ?: '无'}" + script.echo " 自动部署: ${envConfig.autoDeploy}" + script.echo " 仓库策略: ${envConfig.repositoryPolicy ?: 'releases'}" + 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?.mavenSet ?: '未设置'}" + script.echo " 跳过测试: ${branchConfig.maven?.skipTests ?: 'false'}" + script.echo " Maven目标: ${branchConfig.maven?.goals ?: '未设置'}" + script.echo " 部署操作: ${branchConfig.maven?.deploy ?: 'false'}" + } + } + + // 打印服务配置信息 + 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.projectName ?: '未设置'}" + script.echo " 项目描述: ${serviceConfig.description ?: '未设置'}" + script.echo " 编程语言: ${serviceConfig.programLang ?: '未设置'}" + script.echo " 语言版本: ${serviceConfig.programLangVersion ?: '未设置'}" + script.echo " POM路径: ${serviceConfig.pomFilePath ?: '未设置'}" + script.echo " 服务路径: ${serviceConfig.servicePath ?: '未设置'}" + } + } + + 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.maven?.mavenSet ?: '未设置'}" + script.echo " - Maven目标: ${branchConfig.maven?.goals ?: '未设置'}" + script.echo " - 跳过测试: ${branchConfig.maven?.skipTests ?: 'false'}" + script.echo " - 部署操作: ${branchConfig.maven?.deploy ?: 'false'}" + } 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.projectName ?: '未设置'}" + script.echo " - 项目描述: ${serviceConfig.description ?: '未设置'}" + script.echo " - 编程语言: ${serviceConfig.programLang ?: '未设置'}" + script.echo " - 语言版本: ${serviceConfig.programLangVersion ?: '未设置'}" + script.echo " - POM路径: ${serviceConfig.pomFilePath ?: '未设置'}" + script.echo " - 服务路径: ${serviceConfig.servicePath ?: '未设置'}" + } else { + // 构建友好的错误信息,列出所有可用服务 + def availableServices = config.serviceConfig.keySet().join(', ') + script.error("❌ 错误: 找不到服务 '${serviceName}' 的配置。可用服务: ${availableServices}") + } + + return serviceConfig + } + + /** + * 设置管道参数 + * 整合分支配置、服务配置和环境配置,生成完整的流水线参数 + * 增强对Nexus发布配置的支持 + * + * @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}" + + // 构建完整的参数映射表 + def params = [ + // 构建相关参数 + jenkinsAgent : branchConfig.jenkinsAgent, + MAVEN_SET : branchConfig.maven?.mavenSet, + skipTests : branchConfig.maven?.skipTests, + goals : branchConfig.maven?.goals, + mavenOptions : branchConfig.maven?.options, + + // 服务相关参数 + projectName : serviceConfig.projectName ?: serviceConfig.containerName, + description : serviceConfig.description, + pomFilePath : serviceConfig.pomFilePath, + servicePath : serviceConfig.servicePath, + + // 环境相关参数 + PROFILES : profiles.default_profile, + availableProfiles : profiles.available_profiles, + + // 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) + + script.echo "基础参数:${params}" + + // 设置Jenkins参数(仅对标准流水线) + setupJenkinsParameters(profiles.available_profiles as List) + + script.echo "✅ 管道参数设置完成" + + // 返回参数 + return params + } + + /** + * 获取指定环境的全部配置参数 + * 从通用配置中提取指定环境的所有参数,包括Nexus配置、构建策略等 + * + * @param params 参数映射表(会被修改),用于存储提取的配置信息 + * @return 包含指定环境全部参数的Map + */ + def getEnvironmentConfig(params) { + try { + // 从参数中获取环境名称,如果没有设置则使用默认值"dev" + def envName = params.PROFILES ?: "dev" + def envKey = envName.toLowerCase() + + script.echo "🔍 开始获取 ${envKey} 环境的全部配置参数..." + + // ========================================================================== + // 添加Nexus配置 + // ========================================================================== + if (config.common?.nexus) { + params.nexusConfigs = config.common.nexus + script.echo "🔗 Nexus配置已加载,共 ${config.common.nexus.size()} 个仓库" + + // 设置当前环境使用的Nexus配置 + def envConfig = config.common?.profiles?."${envKey}" + def nexusConfigName = envConfig?.nexus ?: "default" + params.currentNexusConfig = config.common.nexus[nexusConfigName] + + script.echo "📦 当前环境使用Nexus配置: ${nexusConfigName}" + script.echo " - URL: ${params.currentNexusConfig?.url}" + script.echo " - 凭证ID: ${params.currentNexusConfig?.credentialsId}" + script.echo " - 策略: ${params.currentNexusConfig?.policy}" + } + + // ========================================================================== + // 添加通知配置 + // ========================================================================== + if (config.common?.notification) { + params.notification = config.common.notification + 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}" + } + + // ========================================================================== + // 添加发布策略配置 + // ========================================================================== + if (config.common?.publishStrategy) { + params.publishStrategy = config.common.publishStrategy + script.echo "🚀 发布策略:" + script.echo " - 版本策略: ${params.publishStrategy.versionPolicy}" + script.echo " - 自动发布: ${params.publishStrategy.autoPublish}" + script.echo " - 签名构件: ${params.publishStrategy.signArtifacts}" + } + + script.echo "环境变量:${config.common?.profiles}" + + // 安全地获取环境配置 + def envConfig = config.common?.profiles?."${envKey}" + script.echo "环境变量:${envConfig}" + if (!envConfig) { + def availableProfiles = config?.common?.profiles?.keySet() ?: [] + throw new Exception("未找到 ${envKey} 环境的配置,可用环境: ${availableProfiles.join(', ')}") + } + + script.echo "✅ 找到 ${envKey} 环境配置,开始提取参数..." + + // ========================================================================== + // 提取环境特定配置 + // ========================================================================== + if (envConfig?.versionSuffix) { + params.versionSuffix = envConfig.versionSuffix + script.echo "🏷️ 版本后缀: ${envConfig.versionSuffix}" + } + + if (envConfig?.autoDeploy != null) { + params.autoDeploy = envConfig.autoDeploy + script.echo "🚀 自动部署: ${envConfig.autoDeploy}" + } + + if (envConfig?.repositoryPolicy) { + params.repositoryPolicy = envConfig.repositoryPolicy + script.echo "📦 仓库策略: ${envConfig.repositoryPolicy}" + } + + script.echo "✅ ${envKey} 环境全部参数获取完成" + + return params + } catch (Exception e) { + script.echo "❌ 获取环境配置失败: ${e.message}" + throw e + } + } + + /** + * 获取Nexus配置信息 + * 专门用于获取Nexus仓库配置,支持按环境选择不同的Nexus配置 + * + * @param envName 环境名称 + * @param nexusConfigName Nexus配置名称(可选,默认使用环境配置中的设置) + * @return Nexus配置对象 + */ + def getNexusConfig(String envName = null, String nexusConfigName = null) { + try { + def envKey = (envName ?: params.PROFILES ?: "dev").toLowerCase() + def configName = nexusConfigName ?: config.common?.profiles?."${envKey}"?.nexus ?: "default" + + def nexusConfig = config.common?.nexus?."${configName}" + if (!nexusConfig) { + script.echo "⚠️ 警告: 未找到Nexus配置 '${configName}',使用默认配置" + nexusConfig = config.common?.nexus?.default ?: [:] + } + + script.echo "🔗 Nexus配置 [${configName}] for ${envKey} 环境:" + script.echo " - URL: ${nexusConfig.url}" + script.echo " - Snapshots URL: ${nexusConfig.snapshotsUrl}" + script.echo " - 凭证ID: ${nexusConfig.credentialsId}" + + return nexusConfig + } catch (Exception e) { + script.echo "❌ 获取Nexus配置失败: ${e.message}" + return [:] + } + } + + /** + * 获取构建策略配置 + * @return 构建策略配置对象 + */ + def getBuildStrategy() { + return config.common?.buildStrategy ?: [:] + } + + /** + * 获取发布策略配置 + * @return 发布策略配置对象 + */ + def getPublishStrategy() { + return config.common?.publishStrategy ?: [:] + } + + /** + * 获取通知配置 + * @return 通知配置对象 + */ + def getNotificationConfig() { + return config.common?.notification ?: [:] + } + + /** + * 设置 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访问 + ) + + // ========================================================================== + // 设置Jenkins作业参数 + // ========================================================================== + script.properties([ + script.parameters([ + profileParameter, // 环境选择参数 + ]) + ]) + + script.echo "✅ 成功设置部署参数:" + script.echo " - PROFILES: 环境选择(${availableProfiles.size()} 个选项)" + + } catch (Exception e) { + script.echo "⚠️ 设置 Jenkins 参数失败: ${e.message}" + script.echo "💡 这可能是因为没有权限修改作业配置,或者参数格式不正确" + // 不抛出异常,避免影响后续流程,参数设置失败通常不会阻断部署 + } + } + + /** + * 根据分支配置获取对应的环境配置文件和默认配置文件 + * @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 + ] + } + +} \ No newline at end of file diff --git a/src/com/nexus/stages/BuildService copy.groovy b/src/com/nexus/stages/BuildService copy.groovy new file mode 100644 index 0000000..ac12bf0 --- /dev/null +++ b/src/com/nexus/stages/BuildService copy.groovy @@ -0,0 +1,396 @@ +package com.nexus.stages + +/** + * 构建阶段服务 - 负责Maven项目的编译和打包,支持Nexus私库发布 + * + * 主要职责: + * - 执行Maven项目的清理、编译、打包、部署操作 + * - 验证构建环境和配置的有效性 + * - 处理构建过程中的异常和错误 + * - 提供构建结果的状态反馈 + * - 支持Nexus私库发布和依赖管理 + * + * 设计原则: + * - 单一职责:专注于Maven构建相关的逻辑 + * - 可重用性:可以在不同的流水线项目中重用 + * - 错误隔离:构建失败不会影响其他服务实例 + * - 配置驱动:通过参数Map接收所有配置信息 + * + * @see Serializable 实现序列化接口,支持Jenkins流水线的暂停和恢复 + */ +class BuildService implements Serializable { + + /** + * Jenkins pipeline脚本对象 + * 用于访问Jenkins DSL方法,如sh、echo、error等 + * 类型: Object (通常是Jenkins pipeline的script对象) + */ + def script + + /** + * 环境配置信息 + * 存储构建环境特定的配置参数 + * 类型: Map 键值对配置映射 + */ + def envConfig + + /** + * 构造函数 - 初始化构建服务 + * + * @param script Jenkins pipeline脚本对象(必须) + * - 用途:用于在服务中访问Jenkins DSL方法 + * - 示例:在Pipeline中通过`this`传递当前脚本上下文 + * + * @param envConfig 环境配置信息(可选) + * - 类型:Map 键值对配置映射 + * - 默认值:空Map [:] + * - 内容:构建环境相关的配置参数 + */ + BuildService(script, envConfig = [:]) { + this.script = script + this.envConfig = envConfig + + script.echo "🔧 BuildService 初始化完成" + } + + /** + * 执行构建阶段逻辑 - 增强版,支持Nexus私库发布 + * 负责Maven项目的完整构建生命周期,包括清理、编译、测试、打包、部署 + * + * 主要步骤: + * 1. 输出构建开始信息和配置详情 + * 2. 验证环境配置的有效性 + * 3. 执行Maven构建命令(包含依赖清理和Nexus部署) + * 4. 处理构建结果和异常 + * 5. 生成构建报告 + * + * @param params 管道参数Map,包含构建所需的所有配置信息,必须包含: + * - MAVEN_SET: String - Maven设置文件ID(Jenkins Config File ID) + * - PROFILES: String - Maven构建环境profiles(如:dev, test, prod) + * 可选字段: + * - jarFilePath: String - JAR文件输出路径(默认:target) + * - jarFile: String - 生成的JAR文件名 + * - skipTests: Boolean - 是否跳过测试(默认:true) + * - goals: String - Maven执行目标 + * - pomFilePath: String - POM文件路径(默认:pom.xml) + * - orgName: String - 组织名称(用于JDK服务验证) + * - availableProfiles: List - 可用的环境profile列表 + * - branchConfig: Map - 分支配置信息 + * - currentNexusConfig: Map - 当前Nexus配置 + * - repositoryPolicy: String - 仓库策略 + * - publishStrategy: Map - 发布策略配置 + * + * @throws Exception 当Maven构建失败时抛出异常,中断流水线 + * 异常信息包含详细的错误原因和建议解决方案 + * + * @example 使用示例: + * def buildParams = [ + * MAVEN_SET: "nexus-maven-dev", + * PROFILES: "dev", + * jarFilePath: "target", + * jarFile: "xiaomayi-common.jar", + * skipTests: true, + * orgName: "xiaomayi", + * availableProfiles: ["dev", "test", "prod"], + * branchConfig: [maven: [deploy: true]], + * currentNexusConfig: [url: "http://nexus/repository/maven-snapshots/"], + * repositoryPolicy: "snapshots" + * ] + * buildService.executeBuildStage(buildParams) + */ + def executeBuildStage(params) { + try { + // 输出构建开始信息和配置详情 + script.echo "🏗️ 开始构建阶段..." + + printBuildConfiguration(params) + + // 验证环境profile的有效性(确保配置的一致性) + validateProfile(params) + + // 执行Maven构建命令 + executeMavenBuild(params) + + // 构建成功完成,生成报告 + generateBuildReport(params) + + } catch (Exception e) { + // 构建失败处理 + handleBuildFailure(e, params) + // 重新抛出异常,确保流水线标记为失败状态 + throw e + } + } + + /** + * 打印构建配置详情 + * 显示所有构建相关的配置信息,便于调试和验证 + * + * @param params 构建参数Map + */ + private def printBuildConfiguration(params) { + script.echo "📋 构建配置详情:" + script.echo " 🔧 Maven配置: ${params.MAVEN_SET}" + script.echo " 🌍 构建Profile: ${params.PROFILES}" + script.echo " 📦 输出路径: ${params.jarFilePath ?: 'target'}" + script.echo " 🏷️ JAR文件: ${params.jarFile ?: '未指定'}" + script.echo " ⚡ 跳过测试: ${params.skipTests ?: true}" + script.echo " 📄 POM文件: ${params.pomFilePath ?: 'pom.xml'}" + + // 显示Nexus相关配置 + if (params.currentNexusConfig) { + script.echo " 🔗 Nexus仓库: ${params.currentNexusConfig.url}" + script.echo " 🎯 仓库策略: ${params.repositoryPolicy ?: 'releases'}" + } + + // 显示发布策略 + if (params.publishStrategy) { + script.echo " 🚀 自动发布: ${params.publishStrategy.autoPublish ?: 'false'}" + script.echo " 🔏 GPG签名: ${params.publishStrategy.signArtifacts ?: 'false'}" + } + } + + /** + * 执行Maven构建命令 + * 使用Config File Provider动态加载Maven配置,执行完整的构建生命周期 + * + * @param params 构建参数Map + */ + private def executeMavenBuild(params) { + script.echo "🔨 执行Maven构建命令..." + + // 使用Config File Provider加载Maven settings.xml + script.configFileProvider([script.configFile(fileId: params.MAVEN_SET, variable: 'MAVEN_SETTINGS_XML')]) { + + // 构建Maven命令参数 + def mavenGoals = buildMavenGoals(params) + def mavenOptions = buildMavenOptions(params) + + script.sh """ + # ================================================ + # 小蚂蚁核心库Maven构建脚本 + # 环境: ${params.PROFILES} + # 时间: \$(date) + # ================================================ + + echo "🚀 开始执行Maven构建..." + + # 显示Maven版本信息 + /usr/local/maven/bin/mvn --version + + # 显示当前工作目录和POM文件 + echo "📁 工作目录: \$(pwd)" + echo "📄 POM文件: ${params.pomFilePath ?: 'pom.xml'}" + echo "🔧 Settings文件: \${MAVEN_SETTINGS_XML}" + + # 执行Maven构建命令 + echo "🔨 执行命令: /usr/local/maven/bin/mvn --settings \${MAVEN_SETTINGS_XML} ${mavenGoals} ${mavenOptions}" + + /usr/local/maven/bin/mvn \\ + --settings \${MAVEN_SETTINGS_XML} \\ + -f ${params.pomFilePath ?: 'pom.xml'} \\ + ${mavenGoals} ${mavenOptions} + + # 检查构建结果 + BUILD_RESULT=\$? + if [ \$BUILD_RESULT -eq 0 ]; then + echo "✅ Maven构建成功完成!" + else + echo "❌ Maven构建失败,退出码: \$BUILD_RESULT" + exit \$BUILD_RESULT + fi + """ + } + } + + /** + * 构建Maven执行目标 + * 根据参数配置生成合适的Maven goals + * + * @param params 构建参数Map + * @return Maven goals字符串 + */ + private def buildMavenGoals(params) { + def goals = [] + + // 添加依赖清理(针对小蚂蚁依赖) + goals.add("dependency:purge-local-repository -Dinclude=com.xiaomayi") + + // 添加标准构建生命周期 + goals.add("clean") + + // 根据分支配置决定是否部署 + if (params.branchConfig?.maven?.deploy) { + goals.add("deploy") + script.echo " 🚀 启用部署到Nexus仓库" + } else { + goals.add("install") + script.echo " 💾 仅安装到本地仓库" + } + + goals.add("package") + + return goals.join(" ") + } + + /** + * 构建Maven选项参数 + * 根据配置生成Maven命令行选项 + * + * @param params 构建参数Map + * @return Maven选项字符串 + */ + private def buildMavenOptions(params) { + def options = [] + + // 强制更新依赖 + options.add("-U") + + // 跳过测试配置 + if (params.skipTests ?: true) { + options.add("-Dmaven.test.skip=true") + script.echo " ⚡ 跳过单元测试" + } else { + script.echo " ✅ 执行单元测试" + } + + // 添加Maven profile(如果指定) + if (params.PROFILES) { + options.add("-P${params.PROFILES}") + } + + // 添加分支配置中的额外选项 + if (params.branchConfig?.maven?.options) { + options.add(params.branchConfig.maven.options) + } + + return options.join(" ") + } + + /** + * 生成构建报告 + * 构建成功后生成详细的构建结果报告 + * + * @param params 构建参数Map + */ + private def generateBuildReport(params) { + script.echo "📊 构建阶段完成报告:" + script.echo " - ✅ 依赖清理完成(com.xiaomayi)" + script.echo " - ✅ 代码编译完成" + script.echo " - ${params.skipTests ? '⚡ 单元测试跳过' : '✅ 单元测试通过'}" + script.echo " - ✅ 打包完成" + + // 显示部署状态 + def deployStatus = params.branchConfig?.maven?.deploy ? "已部署到Nexus" : "未部署" + script.echo " - 📦 部署状态: ${deployStatus}" + + if (params.branchConfig?.maven?.deploy) { + script.echo " 🎯 目标仓库: ${params.currentNexusConfig?.url ?: '默认仓库'}" + script.echo " 📋 仓库策略: ${params.repositoryPolicy ?: 'releases'}" + } + + // 显示GPG签名状态 + if (params.publishStrategy?.signArtifacts) { + script.echo " - 🔏 GPG签名: 已启用(密钥: ${params.publishStrategy.gpgKeyId ?: '默认密钥'})" + } + + // 显示生成的构件信息 + script.echo "🎉 构建产物已生成到: ${params.jarFilePath ?: 'target'} 目录" + + // 尝试列出生成的JAR文件 + try { + def jarFiles = script.findFiles(glob: "${params.jarFilePath ?: 'target'}/*.jar") + if (jarFiles) { + script.echo "📦 生成的构件:" + jarFiles.each { file -> + script.echo " - ${file.name} (${file.length()} bytes)" + } + } + } catch (Exception e) { + script.echo " ℹ️ 无法列出构件文件: ${e.message}" + } + } + + /** + * 处理构建失败情况 + * 提供详细的错误信息和调试建议 + * + * @param e 异常对象 + * @param params 构建参数Map + */ + private def handleBuildFailure(Exception e, params) { + script.echo "❌ 构建阶段失败: ${e.message}" + script.echo "💡 建议检查:" + script.echo " - Maven settings.xml 配置是否正确" + script.echo " - Nexus仓库连接是否正常(地址: ${params.currentNexusConfig?.url ?: '未配置'})" + script.echo " - 网络连接是否正常(依赖下载)" + script.echo " - 代码编译是否有语法错误" + script.echo " - 单元测试是否通过" + script.echo " - 版本号冲突或依赖问题" + + // 显示当前环境信息用于调试 + script.echo "🔍 调试信息:" + script.echo " - 环境: ${params.PROFILES}" + script.echo " - Maven配置: ${params.MAVEN_SET}" + script.echo " - POM文件: ${params.pomFilePath ?: 'pom.xml'}" + } + + /** + * 验证环境profile有效性 + * 检查选择的部署环境是否在可用环境列表中,确保部署配置的正确性 + * + * 主要功能: + * - 验证必要参数的存在性和有效性 + * - 检查所选环境是否在可用环境列表中 + * - 提供详细的错误信息和调试建议 + * + * @param params 参数Map,必须包含以下字段: + * - PROFILES: String - 要验证的环境profile名称 + * - availableProfiles: List - 可用的环境profile列表 + * - orgName: String - 组织名称(用于日志和错误消息) + * + * @throws IllegalArgumentException 当缺少必要参数或参数无效时抛出 + * @throws Exception 当环境验证失败时抛出,包含详细的错误信息 + */ + private def validateProfile(params) { + script.echo "🔍 开始验证环境profile有效性..." + + // 参数完整性检查 + if (!params.PROFILES) { + def errorMsg = "缺少必要的PROFILES参数,请指定要部署的环境" + script.echo "❌ ${errorMsg}" + throw new IllegalArgumentException(errorMsg) + } + + if (!params.availableProfiles || params.availableProfiles.isEmpty()) { + def errorMsg = "缺少可用的环境profile列表,请检查配置文件中环境配置" + script.echo "❌ ${errorMsg}" + throw new IllegalArgumentException(errorMsg) + } + + if (!params.orgName) { + script.echo "⚠️ 缺少组织名称参数orgName,使用默认标识" + } + + // 环境有效性验证 + try { + def selectedProfile = params.PROFILES.trim() + def availableProfiles = params.availableProfiles.collect { it.toString().trim() } + + script.echo "📋 验证详情:" + script.echo " 🎯 选择的环境: ${selectedProfile}" + script.echo " 📊 可用环境: ${availableProfiles.join(', ')}" + + if (!availableProfiles.contains(selectedProfile)) { + def errorMsg = "无效的部署环境: '${selectedProfile}'。可用环境: ${availableProfiles.join(', ')}" + script.error("环境验证失败: ${errorMsg}") + } + + script.echo "✅ 环境profile验证通过: ${selectedProfile}" + } catch (Exception e) { + script.echo "❌ 环境profile验证过程中发生错误: ${e.message}" + script.echo "📋 可用环境列表: ${params.availableProfiles.join(', ')}" + throw e + } + } +} \ No newline at end of file diff --git a/src/com/nexus/stages/BuildService.groovy b/src/com/nexus/stages/BuildService.groovy new file mode 100644 index 0000000..eb8eb89 --- /dev/null +++ b/src/com/nexus/stages/BuildService.groovy @@ -0,0 +1,375 @@ +package com.nexus.stages + +/** + * 构建服务 - 负责Maven项目的编译、测试、打包和本地安装 + * 专注于构建生命周期,不包含部署逻辑 + * + * 主要职责: + * - 执行Maven项目的清理、编译、测试、打包 + * - 将构件安装到本地Maven仓库 + * - 验证构建环境和配置的有效性 + * - 处理构建过程中的异常和错误 + * - 提供构建结果的状态反馈 + * + * 设计原则: + * - 单一职责:专注于代码构建和本地安装 + * - 可重用性:可以在不同的流水线项目中重用 + * - 错误隔离:构建失败不会影响部署服务 + * - 配置驱动:通过参数Map接收所有配置信息 + * + * @see Serializable 实现序列化接口,支持Jenkins流水线的暂停和恢复 + */ +class BuildService implements Serializable { + + /** + * Jenkins pipeline脚本对象 + */ + def script + + /** + * 环境配置信息 + */ + def envConfig + + /** + * 构造函数 - 初始化构建服务 + * + * @param script Jenkins pipeline脚本对象 + * @param envConfig 环境配置信息(可选) + */ + BuildService(script, envConfig = [:]) { + this.script = script + this.envConfig = envConfig + + script.echo "🔧 BuildService 初始化完成(纯构建版本)" + } + + /** + * 执行构建阶段逻辑 + * 负责Maven项目的编译、测试、打包和本地安装 + * + * 主要步骤: + * 1. 输出构建开始信息和配置详情 + * 2. 验证环境配置的有效性 + * 3. 执行Maven install步骤 + * 4. 处理构建结果和异常 + * 5. 生成构建报告 + * + * @param params 管道参数Map,包含构建所需的所有配置信息 + * @return 构建结果信息,包含构建状态和产物信息 + * @throws Exception 当Maven构建失败时抛出异常,中断流水线 + */ + def executeBuildStage(params) { + def buildResult = [:] + + try { + // 输出构建开始信息和配置详情 + script.echo "🏗️ 开始构建阶段..." + printBuildConfiguration(params) + + // 验证环境profile的有效性 + validateProfile(params) + + // 执行Maven install(构建和本地安装) + buildResult = executeMavenInstall(params) + + // 构建成功完成,生成报告 + generateBuildReport(params, buildResult) + + return buildResult + + } catch (Exception e) { + // 构建失败处理 + handleBuildFailure(e, params) + // 重新抛出异常,确保流水线标记为失败状态 + throw e + } + } + + /** + * 执行Maven install步骤 + * 负责代码编译、测试、打包和本地安装 + * + * @param params 构建参数Map + * @return 构建结果信息 + */ + private def executeMavenInstall(params) { + script.echo "📦 开始执行Maven install步骤..." + + def buildResult = [ + success: false, + artifacts: [], + installTime: new Date().format('yyyy-MM-dd HH:mm:ss'), + profile: params.PROFILES + ] + + // 使用Config File Provider加载Maven settings.xml + script.configFileProvider([script.configFile(fileId: params.MAVEN_SET, variable: 'MAVEN_SETTINGS_XML')]) { + + def installGoals = buildInstallGoals(params) + def installOptions = buildInstallOptions(params) + + def installOutput = script.sh( + script: """ + # ================================================ + # Maven Install 步骤 - 编译和本地安装 + # 环境: ${params.PROFILES} + # 时间: \$(date) + # ================================================ + + echo "🚀 开始Maven install操作..." + + # 显示构建信息 + echo "📁 工作目录: \$(pwd)" + echo "📄 POM文件: ${params.pomFilePath ?: 'pom.xml'}" + echo "🔧 Settings文件: \${MAVEN_SETTINGS_XML}" + echo "🎯 操作目标: 本地安装 (install)" + + # 执行install命令 + echo "🔨 执行命令: /usr/local/maven/bin/mvn --settings \${MAVEN_SETTINGS_XML} ${installGoals} ${installOptions}" + + /usr/local/maven/bin/mvn \\ + --settings \${MAVEN_SETTINGS_XML} \\ + -f ${params.pomFilePath ?: 'pom.xml'} \\ + ${installGoals} ${installOptions} + """, + returnStatus: true + ) + + // 处理构建结果 + buildResult.success = (installOutput == 0) + buildResult.exitCode = installOutput + + if (buildResult.success) { + script.echo "✅ Maven install 成功完成!" + + // 收集生成的构件信息 + buildResult.artifacts = collectArtifacts(params) + buildResult.localRepositoryPath = getLocalRepositoryPath() + + } else { + script.echo "❌ Maven install 失败,退出码: ${installOutput}" + throw new Exception("Maven构建失败,退出码: ${installOutput}") + } + } + + return buildResult + } + + /** + * 构建install步骤的Maven目标 + * + * @param params 构建参数Map + * @return Maven goals字符串 + */ + private def buildInstallGoals(params) { + def goals = [] + + // 添加依赖清理(针对小蚂蚁依赖) + goals.add("dependency:purge-local-repository -Dinclude=com.xiaomayi") + + // 添加标准构建生命周期 + goals.add("clean") + goals.add("install") // 本地安装,包含package阶段 + + script.echo " 🔧 Install步骤Goals: ${goals.join(' ')}" + return goals.join(" ") + } + + /** + * 构建install步骤的Maven选项 + * + * @param params 构建参数Map + * @return Maven选项字符串 + */ + private def buildInstallOptions(params) { + def options = [] + + // 强制更新依赖 + options.add("-U") + + // 跳过测试配置 + if (params.skipTests ?: true) { + options.add("-Dmaven.test.skip=true") + } + + // 添加Maven profile(如果指定) + if (params.PROFILES) { + options.add("-P${params.PROFILES}") + } + + // 添加分支配置中的额外选项 + if (params.branchConfig?.maven?.options) { + options.add(params.branchConfig.maven.options) + } + + script.echo " ⚙️ Install步骤Options: ${options.join(' ')}" + return options.join(" ") + } + + /** + * 收集生成的构件信息 + * + * @param params 构建参数Map + * @return 构件信息列表 + */ + private def collectArtifacts(params) { + def artifacts = [] + + try { + def jarFiles = script.findFiles(glob: "${params.jarFilePath ?: 'target'}/*.jar") + jarFiles.each { file -> + artifacts.add([ + name: file.name, + path: file.path, + size: file.length(), + type: file.name.endsWith('-sources.jar') ? 'sources' : + file.name.endsWith('-javadoc.jar') ? 'javadoc' : 'main' + ]) + } + } catch (Exception e) { + script.echo "⚠️ 无法收集构件信息: ${e.message}" + } + + return artifacts + } + + /** + * 获取本地仓库路径(模拟) + * + * @return 本地仓库路径 + */ + private def getLocalRepositoryPath() { + return "~/.m2/repository/com/xiaomayi/" + } + + /** + * 打印构建配置详情 + * + * @param params 构建参数Map + */ + private def printBuildConfiguration(params) { + script.echo "📋 构建配置详情:" + script.echo " 🔧 Maven配置: ${params.MAVEN_SET}" + script.echo " 🌍 构建Profile: ${params.PROFILES}" + script.echo " 📦 输出路径: ${params.jarFilePath ?: 'target'}" + script.echo " 🏷️ JAR文件: ${params.jarFile ?: '未指定'}" + script.echo " ⚡ 跳过测试: ${params.skipTests ?: true}" + script.echo " 📄 POM文件: ${params.pomFilePath ?: 'pom.xml'}" + script.echo " 🔄 构建模式: 纯构建 (install only)" + } + + /** + * 生成构建报告 + * + * @param params 构建参数Map + * @param buildResult 构建结果 + */ + private def generateBuildReport(params, buildResult) { + script.echo "📊 构建阶段完成报告:" + script.echo " - ✅ 依赖清理完成(com.xiaomayi)" + script.echo " - ✅ 代码编译完成" + script.echo " - ${params.skipTests ? '⚡ 单元测试跳过' : '✅ 单元测试通过'}" + script.echo " - ✅ 打包完成" + script.echo " - ✅ 本地安装完成" + + // 显示生成的构件信息 + script.echo "🎉 构建产物信息:" + script.echo " - 本地路径: ${params.jarFilePath ?: 'target'} 目录" + script.echo " - 本地仓库: ${buildResult.localRepositoryPath}" + + if (buildResult.artifacts) { + script.echo "📦 生成的构件:" + buildResult.artifacts.each { artifact -> + script.echo " - ${artifact.name} (${artifact.size} bytes) [${artifact.type}]" + } + } + + script.echo "⏱️ 构建时间: ${buildResult.installTime}" + } + + /** + * 处理构建失败情况 + * + * @param e 异常对象 + * @param params 构建参数Map + */ + private def handleBuildFailure(Exception e, params) { + script.echo "❌ 构建阶段失败: ${e.message}" + script.echo "💡 建议检查:" + script.echo " - Maven settings.xml 配置是否正确" + script.echo " - 网络连接是否正常(依赖下载)" + script.echo " - 代码编译是否有语法错误" + script.echo " - 单元测试是否通过" + script.echo " - 版本号冲突或依赖问题" + + // 显示当前环境信息用于调试 + script.echo "🔍 调试信息:" + script.echo " - 环境: ${params.PROFILES}" + script.echo " - Maven配置: ${params.MAVEN_SET}" + script.echo " - POM文件: ${params.pomFilePath ?: 'pom.xml'}" + } + + /** + * 验证环境profile有效性 + * + * @param params 参数Map + */ + private def validateProfile(params) { + script.echo "🔍 开始验证环境profile有效性..." + + // 参数完整性检查 + if (!params.PROFILES) { + def errorMsg = "缺少必要的PROFILES参数,请指定要部署的环境" + script.echo "❌ ${errorMsg}" + throw new IllegalArgumentException(errorMsg) + } + + if (!params.availableProfiles || params.availableProfiles.isEmpty()) { + def errorMsg = "缺少可用的环境profile列表,请检查配置文件中环境配置" + script.echo "❌ ${errorMsg}" + throw new IllegalArgumentException(errorMsg) + } + + // 环境有效性验证 + try { + def selectedProfile = params.PROFILES.trim() + def availableProfiles = params.availableProfiles.collect { it.toString().trim() } + + script.echo "📋 验证详情:" + script.echo " 🎯 选择的环境: ${selectedProfile}" + script.echo " 📊 可用环境: ${availableProfiles.join(', ')}" + + if (!availableProfiles.contains(selectedProfile)) { + def errorMsg = "无效的部署环境: '${selectedProfile}'。可用环境: ${availableProfiles.join(', ')}" + script.error("环境验证失败: ${errorMsg}") + } + + script.echo "✅ 环境profile验证通过: ${selectedProfile}" + } catch (Exception e) { + script.echo "❌ 环境profile验证过程中发生错误: ${e.message}" + script.echo "📋 可用环境列表: ${params.availableProfiles.join(', ')}" + throw e + } + } + + /** + * 检查构建是否成功(公共方法) + * + * @param buildResult 构建结果 + * @return boolean 是否成功 + */ + def isBuildSuccessful(buildResult) { + return buildResult?.success ?: false + } + + /** + * 获取构建产物列表(公共方法) + * + * @param buildResult 构建结果 + * @return 构件列表 + */ + def getBuildArtifacts(buildResult) { + return buildResult?.artifacts ?: [] + } +} \ No newline at end of file diff --git a/src/com/nexus/stages/DeployService.groovy b/src/com/nexus/stages/DeployService.groovy new file mode 100644 index 0000000..843f41d --- /dev/null +++ b/src/com/nexus/stages/DeployService.groovy @@ -0,0 +1,431 @@ +package com.nexus.stages + +/** + * 部署服务 - 负责将Maven构件部署到Nexus私库 + * 专注于部署生命周期,依赖于构建服务的输出 + * + * 主要职责: + * - 执行Maven deploy步骤,将构件部署到远程仓库 + * - 验证部署环境和配置的有效性 + * - 处理GPG签名等安全相关操作 + * - 提供部署结果的状态反馈 + * - 支持快照版本和正式版本的发布策略 + * + * 设计原则: + * - 单一职责:专注于构件部署和发布 + * - 依赖注入:依赖于BuildService的输出结果 + * - 条件执行:根据配置决定是否执行部署 + * - 错误隔离:部署失败不影响构建结果 + * + * @see Serializable 实现序列化接口,支持Jenkins流水线的暂停和恢复 + */ +class DeployService implements Serializable { + + /** + * Jenkins pipeline脚本对象 + */ + def script + + /** + * 环境配置信息 + */ + def envConfig + + /** + * 构造函数 - 初始化部署服务 + * + * @param script Jenkins pipeline脚本对象 + * @param envConfig 环境配置信息(可选) + */ + DeployService(script, envConfig = [:]) { + this.script = script + this.envConfig = envConfig + + script.echo "🚀 DeployService 初始化完成" + } + + /** + * 执行部署阶段逻辑 + * 负责将构建产物部署到Nexus仓库 + * + * 主要步骤: + * 1. 验证部署条件和配置 + * 2. 执行Maven deploy步骤 + * 3. 处理部署结果和异常 + * 4. 生成部署报告 + * + * @param params 管道参数Map,包含部署所需的所有配置信息 + * @param buildResult 构建阶段的结果(可选) + * @return 部署结果信息 + * @throws Exception 当部署失败时抛出异常 + */ + def executeDeployStage(params, buildResult = null) { + def deployResult = [:] + + try { + // 验证是否应该执行部署 + if (!shouldExecuteDeploy(params)) { + script.echo "⏭️ 跳过部署阶段(部署功能未启用)" + return [success: true, skipped: true, reason: "部署功能未启用"] + } + + // 输出部署开始信息 + script.echo "🚀 开始部署阶段..." + printDeployConfiguration(params) + + // 验证部署环境 + validateDeployEnvironment(params) + + // 执行Maven deploy步骤 + deployResult = executeMavenDeploy(params) + + // 部署成功完成,生成报告 + generateDeployReport(params, deployResult, buildResult) + + return deployResult + + } catch (Exception e) { + // 部署失败处理 + handleDeployFailure(e, params) + // 重新抛出异常,确保流水线标记为失败状态 + throw e + } + } + + /** + * 执行Maven deploy步骤 + * 负责将构件部署到远程Nexus仓库 + * + * @param params 部署参数Map + * @return 部署结果信息 + */ + private def executeMavenDeploy(params) { + script.echo "📤 开始执行Maven deploy步骤..." + + def deployResult = [ + success: false, + deployedArtifacts: [], + deployTime: new Date().format('yyyy-MM-dd HH:mm:ss'), + repositoryUrl: params.currentNexusConfig?.url, + repositoryPolicy: params.repositoryPolicy + ] + + // 使用Config File Provider加载Maven settings.xml + script.configFileProvider([script.configFile(fileId: params.MAVEN_SET, variable: 'MAVEN_SETTINGS_XML')]) { + + def deployGoals = buildDeployGoals(params) + def deployOptions = buildDeployOptions(params) + + def deployOutput = script.sh( + script: """ + # ================================================ + # Maven Deploy 步骤 - 部署到Nexus仓库 + # 环境: ${params.PROFILES} + # 时间: \$(date) + # ================================================ + + echo "🚀 开始部署到Nexus仓库..." + + # 显示部署信息 + echo "🎯 目标仓库: ${params.currentNexusConfig?.url ?: '默认仓库'}" + echo "📋 仓库策略: ${params.repositoryPolicy ?: 'releases'}" + echo "🔧 Settings文件: \${MAVEN_SETTINGS_XML}" + echo "🏷️ 版本后缀: ${params.versionSuffix ?: '无'}" + + # 执行deploy命令 + echo "🔨 执行命令: /usr/local/maven/bin/mvn --settings \${MAVEN_SETTINGS_XML} ${deployGoals} ${deployOptions}" + + /usr/local/maven/bin/mvn \\ + --settings \${MAVEN_SETTINGS_XML} \\ + -f ${params.pomFilePath ?: 'pom.xml'} \\ + ${deployGoals} ${deployOptions} + """, + returnStatus: true + ) + + // 处理部署结果 + deployResult.success = (deployOutput == 0) + deployResult.exitCode = deployOutput + + if (deployResult.success) { + script.echo "✅ Maven deploy 成功完成!" + deployResult.deployedArtifacts = estimateDeployedArtifacts(params) + } else { + script.echo "❌ Maven deploy 失败,退出码: ${deployOutput}" + throw new Exception("Maven部署失败,退出码: ${deployOutput}") + } + } + + return deployResult + } + + /** + * 构建deploy步骤的Maven目标 + * + * @param params 部署参数Map + * @return Maven goals字符串 + */ + private def buildDeployGoals(params) { + def goals = ["deploy"] + + script.echo " 🚀 Deploy步骤Goals: ${goals.join(' ')}" + return goals.join(" ") + } + + /** + * 构建deploy步骤的Maven选项 + * + * @param params 部署参数Map + * @return Maven选项字符串 + */ + private def buildDeployOptions(params) { + def options = buildCommonMavenOptions(params) + + // deploy特有的选项 + if (params.publishStrategy?.signArtifacts) { + options.add("-Dgpg.sign=true") + if (params.publishStrategy.gpgKeyId) { + options.add("-Dgpg.keyname=${params.publishStrategy.gpgKeyId}") + } + script.echo " 🔏 启用GPG签名" + } + + script.echo " ⚙️ Deploy步骤Options: ${options.join(' ')}" + return options.join(" ") + } + + /** + * 构建通用的Maven选项 + * + * @param params 部署参数Map + * @return Maven选项列表 + */ + private def buildCommonMavenOptions(params) { + def options = [] + + // 强制更新依赖 + options.add("-U") + + // 跳过测试配置 + if (params.skipTests ?: true) { + options.add("-Dmaven.test.skip=true") + } + + // 添加Maven profile(如果指定) + if (params.PROFILES) { + options.add("-P${params.PROFILES}") + } + + // 添加分支配置中的额外选项 + if (params.branchConfig?.maven?.options) { + options.add(params.branchConfig.maven.options) + } + + return options + } + + /** + * 判断是否应该执行deploy步骤 + * + * @param params 部署参数Map + * @return boolean 是否执行deploy + */ + private def shouldExecuteDeploy(params) { + // 检查分支配置中的deploy设置 + def branchDeployEnabled = params.branchConfig?.maven?.deploy ?: false + + // 检查环境配置中的autoDeploy设置 + def envAutoDeploy = params.autoDeploy ?: true + + // 检查发布策略中的autoPublish设置 + def publishAutoPublish = params.publishStrategy?.autoPublish ?: true + + // 最终决策:所有条件都满足时才执行部署 + def finalDecision = branchDeployEnabled && envAutoDeploy && publishAutoPublish + + script.echo "📋 部署决策分析:" + script.echo " - 分支部署配置: ${branchDeployEnabled}" + script.echo " - 环境自动部署: ${envAutoDeploy}" + script.echo " - 发布策略自动发布: ${publishAutoPublish}" + script.echo " - 最终决策: ${finalDecision ? '执行部署' : '跳过部署'}" + + return finalDecision + } + + /** + * 估计部署的构件信息 + * + * @param params 部署参数Map + * @return 部署的构件列表 + */ + private def estimateDeployedArtifacts(params) { + def artifacts = [] + + // 根据常见的Maven项目结构估计部署的构件 + def baseArtifacts = [ + [name: "${params.artifactName ?: 'project'}.jar", type: "main"], + [name: "${params.artifactName ?: 'project'}-sources.jar", type: "sources"], + [name: "${params.artifactName ?: 'project'}-javadoc.jar", type: "javadoc"], + [name: "${params.artifactName ?: 'project'}.pom", type: "pom"] + ] + + baseArtifacts.each { artifact -> + artifacts.add([ + name: artifact.name, + type: artifact.type, + repository: params.currentNexusConfig?.url, + policy: params.repositoryPolicy + ]) + } + + return artifacts + } + + /** + * 验证部署环境 + * + * @param params 部署参数Map + */ + private def validateDeployEnvironment(params) { + script.echo "🔍 验证部署环境配置..." + + // 检查Nexus配置 + if (!params.currentNexusConfig) { + throw new IllegalArgumentException("缺少Nexus仓库配置") + } + + if (!params.currentNexusConfig.url) { + throw new IllegalArgumentException("Nexus仓库URL未配置") + } + + if (!params.currentNexusConfig.credentialsId) { + script.echo "⚠️ Nexus仓库凭证未配置,可能使用匿名访问" + } + + // 检查仓库策略 + if (!params.repositoryPolicy) { + script.echo "⚠️ 仓库策略未指定,使用默认策略" + } + + script.echo "✅ 部署环境验证通过" + } + + /** + * 打印部署配置详情 + * + * @param params 部署参数Map + */ + private def printDeployConfiguration(params) { + script.echo "📋 部署配置详情:" + script.echo " 🔧 Maven配置: ${params.MAVEN_SET}" + script.echo " 🌍 部署Profile: ${params.PROFILES}" + script.echo " 🔗 Nexus仓库: ${params.currentNexusConfig?.url}" + script.echo " 🎯 仓库策略: ${params.repositoryPolicy ?: 'releases'}" + script.echo " 🔑 凭证ID: ${params.currentNexusConfig?.credentialsId ?: '未设置'}" + + // 显示发布策略 + if (params.publishStrategy) { + script.echo " 🚀 自动发布: ${params.publishStrategy.autoPublish ?: 'false'}" + script.echo " 🔏 GPG签名: ${params.publishStrategy.signArtifacts ?: 'false'}" + if (params.publishStrategy.signArtifacts) { + script.echo " 🔑 GPG密钥: ${params.publishStrategy.gpgKeyId ?: '默认密钥'}" + } + script.echo " 📋 版本策略: ${params.publishStrategy.versionPolicy ?: 'semantic'}" + } + + script.echo " 🏷️ 版本后缀: ${params.versionSuffix ?: '无'}" + } + + /** + * 生成部署报告 + * + * @param params 部署参数Map + * @param deployResult 部署结果 + * @param buildResult 构建结果(可选) + */ + private def generateDeployReport(params, deployResult, buildResult) { + script.echo "📊 部署阶段完成报告:" + script.echo " - ✅ 构件验证完成" + script.echo " - ✅ 仓库连接建立" + script.echo " - ✅ 构件上传完成" + + if (params.publishStrategy?.signArtifacts) { + script.echo " - 🔏 GPG签名验证完成" + } + + script.echo "🎯 部署目标信息:" + script.echo " - 🌐 仓库地址: ${deployResult.repositoryUrl}" + script.echo " - 📋 仓库策略: ${deployResult.repositoryPolicy}" + script.echo " - 🏷️ 版本类型: ${params.versionSuffix ? '快照版本' : '正式版本'}" + + if (deployResult.deployedArtifacts) { + script.echo "📦 部署的构件:" + deployResult.deployedArtifacts.each { artifact -> + script.echo " - ${artifact.name} [${artifact.type}]" + } + } + + script.echo "⏱️ 部署时间: ${deployResult.deployTime}" + + // 显示与构建结果的关联 + if (buildResult) { + script.echo "🔗 构建-部署关联:" + script.echo " - 构建时间: ${buildResult.installTime}" + script.echo " - 部署时间: ${deployResult.deployTime}" + script.echo " - 总耗时: 计算中..." + } + } + + /** + * 处理部署失败情况 + * + * @param e 异常对象 + * @param params 部署参数Map + */ + private def handleDeployFailure(Exception e, params) { + script.echo "❌ 部署阶段失败: ${e.message}" + script.echo "💡 建议检查:" + script.echo " - Nexus仓库地址是否正确" + script.echo " - 仓库访问权限是否足够" + script.echo " - 网络连接是否正常" + script.echo " - 版本号是否冲突(重复部署)" + script.echo " - GPG签名配置是否正确" + + // 显示当前部署环境信息用于调试 + script.echo "🔍 调试信息:" + script.echo " - 环境: ${params.PROFILES}" + script.echo " - Nexus仓库: ${params.currentNexusConfig?.url}" + script.echo " - 仓库策略: ${params.repositoryPolicy}" + script.echo " - 部署配置: ${params.branchConfig?.maven?.deploy ? '启用' : '禁用'}" + } + + /** + * 检查部署是否成功(公共方法) + * + * @param deployResult 部署结果 + * @return boolean 是否成功 + */ + def isDeploySuccessful(deployResult) { + return deployResult?.success ?: false + } + + /** + * 检查部署是否被跳过(公共方法) + * + * @param deployResult 部署结果 + * @return boolean 是否被跳过 + */ + def isDeploySkipped(deployResult) { + return deployResult?.skipped ?: false + } + + /** + * 获取部署的构件信息(公共方法) + * + * @param deployResult 部署结果 + * @return 部署的构件列表 + */ + def getDeployedArtifacts(deployResult) { + return deployResult?.deployedArtifacts ?: [] + } +} \ No newline at end of file diff --git a/vars/pipelineNexusService.groovy b/vars/pipelineNexusService.groovy index e69de29..96665cb 100644 --- a/vars/pipelineNexusService.groovy +++ b/vars/pipelineNexusService.groovy @@ -0,0 +1,266 @@ +// 导入在 Pipeline 中需要使用的共享库类 +// 这些类通常在 Jenkins 的共享库 (Shared Libraries) 中定义,提供了可重用的功能 +import com.nexus.ResolverService +import com.nexus.DeploymentService +import com.common.StageService +import com.common.NotificationService + +/** + * 主管道入口点 + * 提供完整的CI/CD流水线功能,实现从配置加载到部署的全流程自动化 + * 这是一个 Jenkins 共享库 (Shared Library) 中的全局变量 (Global Variable) 或直接在 Pipeline 脚本中定义的方法 + * + * @param orgName 组织名称,用于标识不同的组织配置和环境。这是调用此流水线时必须传入的主要参数。 + * + * 功能特性: + * - 动态配置加载:支持根据 orgName 加载多环境配置管理 + * - 多阶段流水线:清晰的构建、测试、部署、验证流程 + * - 错误恢复机制:完善的异常处理和回滚功能 (虽然在当前代码示例中未完全展示,但框架支持) + * - 资源清理:自动清理工作空间和临时资源,避免磁盘空间耗尽 + * - 通知机制:构建结果通知(成功、失败、中止、不稳定) + * + * 示例用法: + * @Library ('share-library@master')_ + * orgName = 'xiaomayi' + * pipelineJDKService(orgName) + */ +def call(String orgName) { // Jenkins Pipeline 的入口方法通常命名为 call + // 定义管道参数变量,用于在不同阶段间传递配置信息。初始化为 null。 + def pipelineParams = null + // 声明服务类变量,将在后续阶段初始化 + def resolverService = null // 配置解析服务实例 + def deploymentService = null // 部署服务实例 + def stageService = null // 阶段服务实例 + def notificationService = null // 通知服务实例 + // Jenkins代理标签,指定流水线特定阶段在哪个代理节点上运行 + def jenkinsAgent = '' + + // 启动流水线定义。这是 Declarative Pipeline 的语法开始 + pipeline { + // 指定流水线执行代理,any表示可在任何可用代理上运行。 + // 注意:这里定义的 agent 会被后面 stage 中定义的 agent 覆盖。 + agent any + + // 流水线全局配置选项块 + options { + // 构建历史保留策略,用于管理 Jenkins 服务器磁盘空间 + buildDiscarder(logRotator( + artifactDaysToKeepStr: '', // 构建产物保留天数(空字符串表示不按天数限制,可能使用数量限制) + artifactNumToKeepStr: '2', // 保留最近2个构建的产物(如生成的jar包、docker镜像等) + daysToKeepStr: '7', // 构建记录元数据(日志、状态等)保留7天 + numToKeepStr: '3' // 保留最近3个构建记录(无论天数) + )) + // 全局超时设置:整个流水线最多运行2小时,超时则自动终止,防止无限运行 + timeout(time: 2, unit: 'HOURS') + // 还可以添加其他选项,例如: disableConcurrentBuilds() 防止并行运行等 + } + + // 流水线阶段定义块,包含按顺序执行的一系列阶段 (stages) + stages { + /** + * 第一阶段:初始化配置和环境 + * 加载环境配置、解析参数、初始化服务实例。 + * 此阶段仍在 pipeline 顶部定义的 agent any 上运行。 + */ + stage('Setup Parameters & ENV') { + steps { + // 执行Git检出操作 (checkout SCM),获取流水线配置文件或所需的配置仓库 + checkout scmGit([ // scmGit 是一种 checkout 方式 + // 指定要检出的分支,这里检出 master 分支 + branches: [[name: '*/master']], + // 配置远程仓库信息,包括认证和URL + userRemoteConfigs: [[ + credentialsId: 'c9b5eae2-5df5-485f-bebd-9cd5393b03e1', // 存储在 Jenkins 中的 Git 认证凭据ID + url: 'http://192.168.10.102:3000/cicd/jenkins-pipeline-files.git' // 配置仓库的URL地址 + ]], + // 扩展配置:指定检出到非默认工作目录的子目录中,避免与后续可能检出的应用代码冲突 + extensions: [[ + $class: 'RelativeTargetDirectory', // Jenkins checkout 扩展的类名,用于设置相对目标目录 + relativeTargetDir: '.pipeline-files' // 将配置仓库检出到工作空间下的 .pipeline-files 目录 + ]], + ]) + script { + echo "=== 开始初始化配置 ===" + echo "组织名称: ${orgName}" // 打印传入的组织名称参数 + try { // 使用 try-catch 进行异常处理,确保配置失败时能妥善处理 + // 初始化阶段服务实例,this 代表当前的流水线脚本对象,用于访问 Jenkins 步骤 + stageService = new StageService(this) + // 记录 '初始化配置' 阶段的开始时间 + stageService.recordStageStart('初始化配置') + + // 初始化配置解析服务实例,传入当前脚本对象和组织名称 + resolverService = new ResolverService(this, orgName) + // 调用解析服务的方法,加载所有配置文件(如环境相关的配置和主配置) + resolverService.loadConfigurations() + // 调用解析服务的方法,解析加载的配置并设置管道运行所需的参数集合 + // 返回的 pipelineParams 可能包含 Maven 设置、镜像仓库地址、目标服务器配置、环境变量等 + pipelineParams = resolverService.setupParameters() + + // 处理环境 profile 选择逻辑 + // params.PROFILES 可能是一个通过 Jenkins 输入参数(parameters {} 块)传入的值 + // 如果用户选择了 profile,则使用它;否则使用配置文件中定义的默认 profile (pipelineParams.PROFILES) + def selectedProfile = params.PROFILES ?: pipelineParams.PROFILES + pipelineParams.PROFILES = selectedProfile // 将最终确定的 profile 设置回参数Map中 + + // 设置后续构建和部署阶段使用的 Jenkins 代理标签 + // 优先使用配置文件中指定的代理标签,如果未配置则默认使用 'master' 节点(Jenkins Controller) + jenkinsAgent = pipelineParams?.jenkinsAgent ?: 'master' + echo "本次使用代理节点: ${jenkinsAgent}" + + // 初始化部署服务实例,传入当前脚本对象和从配置中获取的环境配置 + deploymentService = new DeploymentService(this, pipelineParams.envConfig) + + // 初始化消息通知服务实例,传入当前脚本对象、管道参数和阶段服务实例 + notificationService = new NotificationService(this, pipelineParams, stageService) + + // 记录 '初始化配置' 阶段的成功结束 + stageService.recordStageEnd('初始化配置', 'SUCCESS') + + } catch (Exception e) { // 捕获初始化过程中可能抛出的任何异常 + // 打印错误信息到流水线日志 + echo "配置初始化失败: ${e.message}" + // 记录 '初始化配置' 阶段的失败结束 + stageService.recordStageEnd('初始化配置', 'FAILURE') + // 抛出错误,终止整个流水线的执行,并标记为 FAILURE 状态 + error("管道初始化失败: " + e.getMessage()) + } + + echo "=== 结束初始化配置 ===" + } + } + } + + /** + * 第二阶段:代码构建 + * 执行Maven构建(编译、测试、打包),生成可部署的JAR包和Docker镜像。 + * 此阶段在指定的 Jenkins 代理节点 (jenkinsAgent) 上运行,以分担主节点负载或使用特定环境。 + */ + stage('Build') { + // 指定在此阶段使用的 Jenkins 代理节点标签 + agent { + label jenkinsAgent // 使用前面计算得到的代理标签 + } + steps { + script { + echo "=== 🔨 开始代码构建 ===" + // 记录 '构建镜像' 阶段的开始时间 + stageService.recordStageStart('构建镜像') + // 调用部署服务的方法,执行具体的构建逻辑 + // 该方法内部可能包含:mvn clean compile/test/package、docker build/push 等步骤 + deploymentService.executeBuildStage(pipelineParams) + // 记录 '构建镜像' 阶段的成功结束 + stageService.recordStageEnd('构建镜像', 'SUCCESS') + echo "=== 🔨 完成代码构建 ===" + } + } + } + + // /** + // * 第三阶段:应用部署 + // * 将Docker镜像部署到目标服务器(如测试、预生产、生产环境)。 + // * 此阶段同样在指定的 Jenkins 代理节点 (jenkinsAgent) 上运行。 + // */ + // stage('Deploy') { + // // 指定在此阶段使用的 Jenkins 代理节点标签 + // agent { + // label jenkinsAgent + // } + // steps { + // script { + // echo "=== 🚀 开始应用部署 ===" + // // 记录 '应用部署' 阶段的开始时间 + // stageService.recordStageStart('应用部署') + // // 调用部署服务的方法,执行具体的部署逻辑 + // // 该方法内部可能包含:通过 SSH 连接到目标服务器、执行部署脚本、更新容器(docker compose/k8s)等 + // deploymentService.executeDeployStage(pipelineParams) + // // 记录 '应用部署' 阶段的成功结束 + // stageService.recordStageEnd('应用部署', 'SUCCESS') + // echo "=== 🚀 完成应用部署 ===" + // } + // } + // } + + // 可以在此处添加更多阶段,例如:自动化测试、集成测试、性能测试、安全扫描等 + } + + /** + * 流水线后处理块 (post section) + * 根据流水线的最终状态执行不同的操作,无论构建成功与否都会执行的处理逻辑。 + * 此部分在 pipeline 顶部定义的 agent any 上运行。 + */ + post { + /** + * always:无论构建结果如何(成功、失败、中止、不稳定)都会执行 + * 主要用于资源清理和状态报告等必须完成的操作 + */ + always { + echo "=== 管道执行完成 ===" + echo "完成时间: ${new Date()}" // 打印流水线结束的时间 + // 清理工作空间,删除当前流水线运行产生的所有文件,释放磁盘空间 + cleanWs() + script { + echo "构建完成,状态: ${currentBuild.currentResult}" // 打印最终构建状态 + // 调用阶段服务的方法,收集所有阶段的执行信息(开始时间、持续时间、状态),可能用于通知或报告 + stageService.collectAllStagesInfo() + } + } + + /** + * success:只有当整个流水线的状态为 SUCCESS 时执行 + * 主要用于成功通知和结果报告 + */ + success { + echo "✅ 部署成功!" + script { + // 调用通知服务的方法,发送构建成功的通知(如邮件、钉钉、Slack等) + notificationService.sendBuildSuccess() + } + } + + /** + * failure:只有当整个流水线的状态为 FAILURE 时执行 + * 主要用于错误报告、通知和可能的清理或回滚操作(虽然此处未展示回滚) + */ + failure { + echo "❌ 部署失败!" + script { + // 调用通知服务的方法,发送构建失败的通知,并传递错误信息 + // 这里的 errorMsg 和 extraInfo 是示例,实际可能从捕获的异常中获取 + notificationService.sendBuildFailure( + errorMsg: "单元测试失败", // 示例错误消息 + extraInfo: [stage: "test", errorDetails: "具体错误信息"] // 示例额外信息 + ) + } + } + + /** + * aborted:只有当整个流水线的状态为 ABORTED 时执行(通常由用户手动中止) + * 用于通知构建被中止的情况 + */ + aborted { + echo "❌ 构建中止!" + script { + // 调用通知服务的方法,发送构建中止的通知 + notificationService.sendBuildAborted( + // 传递一些额外信息,例如中止原因和操作人(如果环境变量可用) + extraInfo: [中止原因: '手动中止', 操作人: env.USER_ID] + ) + } + } + + /** + * unstable:只有当整个流水线的状态为 UNSTABLE 时执行(通常由测试失败或有警告导致) + * 主要用于警告通知 + */ + unstable { + echo "⚠️ 管道执行不稳定" + script { + // 调用通知服务的方法,发送构建不稳定的通知 + notificationService.sendBuildUnstable( + extraInfo: ["不稳定原因": "测试未通过或存在警告"] // 示例原因 + ) + } + } + } + } +} \ No newline at end of file