Files
djangoadmin-web/.jenkins/.jenkinsfile2
T
2026-09-10 21:41:50 +08:00

316 lines
10 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
pipeline {
agent any
options {
// 构建记录保留策略
buildDiscarder(logRotator(
artifactDaysToKeepStr: '',
artifactNumToKeepStr: '',
daysToKeepStr: '2',
numToKeepStr: '2'
))
// 防止并发构建冲突
disableConcurrentBuilds()
// 设置构建超时时间(30分钟)
timeout(time: 30, unit: 'MINUTES')
}
// 定义构建参数
parameters {
string(
name: 'PROFILES',
defaultValue: getDefaultProfile(), // 根据分支自动设置默认值
description: '编译环境参数(dev/test/prod)',
trim: true
)
}
stages {
// 阶段1:环境配置和参数设置
stage('Setup Parameters & ENV') {
steps {
// 从Jenkins配置管理获取配置文件
configFileProvider([configFile(fileId: 'xiaomayi-web', variable: 'settingsFile')]) {
script {
setupEnvironment() // 调用环境设置函数
}
}
}
}
// 阶段2:代码编译构建
stage('Build') {
agent {
label {
label "${env.JENKINS_AGENT}" // 使用动态指定的Jenkins agent
}
}
steps {
// 使用指定的Maven配置进行构建
configFileProvider([configFile(fileId: "${env.MAVEN_SET}", variable: 'MAVEN_SETTINGS_XML')]) {
sh """
# 使用Maven进行依赖清理和项目构建
/usr/local/maven/bin/mvn --settings ${MAVEN_SETTINGS_XML} \
dependency:purge-local-repository -Dinclude=com.xiaomayi \
-f pom.xml clean package -P${params.PROFILES} \
-Dmaven.test.skip=true
"""
// 验证构建产物
sh "ls -lsh ${env.JAR_FILE_PATH}/${env.JAR_FILE}"
sh "md5sum ${env.JAR_FILE_PATH}/${env.JAR_FILE}"
}
}
post {
always {
// 归档构建产物以便后续使用和审计
archiveArtifacts artifacts: "${env.JAR_FILE_PATH}/${env.JAR_FILE}", fingerprint: true
}
}
}
// 阶段3:Docker镜像构建和推送
stage('Container Build') {
agent {
label {
label "${env.JENKINS_AGENT}"
}
}
steps {
script {
buildAndPushDockerImage() // 调用镜像构建函数
}
}
post {
always {
cleanDockerImages() // 清理本地Docker镜像节省空间
}
}
}
// 阶段4:部署到目标服务器
stage('Deploy') {
agent {
label {
label "${env.JENKINS_AGENT}"
}
}
steps {
script {
deployToServer() // 调用部署函数
}
}
}
}
// 构建后处理
post {
success {
echo "✅ Pipeline执行成功 - 分支: ${env.BRANCH_NAME} - 构建ID: ${env.BUILD_ID} - 环境: ${params.PROFILES}"
}
failure {
echo "❌ Pipeline执行失败 - 分支: ${env.BRANCH_NAME} - 构建ID: ${env.BUILD_ID}"
// 此处可以添加邮件通知、钉钉通知等
}
aborted {
echo "⚠️ Pipeline被中止 - 分支: ${env.BRANCH_NAME} - 构建ID: ${env.BUILD_ID}"
}
cleanup {
cleanWs() // 清理工作空间,释放磁盘空间
}
}
}
/**
* 根据当前分支获取默认的Profile参数
* @return 对应的环境参数(dev/test/prod)
*/
def getDefaultProfile() {
def branch = env.BRANCH_NAME ?: 'dev'
switch(branch) {
case 'dev':
return 'dev'
case 'test':
return 'test'
case 'master':
return 'prod'
default:
return 'dev' // 默认使用dev环境
}
}
/**
* 设置构建环境变量和配置参数
* 从配置文件中读取分支和服务的具体配置
*/
def setupEnvironment() {
// 读取JSON配置文件
def config = readJSON file: "${settingsFile}"
// 解析任务名称(处理多级目录结构)
def jobNameStr = env.JOB_NAME.tokenize('/')
def jobName = jobNameStr[0]
// 获取分支配置和服务配置
def branchConfig = config.branchConfig."${env.BRANCH_NAME}"
def serviceConfig = config.serviceConfig."${jobName}"
// 验证配置是否存在
if (!branchConfig || !serviceConfig) {
error("❌ 无法获取分支 ${env.BRANCH_NAME} 或服务 ${jobName} 的配置")
}
// 设置分支相关环境变量
env.MAVEN_SET = branchConfig.MAVEN_SET
env.REGISTRY = branchConfig.registry
env.REGISTRY_CREDENTIAL = branchConfig.registryCredential
env.NAMESPACE = branchConfig.namespace
env.JENKINS_AGENT = branchConfig.jenkinsAgent
env.SERVER_PORT = branchConfig.serverPort
// 设置服务相关环境变量
env.PROJECT_NAME = serviceConfig.containerName
env.SERVICE_PATH = serviceConfig.servicePath
env.JAR_PACKAGE_NAME = serviceConfig.jarPackageName
env.BASE_IMAGE = "${env.REGISTRY}/xiaomayi-base/jdk:17.0.16-rocky8-dos"
env.PORT = serviceConfig.port
env.JAR_FILE = "${env.JAR_PACKAGE_NAME}"
env.JAR_FILE_PATH = "${env.SERVICE_PATH}/target"
env.SERVER_HOST_01 = serviceConfig.serverHost01
// 根据分支设置服务器IP地址
if (['dev', 'test', 'master'].contains(env.BRANCH_NAME)) {
env.SERVER_IP_01 = branchConfig."${env.SERVER_HOST_01}"
if (!env.SERVER_IP_01) {
error("❌ 无法获取服务器IP地址配置: ${env.SERVER_HOST_01}")
}
} else {
error("❌ 不支持的分支: ${env.BRANCH_NAME}")
}
// 打印环境配置信息用于调试和验证
echo """
📋 ============ 环境配置信息 ============
🔹 分支: ${env.BRANCH_NAME}
🔹 项目: ${jobName}
🔹 环境参数: ${params.PROFILES}
🔹 Maven配置: ${env.MAVEN_SET}
🔹 镜像仓库: ${env.REGISTRY}
🔹 命名空间: ${env.NAMESPACE}
🔹 项目名称: ${env.PROJECT_NAME}
🔹 JAR文件: ${env.JAR_FILE}
🔹 目标服务器: ${env.SERVER_IP_01}:${env.SERVER_PORT}
🔹 Jenkins Agent: ${env.JENKINS_AGENT}
====================================
"""
}
/**
* 构建并推送Docker镜像到镜像仓库
*/
def buildAndPushDockerImage() {
// 打印镜像构建参数
echo """
🐳 ============ 镜像构建参数 ============
🔹 基础镜像: ${env.BASE_IMAGE}
🔹 暴露端口: ${env.PORT}
🔹 JAR文件: ${env.JAR_FILE}
🔹 JAR文件路径: ${env.JAR_FILE_PATH}
🔹 镜像标签: ${env.NAMESPACE}/${env.PROJECT_NAME}:${params.PROFILES}-${env.BUILD_ID}
====================================
"""
// 使用Docker凭证连接到镜像仓库
docker.withRegistry("https://${env.REGISTRY}", env.REGISTRY_CREDENTIAL) {
def dockerImage = docker.build(
"${env.NAMESPACE}/${env.PROJECT_NAME}:${params.PROFILES}-${env.BUILD_ID}",
// 构建参数传递
"--build-arg VAR_PROFILES=${params.PROFILES} " +
"--build-arg VAR_BASE_IMAGE=${env.BASE_IMAGE} " +
"--build-arg VAR_PORT=${env.PORT} " +
"--build-arg VAR_JARFILE=${env.JAR_FILE} " +
"--build-arg VAR_JARFILE_PATH=${env.JAR_FILE_PATH} " +
"-f .jenkinsfile/Dockerfile ./" // 指定Dockerfile路径
)
// 推送镜像到仓库
dockerImage.push()
echo "✅ Docker镜像推送成功: ${env.NAMESPACE}/${env.PROJECT_NAME}:${params.PROFILES}-${env.BUILD_ID}"
}
}
/**
* 清理本地Docker镜像,释放磁盘空间
*/
def cleanDockerImages() {
echo "🧹 开始清理本地Docker镜像..."
try {
// 删除本地构建的镜像
sh """
docker rmi -f ${env.NAMESPACE}/${env.PROJECT_NAME}:${params.PROFILES}-${env.BUILD_ID} || true
docker rmi -f ${env.REGISTRY}/${env.NAMESPACE}/${env.PROJECT_NAME}:${params.PROFILES}-${env.BUILD_ID} || true
"""
// 清理悬空镜像(不再被任何容器引用的镜像)
sh "docker image prune -f || true"
echo "✅ Docker镜像清理完成"
} catch (Exception e) {
echo "⚠️ 镜像清理过程中出现警告: ${e.message}"
// 镜像清理失败不影响主要流程,继续执行
}
}
/**
* 部署应用到目标服务器
* 通过SSH连接到服务器执行部署脚本
*/
def deployToServer() {
// 构建部署命令
def deployCmd = """
ssh -o StrictHostKeyChecking=no \
-o ConnectTimeout=30 \
-o ServerAliveInterval=60 \
esxi@${env.SERVER_IP_01} -p ${env.SERVER_PORT} \
'cd /usr/local/docker/xiaomayi-web/; ./deploy.sh deploy ${env.PROJECT_NAME} ${params.PROFILES}-${env.BUILD_ID}'
"""
echo """
🚀 ============ 开始部署 ============
🔹 目标服务器: ${env.SERVER_IP_01}:${env.SERVER_PORT}
🔹 服务名称: ${env.PROJECT_NAME}
🔹 镜像版本: ${params.PROFILES}-${env.BUILD_ID}
====================================
"""
echo "执行部署命令: ${deployCmd}"
// 部署过程添加重试机制和超时控制
try {
retry(3) { // 最多重试3次
timeout(time: 10, unit: 'MINUTES') { // 部署超时时间10分钟
sh deployCmd
}
}
echo "✅ 部署成功完成"
} catch (Exception e) {
error("❌ 部署失败: ${e.message}")
}
}
/**
* 验证必要环境变量是否设置(可选,可用于前置检查)
*/
def validateEnvironment() {
def requiredEnvVars = [
'BRANCH_NAME', 'MAVEN_SET', 'REGISTRY', 'REGISTRY_CREDENTIAL',
'NAMESPACE', 'JENKINS_AGENT', 'PROJECT_NAME', 'SERVER_IP_01'
]
def missingVars = []
requiredEnvVars.each { var ->
if (!env."${var}") {
missingVars.add(var)
}
}
if (missingVars) {
error("❌ 缺少必要环境变量: ${missingVars.join(', ')}")
}
}