Files
jianghao e4a4c227b5
All checks were successful
test/timeline-server/pipeline/head This commit looks good
feat(响应枚举): 添加参数错误枚举值
chore(Jenkinsfile): 清理构建后的Docker镜像
2026-02-25 17:30:53 +08:00

296 lines
10 KiB
Groovy
Raw Permalink 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
tools {
maven 'maven 3.9.12' // 修正Maven工具名称
jdk 'openjdk21' // 修正JDK工具名称使用Jenkins中实际配置的名称
}
environment {
REGISTRY = 'timeline-registry:5000'
PROJECT_NAME = 'timeline-server'
DOCKER_REGISTRY = 'timeline-registry:5000'
}
parameters {
choice(
name: 'DEPLOY_ENV',
choices: ['dev', 'staging', 'prod'],
description: '选择部署环境'
)
string(
name: 'BRANCH_NAME',
defaultValue: 'main',
description: '构建分支'
)
}
stages {
stage('Checkout') {
steps {
checkout scm
script {
echo "当前分支: ${params.BRANCH_NAME}"
}
}
}
stage('Build') {
steps {
script {
echo '开始构建项目'
sh 'mvn clean compile -DskipTests'
}
}
}
stage('Test') {
steps {
script {
echo '运行单元测试'
// sh 'mvn test'
}
}
post {
always {
script {
// 检查测试报告文件是否存在
def testReportDir = 'target/surefire-reports'
def hasReportDir = fileExists testReportDir
if (hasReportDir) {
def reportCount = sh(
script: "find ${testReportDir} -name 'TEST-*.xml' | wc -l",
returnStdout: true
).trim() as int
if (reportCount > 0) {
echo "找到 ${reportCount} 个测试报告文件"
junit testResults: 'target/surefire-reports/TEST-*.xml'
} else {
echo "未找到测试报告文件跳过JUnit发布"
}
} else {
echo "未找到测试报告目录跳过JUnit发布"
}
}
}
}
}
stage('Package') {
steps {
script {
echo '打包项目'
sh 'mvn package -DskipTests'
// 保存构建产物
archiveArtifacts artifacts: 'timeline-gateway-service/target/*.jar, timeline-user-service/target/*.jar, timeline-story-service/target/*.jar, timeline-file-service/target/*.jar', fingerprint: true
}
}
}
stage('Build and Push Docker Images') {
steps {
script {
def services = ['gateway', 'user', 'story', 'file']
for (service in services) {
def serviceDir = "timeline-${service}-service"
def imageName = "${REGISTRY}/timeline-${service}-service:${BUILD_NUMBER}"
def latestImageName = "${REGISTRY}/timeline-${service}-service:latest"
// 检查Dockerfile是否存在如果不存在则创建
if (!fileExists("${serviceDir}/Dockerfile")) {
writeFile file: "${serviceDir}/Dockerfile", text: getDockerfileContent(serviceDir)
}
// 构建镜像
sh "docker build -t ${imageName} -t ${latestImageName} ${serviceDir}/."
// 推送镜像
sh "docker push ${imageName}"
sh "docker push ${latestImageName}"
}
}
}
}
stage('Deploy') {
steps {
script {
// 创建或更新docker-compose文件
def composeContent = getComposeFileContent(BUILD_NUMBER)
writeFile file: 'docker-compose.yml', text: composeContent
// 拉取最新镜像
sh 'docker compose pull'
// 停止旧容器
sh 'docker compose down || true'
// 启动新容器
sh 'docker compose up -d'
echo "所有服务已部署完成"
}
}
}
}
post {
success {
script {
sh 'echo "构建和部署成功完成"'
// 发送成功通知
//emailext (
// subject: "构建成功: ${env.JOB_NAME} - ${env.BUILD_NUMBER}",
// body: "构建成功: ${env.BUILD_URL}",
// to: "332515344@qq.com"
//)
}
}
failure {
script {
sh 'echo "构建或部署失败"'
// 发送失败通知
//emailext (
// subject: "构建失败: ${env.JOB_NAME} - ${env.BUILD_NUMBER}",
// body: "构建失败: ${env.BUILD_URL}",
// to: "332515344@qq.com"
//)
}
}
always {
cleanWs()
}
cleanup {
// 清理 Docker 镜像
script {
def services = ['gateway', 'user', 'story', 'file']
for (service in services) {
def serviceDir = "timeline-${service}-service"
def imageName = "${REGISTRY}/timeline-${service}-service:${BUILD_NUMBER}"
sh "docker rmi -f ${imageName}"
}
}
}
}
}
// 生成Dockerfile内容的函数
def getDockerfileContent(serviceDir) {
return """FROM eclipse-temurin:21.0.2_13-jdk-alpine
VOLUME /tmp
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
"""
}
// 生成docker-compose文件内容的函数
def getComposeFileContent(buildNumber) {
return """version: '3.8'
services:
timeline-story-service:
image: timeline-registry:5000/timeline-story-service:${buildNumber}
container_name: timeline-story-service
ports:
- "30001:30001"
environment:
- server.port=30001
- spring.cloud.nacos.discovery.server-addr=host.docker.internal:8848
- spring.cloud.nacos.config.server-addr=host.docker.internal:8848
- spring.datasource.url=jdbc:mysql://host.docker.internal:33306/timeline?serverTimezone=UTC&allowPublicKeyRetrieval=true
- spring.datasource.username=root
- spring.datasource.password=WoCloud@9ol7uj
- spring.data.redis.host=host.docker.internal
- spring.data.redis.port=36379
- spring.data.redis.password=123456
- file.service.url=http://timeline-file-service:30002/file/
- user.service.url=http://timeline-user-service:30003/user/
extra_hosts:
- "host.docker.internal:host-gateway"
timeline-file-service:
image: timeline-registry:5000/timeline-file-service:${buildNumber}
container_name: timeline-file-service
ports:
- "30002:30002"
environment:
- server.port=30002
- spring.cloud.nacos.discovery.server-addr=host.docker.internal:8848
- spring.cloud.nacos.config.server-addr=host.docker.internal:8848
- spring.datasource.url=jdbc:mysql://host.docker.internal:33306/timeline?serverTimezone=UTC&allowPublicKeyRetrieval=true
- spring.datasource.username=root
- spring.datasource.password=WoCloud@9ol7uj
- minio.endpoint=http://host.docker.internal:9000
- minio.accessKey=9ttSGjvQxek2uKKlhpqI
- minio.secretKey=12CaKew53tu94tgyDLoqAwAq32iDuz3SWW0O1hex
- minio.bucketName=timeline-test
extra_hosts:
- "host.docker.internal:host-gateway"
timeline-user-service:
image: timeline-registry:5000/timeline-user-service:${buildNumber}
container_name: timeline-user-service
ports:
- "30003:30003"
environment:
- server.port=30003
- spring.cloud.nacos.discovery.server-addr=host.docker.internal:8848
- spring.cloud.nacos.config.server-addr=host.docker.internal:8848
- spring.datasource.url=jdbc:mysql://host.docker.internal:33306/timeline?serverTimezone=UTC&allowPublicKeyRetrieval=true
- spring.datasource.username=root
- spring.datasource.password=WoCloud@9ol7uj
- spring.data.redis.host=host.docker.internal
- spring.data.redis.port=36379
- spring.data.redis.password=123456
extra_hosts:
- "host.docker.internal:host-gateway"
timeline-gateway-service:
image: timeline-registry:5000/timeline-gateway-service:${buildNumber}
container_name: timeline-gateway-service
depends_on:
- timeline-story-service
- timeline-file-service
- timeline-user-service
ports:
- "33333:33333"
environment:
- server.port=33333
- spring.cloud.nacos.discovery.server-addr=host.docker.internal:8848
- spring.cloud.nacos.config.server-addr=host.docker.internal:8848
- spring.cloud.gateway.routes[0].id=story-service
- spring.cloud.gateway.routes[0].uri=lb://timeline-story
- spring.cloud.gateway.routes[0].predicates[0]=Path=/story/**
- spring.cloud.gateway.routes[0].filters[0]=StripPrefix=0
- spring.cloud.gateway.routes[1].id=file-service
- spring.cloud.gateway.routes[1].uri=lb://timeline-file
- spring.cloud.gateway.routes[1].predicates[0]=Path=/file/**
- spring.cloud.gateway.routes[1].filters[0]=StripPrefix=0
- spring.cloud.gateway.routes[2].id=user-service
- spring.cloud.gateway.routes[2].uri=lb://timeline-user
- spring.cloud.gateway.routes[2].predicates[0]=Path=/user/**
- spring.cloud.gateway.routes[2].filters[0]=StripPrefix=0
- spring.cloud.gateway.routes[3].id=user-service-ws
- spring.cloud.gateway.routes[3].uri=lb://timeline-user
- spring.cloud.gateway.routes[3].predicates[0]=Path=/user/ws/**
- spring.cloud.gateway.routes[3].filters[0]=StripPrefix=0
- spring.datasource.url=jdbc:mysql://host.docker.internal:33306/timeline?serverTimezone=UTC&allowPublicKeyRetrieval=true
- spring.datasource.username=root
- spring.datasource.password=WoCloud@9ol7uj
- spring.data.redis.host=host.docker.internal
- spring.data.redis.port=36379
- spring.data.redis.password=123456
extra_hosts:
- "host.docker.internal:host-gateway"
"""
}