// 导入在 Pipeline 中需要使用的共享库类 // 这些类通常在 Jenkins 的共享库 (Shared Libraries) 中定义,提供了可重用的功能 import com.jdk.ResolverService import com.jdk.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) // ✅ 关键步骤:将配置文件 stash 起来 stash name: 'pipeline-files', includes: '.pipeline-files/**' // 记录 '初始化配置' 阶段的成功结束 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 "=== 🔨 开始代码构建 ===" // ✅ 关键步骤:在节点上 unstash 配置文件 unstash 'pipeline-files' // 记录 '构建镜像' 阶段的开始时间 stageService.recordStageStart('构建镜像') // 调用部署服务的方法,执行具体的构建逻辑 // 该方法内部可能包含:mvn clean compile/test/package、docker build/push 等步骤 deploymentService.executeBuildStage(pipelineParams) // 记录 '构建镜像' 阶段的成功结束 stageService.recordStageEnd('构建镜像', 'SUCCESS') echo "=== 🔨 完成代码构建 ===" } } } /** * 第三阶段:容器构建阶段 * 负责将JAR包构建为Docker镜像,并推送到镜像仓库 * 此阶段同样在指定的 Jenkins 代理节点 (jenkinsAgent) 上运行。 */ stage('Container Build') { agent { label jenkinsAgent } steps { script { echo "=== 🐳 开始容器构建 ===" // ✅ 关键步骤:在节点上 unstash 配置文件 unstash 'pipeline-files' // 记录 '应用部署' 阶段的开始时间 stageService.recordStageStart('容器构建') // 调用部署服务的方法,执行具体的容器构建逻辑 deploymentService.executeContainerBuildStage(pipelineParams) // 记录 '应用部署' 阶段的成功结束 stageService.recordStageEnd('容器构建', 'SUCCESS') echo "=== 🚀 完成容器构建 ===" } } } /** * 第四阶段:应用部署 * 将Docker镜像部署到目标服务器(如测试、预生产、生产环境)。 * 此阶段同样在指定的 Jenkins 代理节点 (jenkinsAgent) 上运行。 */ stage('Deploy') { // 指定在此阶段使用的 Jenkins 代理节点标签 agent { label jenkinsAgent } steps { script { echo "=== 🚀 开始应用部署 ===" // ✅ 关键步骤:在节点上 unstash 配置文件 unstash 'pipeline-files' // 记录 '应用部署' 阶段的开始时间 stageService.recordStageStart('应用部署') // 调用部署服务的方法,执行具体的部署逻辑 // 该方法内部可能包含:通过 SSH 连接到目标服务器、执行部署脚本、更新容器(docker compose/k8s)等 deploymentService.executeDeployStage(pipelineParams) // 记录 '应用部署' 阶段的成功结束 stageService.recordStageEnd('应用部署', 'SUCCESS') echo "=== 🚀 完成应用部署 ===" } } } /** * 第五阶段:健康检查 * 负责验证部署的应用是否正常运行,确保部署的服务的可用性和功能性 * 这是CI/CD流程中的重要质量关卡,防止有缺陷的部署进入生产环境 */ stage('Health Check') { agent { // 使用配置文件中指定的代理标签,如果未配置则默认使用'master'节点 // 健康检查可能需要访问部署环境网络或使用特定工具 label jenkinsAgent } steps { script { echo "=== 🏥 开始健康检查 ===" // ✅ 关键步骤:在节点上 unstash 配置文件 unstash 'pipeline-files' // 记录健康检查阶段的开始时间和状态 stageService.recordStageStart('健康检查') try { // 调用部署服务的健康检查方法,执行具体的验证逻辑 // deploymentService.executeHealthCheckStage(pipelineParams) // 🏗️ 以下是健康检查可能包含的具体操作(示例): // 1. 🔗 服务端点连通性测试 // - 检查应用的健康检查端点(如:/actuator/health)是否返回200状态码 // - 验证关键API接口是否可访问 // 2. 📊 应用状态验证 // - 检查应用日志是否有启动错误 // - 验证数据库连接是否正常建立 // - 确认必要的服务依赖(如Redis、MQ等)是否连接成功 // 3. 🔍 功能冒烟测试 // - 执行一组最基本的业务操作测试,确保核心功能正常 // - 验证配置是否正确加载(如配置文件、环境变量等) // 4. 📈 性能基线检查 // - 检查应用启动时间是否在可接受范围内 // - 验证内存占用、线程数等指标是否正常 // 5. 🐳 容器运行状态检查 // - 确认Docker容器处于Running状态 // - 检查容器资源使用情况(CPU、内存) // 调用部署服务的健康检查阶段逻辑 // deploymentService.executeHealthCheckStage(pipelineParams) // 记录健康检查阶段的成功结束 stageService.recordStageEnd('健康检查', 'SUCCESS') } catch (Exception e) { // 健康检查失败时的处理 echo "健康检查失败: ${e.message}" // 记录健康检查阶段的失败状态 stageService.recordStageEnd('健康检查', 'FAILURE') // 可以选择抛出错误使整个流水线失败,或者标记为UNSTABLE error("健康检查未通过,部署可能存在风险: " + e.getMessage()) } 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: ["不稳定原因": "测试未通过或存在警告"] // 示例原因 ) } } } } }