354 lines
20 KiB
Groovy
354 lines
20 KiB
Groovy
// 导入在 Pipeline 中需要使用的共享库类
|
||
// 这些类通常在 Jenkins 的共享库 (Shared Libraries) 中定义,提供了可重用的功能
|
||
import com.node.ResolverService
|
||
import com.node.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 "=== 🔨 完成代码构建 ==="
|
||
}
|
||
}
|
||
}
|
||
|
||
// /**
|
||
// * 第三阶段:容器构建阶段
|
||
// * 负责将JAR包构建为Docker镜像,并推送到镜像仓库
|
||
// * 此阶段同样在指定的 Jenkins 代理节点 (jenkinsAgent) 上运行。
|
||
// */
|
||
// stage('Container Build') {
|
||
// agent {
|
||
// label jenkinsAgent
|
||
// }
|
||
// steps {
|
||
// script {
|
||
// echo "=== 🐳 开始容器构建 ==="
|
||
// // 记录 '应用部署' 阶段的开始时间
|
||
// stageService.recordStageStart('容器构建')
|
||
// // 调用部署服务的方法,执行具体的容器构建逻辑
|
||
// deploymentService.executeContainerBuildStage(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 "=== 🚀 完成应用部署 ==="
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 第五阶段:健康检查
|
||
* 负责验证部署的应用是否正常运行,确保部署的服务的可用性和功能性
|
||
* 这是CI/CD流程中的重要质量关卡,防止有缺陷的部署进入生产环境
|
||
*/
|
||
stage('Health Check') {
|
||
agent {
|
||
// 使用配置文件中指定的代理标签,如果未配置则默认使用'master'节点
|
||
// 健康检查可能需要访问部署环境网络或使用特定工具
|
||
label jenkinsAgent
|
||
}
|
||
steps {
|
||
script {
|
||
echo "=== 🏥 开始健康检查 ==="
|
||
|
||
// 记录健康检查阶段的开始时间和状态
|
||
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: ["不稳定原因": "测试未通过或存在警告"] // 示例原因
|
||
)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} |