You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
RuoYi-Vue-Jenkins/Jenkinsfile-host

251 lines
11 KiB

pipeline {
agent any
parameters {
string(name: 'PROJECT_VERSION', defaultValue: '3.8.0', description: '构建版本')
string(name: 'PROJECT_KEY', defaultValue: 'ruoyi', description: '项目唯一标识')
string(name: 'NEXUS_JAVA_URL', defaultValue: 'ruoyi-maven', description: '后端制品仓库')
string(name: 'NEXUS_DIST_URL', defaultValue: 'ruoyi-dist', description: '前端制品仓库')
string(name: 'DOCKER_JAVA_IMAGE_NAME', defaultValue: 'library/ruoyi-backend', description: 'Docker后端镜像名称')
string(name: 'DOCKER_DIST_IMAGE_NAME', defaultValue: 'library/ruoyi-fronted', description: 'Docker前端镜像名称')
string(name: 'DOCKER_REGISTRY_URL', defaultValue: '10.36.176.174', description: 'Docker 镜像仓库地址')
}
environment {
NEXUS_CREDENTIALS_ID = 'jenkins_nexus'
GROUP_ID = 'com.ruoyi'
ARTIFACT_ID = 'ruoyi'
SONARQUBE_ENV = 'sonarqube'
}
stages {
stage('后端打包') {
steps {
withDockerContainer(image: 'maven:3.8.8-sapmachine-11') {
sh """
mvn package
"""
}
}
}
stage('前端打包') {
steps {
withDockerContainer(image: 'node:18.20.3-alpine3.20') {
sh """
cd ruoyi-ui
npm install --cache .npm --registry http://registry.npmmirror.com
npm run build:prod
"""
}
}
}
stage('代码扫描') {
steps {
withCredentials([string(credentialsId: 'sonarqube-token-id', variable: 'SONAR_TOKEN')]) {
withSonarQubeEnv("${env.SONARQUBE_ENV}") { // 使用配置的 SonarQube 安装名称
withDockerContainer(image: 'sonarsource/sonar-scanner-cli') {
sh """
sonar-scanner \
-Dsonar.userHome=./cache \
-Dsonar.projectKey=${params.PROJECT_KEY} \
-Dsonar.projectName=${params.PROJECT_KEY} \
-Dsonar.projectVersion=${params.PROJECT_VERSION} \
-Dsonar.sources=. \
-Dsonar.host.url=http://10.36.176.174:19000 \
-Dsonar.login=${SONAR_TOKEN} \
-Dsonar.java.binaries=.
"""
}
}
}
}
}
stage('质量检查') {
steps {
script {
// 增加超时设置,防止无限等待
timeout(time: 30, unit: 'MINUTES') {
def qg = waitForQualityGate()
// 打印质量门的详细信息以便调试
echo "Quality Gate status: ${qg.status}"
echo "Quality Gate details: ${qg}"
if (qg.status != 'OK') {
error "代码扫描异常,质量门未通过: ${qg.status}"
}
}
}
}
}
stage('后端推送制品库') {
steps {
withCredentials([usernamePassword(credentialsId: "${env.NEXUS_CREDENTIALS_ID}", usernameVariable: 'NEXUS_USERNAME', passwordVariable: 'NEXUS_PASSWORD')]) {
withDockerContainer(args: '-v /root/.m2:/root/.m2', image: 'maven:3.8.8-sapmachine-11') {
sh """
mvn deploy:deploy-file \
-DgroupId=${env.GROUP_ID} \
-DartifactId=${env.ARTIFACT_ID} \
-Dversion=${params.PROJECT_VERSION} \
-Dpackaging=jar \
-Dfile=ruoyi-admin/target/ruoyi-admin.jar \
-DrepositoryId=nexus \
-Durl=http://${NEXUS_USERNAME}:${NEXUS_PASSWORD}@10.36.176.174:8081/repository/${params.NEXUS_JAVA_URL}/
"""
}
}
}
}
stage('前端推送制品库') {
steps {
// 使用curl命令将构建的HTML文件上传到Nexus
script {
// 上传zip文件到Nexus
withCredentials([usernamePassword(credentialsId: env.NEXUS_CREDENTIALS_ID, passwordVariable: 'NEXUS_PASSWORD', usernameVariable: 'NEXUS_USERNAME')]) {
sh """
cd ruoyi-ui
zip -r build.zip dist
curl -v -u $NEXUS_USERNAME:$NEXUS_PASSWORD --upload-file build.zip http://10.36.176.174:8081/repository/${params.NEXUS_DIST_URL}/build-${params.PROJECT_VERSION}.zip
"""
}
}
}
}
stage('后端镜像构建和推送') {
steps {
script {
withCredentials([usernamePassword(credentialsId: 'jenkins-docker', usernameVariable: 'DOCKER_USERNAME', passwordVariable: 'DOCKER_PASSWORD')]) {
def imageName = "${params.DOCKER_REGISTRY_URL}/${params.DOCKER_JAVA_IMAGE_NAME}:${params.PROJECT_VERSION}"
sh """
docker build -t ${imageName} -f Dockerfile-java .
echo ${DOCKER_PASSWORD} | docker login -u ${DOCKER_USERNAME} --password-stdin ${params.DOCKER_REGISTRY_URL}
docker push ${imageName}
docker logout ${params.DOCKER_REGISTRY_URL}
"""
}
}
}
}
stage('前端镜像构建和推送') {
steps {
script {
withCredentials([usernamePassword(credentialsId: 'jenkins-docker', usernameVariable: 'DOCKER_USERNAME', passwordVariable: 'DOCKER_PASSWORD')]) {
def imageName = "${params.DOCKER_REGISTRY_URL}/${params.DOCKER_DIST_IMAGE_NAME}:${params.PROJECT_VERSION}"
sh """
docker build -t ${imageName} -f Dockerfile-nginx .
echo ${DOCKER_PASSWORD} | docker login -u ${DOCKER_USERNAME} --password-stdin ${params.DOCKER_REGISTRY_URL}
docker push ${imageName}
docker logout ${params.DOCKER_REGISTRY_URL}
"""
}
}
}
}
}
post {
// always {
// cleanWs()
// }
success {
emailext(
subject: '项目 【$PROJECT_NAME】 第【$BUILD_NUMBER】次构建 - SUCCESS!',
body: '''
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title>
</head>
<body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0">
<table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
<h3>本邮件由系统自动发出,请勿回复!</h3>
<tr>
<br/>
各位同事,大家好,以下为${PROJECT_NAME}项目构建信息</br>
<td><font color="#0B610B">构建结果 - ${BUILD_STATUS}</font></td>
</tr>
<tr>
<td><br />
<b><font color="#0B610B">构建信息</font></b>
<hr size="2" width="100%" align="center" /></td>
</tr>
<tr>
<td>
<ul>
<li>项目名称 : ${PROJECT_NAME}</li>
<li>构建编号 : 第${BUILD_NUMBER}次构建</li>
<li>触发原因: ${CAUSE}</li>
<li>构建状态: ${BUILD_STATUS}</li>
<li>构建日志: <a href="${BUILD_URL}console">${BUILD_URL}console</a></li>
<li>构建 URL : <a href="${BUILD_URL}">${BUILD_URL}</a></li>
<li>工作目录 : <a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li>
<li>项目 URL : <a href="${PROJECT_URL}">${PROJECT_URL}</a></li>
</ul>
<h4><font color="#0B610B">最近提交</font></h4>
<ul>
<hr size="2" width="100%" />
${CHANGES_SINCE_LAST_SUCCESS, reverse=true, format="%c", changesFormat="<li>%d [%a] %m</li>"}
</ul>
详细提交: <a href="${PROJECT_URL}changes">${PROJECT_URL}changes</a><br/>
</td>
</tr>
</table>
</body>
</html>
''',
to: '1161733918@qq.com',
attachLog: true
)
}
failure {
emailext(
subject: '项目 【$PROJECT_NAME】 第【$BUILD_NUMBER】次构建 - FAILURE!',
body: '''
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title>
</head>
<body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" offset="0">
<table width="95%" cellpadding="0" cellspacing="0" style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
<h3>本邮件由系统自动发出,请勿回复!</h3>
<tr>
<br/>
各位同事,以下为${PROJECT_NAME}项目构建信息</br>
<td><font color="#CC0000">构建结果 - ${BUILD_STATUS}</font></td>
</tr>
<tr>
<td><br />
<b><font color="#CC0000">构建信息</font></b>
<hr size="2" width="100%" align="center" /></td>
</tr>
<tr>
<td>
<ul>
<li>项目名称 : ${PROJECT_NAME}</li>
<li>构建编号 : 第${BUILD_NUMBER}次构建</li>
<li>触发原因: ${CAUSE}</li>
<li>构建状态: ${BUILD_STATUS}</li>
<li>构建日志: <a href="${BUILD_URL}console">${BUILD_URL}console</a></li>
<li>构建 URL : <a href="${BUILD_URL}">${BUILD_URL}</a></li>
<li>工作目录 : <a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li>
<li>项目 URL : <a href="${PROJECT_URL}">${PROJECT_URL}</a></li>
</ul>
<h4><font color="#CC0000">最近提交</font></h4>
<ul>
<hr size="2" width="100%" />
${CHANGES_SINCE_LAST_SUCCESS, reverse=true, format="%c", changesFormat="<li>%d [%a] %m</li>"}
</ul>
详细提交: <a href="${PROJECT_URL}changes">${PROJECT_URL}changes</a><br/>
</td>
</tr>
</table>
</body>
</html>
''',
to: '1161733918@qq.com',
attachLog: true
)
}
}
}