java_demo/Jenkinsfile
wangtianqi abdb259a9f 更新Jenkins配置支持SSH用户名密码认证 + 添加详细的Jenkins面板操作指南
- 修改Jenkinsfile支持SSH用户名密码认证方式
- 添加JENKINS_PANEL_GUIDE.md详细操作指南
- 添加QUICK_START.md快速配置清单
- 添加服务器配置脚本支持用户名密码认证
- 更新配置文档和部署说明
2025-06-23 18:39:00 +08:00

350 lines
13 KiB
Groovy
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(numToKeepStr: '10'))
timeout(time: 30, unit: 'MINUTES')
timestamps()
}
environment {
JAVA_HOME = '/usr/lib/jvm/java-17-openjdk'
MAVEN_HOME = '/opt/maven'
PATH = "${MAVEN_HOME}/bin:${JAVA_HOME}/bin:${env.PATH}"
// 目标服务器配置
DEPLOY_SERVER = '116.62.163.84'
// Docker相关环境变量
IMAGE_NAME = 'jenkins-demo'
IMAGE_TAG = "${BUILD_NUMBER}"
// SonarQube配置
SONAR_HOST_URL = 'http://116.62.163.84:15010'
SONAR_PROJECT_KEY = 'jenkins-demo'
SONAR_TOKEN = 'squ_7e4217cabd0faae6f3b8ee359b3b8e2ac52eb69a'
}
tools {
maven 'Maven-3.9.3'
jdk 'JDK-17'
}
stages {
stage('Checkout') {
steps {
echo '🔄 开始检出代码...'
checkout scm
script {
env.GIT_COMMIT_SHORT = sh(
script: "git rev-parse --short HEAD",
returnStdout: true
).trim()
}
echo "📋 Git提交ID: ${env.GIT_COMMIT_SHORT}"
}
}
stage('环境检查') {
steps {
echo '🔍 检查构建环境...'
sh '''
echo "Java版本:"
java -version
echo "Maven版本:"
mvn -version
echo "Git版本:"
git --version
'''
}
}
stage('编译') {
steps {
echo '🔨 开始编译项目...'
sh 'mvn clean compile -DskipTests=true'
}
}
stage('单元测试') {
steps {
echo '🧪 运行单元测试...'
sh 'mvn test'
}
post {
always {
// 发布测试结果
publishTestResults testResultsPattern: 'target/surefire-reports/*.xml'
// 发布代码覆盖率报告
step([$class: 'JacocoPublisher',
execPattern: 'target/jacoco.exec',
classPattern: 'target/classes',
sourcePattern: 'src/main/java',
exclusionPattern: '**/*Test*.class'
])
}
}
}
stage('代码质量扫描') {
steps {
echo '🔍 运行SonarQube代码扫描...'
script {
try {
sh '''
mvn sonar:sonar \
-Dsonar.projectKey=${SONAR_PROJECT_KEY} \
-Dsonar.host.url=${SONAR_HOST_URL} \
-Dsonar.login=${SONAR_TOKEN} \
-Dsonar.coverage.jacoco.xmlReportPaths=target/site/jacoco/jacoco.xml
'''
echo "✅ SonarQube代码扫描完成"
} catch (Exception e) {
echo "⚠️ SonarQube扫描失败继续构建流程: ${e.getMessage()}"
}
}
}
}
stage('打包') {
steps {
echo '📦 开始打包应用程序...'
sh 'mvn package -DskipTests=true'
}
post {
success {
// 归档构建产物
archiveArtifacts artifacts: 'target/*.jar', fingerprint: true
}
}
}
stage('构建Docker镜像') {
steps {
echo '🐳 构建Docker镜像...'
script {
def image = docker.build("${IMAGE_NAME}:${IMAGE_TAG}")
// 也创建latest标签
sh "docker tag ${IMAGE_NAME}:${IMAGE_TAG} ${IMAGE_NAME}:latest"
echo "✅ Docker镜像构建完成: ${IMAGE_NAME}:${IMAGE_TAG}"
}
}
}
stage('传输Docker镜像到服务器') {
when {
anyOf {
branch 'main'
branch 'master'
branch 'develop'
}
}
steps {
echo '📤 传输Docker镜像到目标服务器...'
script {
// 将Docker镜像保存为tar文件并传输到目标服务器
withCredentials([usernamePassword(credentialsId: 'deploy-server-ssh', usernameVariable: 'SSH_USER', passwordVariable: 'SSH_PASS')]) {
sh '''
# 保存Docker镜像为tar文件
docker save ${IMAGE_NAME}:${IMAGE_TAG} -o ${IMAGE_NAME}-${IMAGE_TAG}.tar
# 安装sshpass如果未安装
command -v sshpass >/dev/null 2>&1 || {
echo "安装sshpass..."
apt-get update && apt-get install -y sshpass || yum install -y sshpass || true
}
# 传输镜像文件到目标服务器
sshpass -p "$SSH_PASS" scp -o StrictHostKeyChecking=no ${IMAGE_NAME}-${IMAGE_TAG}.tar ${SSH_USER}@${DEPLOY_SERVER}:/tmp/
# 在目标服务器上加载镜像
sshpass -p "$SSH_PASS" ssh -o StrictHostKeyChecking=no ${SSH_USER}@${DEPLOY_SERVER} << EOF
# 加载Docker镜像
docker load -i /tmp/${IMAGE_NAME}-${IMAGE_TAG}.tar
# 创建latest标签
docker tag ${IMAGE_NAME}:${IMAGE_TAG} ${IMAGE_NAME}:latest
# 清理临时文件
rm -f /tmp/${IMAGE_NAME}-${IMAGE_TAG}.tar
echo "✅ Docker镜像加载完成"
EOF
# 清理本地临时文件
rm -f ${IMAGE_NAME}-${IMAGE_TAG}.tar
'''
}
echo "✅ Docker镜像传输完成"
}
}
}
stage('部署到测试环境') {
when {
anyOf {
branch 'develop'
branch 'feature/*'
}
}
steps {
echo '🚀 部署到测试环境...'
script {
// 部署到测试服务器
withCredentials([usernamePassword(credentialsId: 'deploy-server-ssh', usernameVariable: 'SSH_USER', passwordVariable: 'SSH_PASS')]) {
sh '''
sshpass -p "$SSH_PASS" ssh -o StrictHostKeyChecking=no ${SSH_USER}@${DEPLOY_SERVER} << EOF
# 停止现有容器
docker stop jenkins-demo-test || true
docker rm jenkins-demo-test || true
# 运行新容器
docker run -d --name jenkins-demo-test \\
-p 8080:8080 \\
--restart unless-stopped \\
-e SPRING_PROFILES_ACTIVE=test \\
${IMAGE_NAME}:${IMAGE_TAG}
echo "✅ 测试环境部署完成"
EOF
'''
}
}
}
}
stage('部署到生产环境') {
when {
anyOf {
branch 'main'
branch 'master'
}
}
steps {
echo '🎯 部署到生产环境...'
script {
// 需要手动确认
input message: '确认部署到生产环境?', ok: '部署',
parameters: [choice(name: 'DEPLOY_ENV', choices: ['prod'], description: '选择部署环境')]
// 部署到生产服务器
withCredentials([usernamePassword(credentialsId: 'deploy-server-ssh', usernameVariable: 'SSH_USER', passwordVariable: 'SSH_PASS')]) {
sh '''
sshpass -p "$SSH_PASS" ssh -o StrictHostKeyChecking=no ${SSH_USER}@${DEPLOY_SERVER} << EOF
# 备份当前版本
docker tag ${IMAGE_NAME}:latest ${IMAGE_NAME}:backup-$(date +%Y%m%d-%H%M%S) || true
# 停止现有容器
docker stop jenkins-demo-prod || true
docker rm jenkins-demo-prod || true
# 运行新容器
docker run -d --name jenkins-demo-prod \\
-p 80:8080 \\
--restart unless-stopped \\
-e SPRING_PROFILES_ACTIVE=prod \\
-e JAVA_OPTS="-Xms512m -Xmx1024m" \\
${IMAGE_NAME}:${IMAGE_TAG}
# 更新latest标签
docker tag ${IMAGE_NAME}:${IMAGE_TAG} ${IMAGE_NAME}:latest
echo "✅ 生产环境部署完成"
EOF
'''
}
}
}
}
stage('健康检查') {
steps {
echo '🏥 执行应用健康检查...'
script {
// 等待应用启动
sleep(time: 30, unit: 'SECONDS')
// 检查应用健康状态
def healthCheckUrl = "http://${DEPLOY_SERVER}/api/health"
def response = sh(
script: "curl -s -o /dev/null -w '%{http_code}' ${healthCheckUrl}",
returnStdout: true
).trim()
if (response == "200") {
echo "✅ 应用健康检查通过"
} else {
error "❌ 应用健康检查失败HTTP状态码: ${response}"
}
}
}
}
}
post {
always {
echo '🧹 清理工作空间...'
// 清理Docker镜像
sh '''
docker image prune -f
docker system prune -f
'''
}
success {
echo '✅ 流水线执行成功!'
// 发送成功通知
script {
def message = """
🎉 Jenkins构建成功
📋 项目: ${env.JOB_NAME}
🔢 构建号: ${env.BUILD_NUMBER}
🌿 分支: ${env.BRANCH_NAME}
📝 提交: ${env.GIT_COMMIT_SHORT}
⏱️ 持续时间: ${currentBuild.durationString}
🔗 构建链接: ${env.BUILD_URL}
"""
// 可以集成钉钉、企业微信、邮件等通知
echo message
}
}
failure {
echo '❌ 流水线执行失败!'
// 发送失败通知
script {
def message = """
💥 Jenkins构建失败
📋 项目: ${env.JOB_NAME}
🔢 构建号: ${env.BUILD_NUMBER}
🌿 分支: ${env.BRANCH_NAME}
📝 提交: ${env.GIT_COMMIT_SHORT}
⏱️ 持续时间: ${currentBuild.durationString}
🔗 构建链接: ${env.BUILD_URL}
📄 查看日志: ${env.BUILD_URL}console
"""
echo message
}
}
unstable {
echo '⚠️ 构建不稳定,可能存在测试失败'
}
cleanup {
// 清理工作空间
cleanWs()
}
}
}