|
|
|
|
@ -375,109 +375,154 @@ pipeline {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stage('9. 推送到头歌平台') {
|
|
|
|
|
steps {
|
|
|
|
|
echo '========== 推送制品到头歌 release 分支 =========='
|
|
|
|
|
script {
|
|
|
|
|
try {
|
|
|
|
|
withCredentials([usernamePassword(
|
|
|
|
|
credentialsId: 'educoder-credentials',
|
|
|
|
|
usernameVariable: 'EDUCODER_USER',
|
|
|
|
|
passwordVariable: 'EDUCODER_PASS'
|
|
|
|
|
)]) {
|
|
|
|
|
bat '''
|
|
|
|
|
@echo off
|
|
|
|
|
setlocal EnableExtensions EnableDelayedExpansion
|
|
|
|
|
|
|
|
|
|
set "VERSION_TAG=v1.0.0.%BUILD_NUMBER%"
|
|
|
|
|
set "ARTIFACTS_DIR=artifacts\\!VERSION_TAG!"
|
|
|
|
|
|
|
|
|
|
echo ============================================
|
|
|
|
|
echo 准备制品目录: !VERSION_TAG!
|
|
|
|
|
echo ============================================
|
|
|
|
|
|
|
|
|
|
REM 创建制品目录
|
|
|
|
|
if not exist artifacts mkdir artifacts
|
|
|
|
|
if exist "!ARTIFACTS_DIR!" rmdir /S /Q "!ARTIFACTS_DIR!"
|
|
|
|
|
mkdir "!ARTIFACTS_DIR!"
|
|
|
|
|
|
|
|
|
|
REM 复制制品并重命名 (使用 fatJar)
|
|
|
|
|
echo 复制制品...
|
|
|
|
|
for %%f in (cli\\build\\libs\\mcslms-cli-*-all.jar) do (
|
|
|
|
|
copy /Y "%%f" "!ARTIFACTS_DIR!\\mcslms-cli-!VERSION_TAG!.jar" >nul
|
|
|
|
|
echo ✓ CLI JAR (fatJar)
|
|
|
|
|
)
|
|
|
|
|
for %%f in (gui\\build\\libs\\mcslms-gui-*-all.jar) do (
|
|
|
|
|
copy /Y "%%f" "!ARTIFACTS_DIR!\\mcslms-gui-!VERSION_TAG!.jar" >nul
|
|
|
|
|
echo ✓ GUI JAR (fatJar)
|
|
|
|
|
)
|
|
|
|
|
for %%f in (backend\\build\\libs\\mcslms-backend-*.jar) do (
|
|
|
|
|
copy /Y "%%f" "!ARTIFACTS_DIR!\\mcslms-backend-!VERSION_TAG!.jar" >nul
|
|
|
|
|
echo ✓ Backend JAR
|
|
|
|
|
)
|
|
|
|
|
for %%f in (backend\\build\\libs\\mcslms-web-*.war) do (
|
|
|
|
|
copy /Y "%%f" "!ARTIFACTS_DIR!\\mcslms-web-!VERSION_TAG!.war" >nul
|
|
|
|
|
echo ✓ Web WAR
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
REM 查找 APK
|
|
|
|
|
for %%f in (android\\build\\outputs\\apk\\debug\\*.apk) do (
|
|
|
|
|
copy /Y "%%f" "!ARTIFACTS_DIR!\\mcslms-app-!VERSION_TAG!.apk" >nul
|
|
|
|
|
echo ✓ Android APK
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
REM 复制 GUI EXE/ZIP
|
|
|
|
|
if exist artifacts\\mcslms-gui-!VERSION_TAG!.exe (
|
|
|
|
|
copy /Y artifacts\\mcslms-gui-!VERSION_TAG!.exe "!ARTIFACTS_DIR!\\\\" >nul
|
|
|
|
|
echo ✓ GUI EXE
|
|
|
|
|
)
|
|
|
|
|
if exist artifacts\\mcslms-gui.zip (
|
|
|
|
|
copy /Y artifacts\\mcslms-gui.zip "!ARTIFACTS_DIR!\\mcslms-gui-!VERSION_TAG!.zip" >nul
|
|
|
|
|
echo ✓ GUI ZIP
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
REM 生成清单文件
|
|
|
|
|
echo MCSLMS Release Manifest - !VERSION_TAG! > "!ARTIFACTS_DIR!\\manifest.txt"
|
|
|
|
|
echo Build ID: %BUILD_NUMBER% >> "!ARTIFACTS_DIR!\\manifest.txt"
|
|
|
|
|
echo 发布时间: %date% %time% >> "!ARTIFACTS_DIR!\\manifest.txt"
|
|
|
|
|
echo. >> "!ARTIFACTS_DIR!\\manifest.txt"
|
|
|
|
|
echo 制品列表: >> "!ARTIFACTS_DIR!\\manifest.txt"
|
|
|
|
|
for %%F in (!ARTIFACTS_DIR!\\*) do echo %%~nxF >> "!ARTIFACTS_DIR!\\manifest.txt"
|
|
|
|
|
|
|
|
|
|
echo.
|
|
|
|
|
echo 制品目录内容:
|
|
|
|
|
dir /B "!ARTIFACTS_DIR!"
|
|
|
|
|
|
|
|
|
|
REM URL编码凭据
|
|
|
|
|
for /f %%i in ('powershell -NoLogo -NoProfile -Command "[Console]::Out.Write([uri]::EscapeDataString($env:EDUCODER_USER))"') do set USER_ENC=%%i
|
|
|
|
|
for /f %%i in ('powershell -NoLogo -NoProfile -Command "[Console]::Out.Write([uri]::EscapeDataString($env:EDUCODER_PASS))"') do set PASS_ENC=%%i
|
|
|
|
|
|
|
|
|
|
echo.
|
|
|
|
|
echo ============================================
|
|
|
|
|
echo 推送到头歌 release 分支
|
|
|
|
|
echo ============================================
|
|
|
|
|
|
|
|
|
|
git config user.name "Jenkins CI"
|
|
|
|
|
git config user.email "jenkins@mcslms.local"
|
|
|
|
|
|
|
|
|
|
REM 创建 orphan 分支只包含制品
|
|
|
|
|
git checkout --orphan release-%BUILD_NUMBER%
|
|
|
|
|
git rm -rf . --ignore-unmatch >nul 2>&1
|
|
|
|
|
git add artifacts/
|
|
|
|
|
git commit -m "release: 发布 !VERSION_TAG! (Build #%BUILD_NUMBER%)"
|
|
|
|
|
|
|
|
|
|
echo 推送到头歌平台...
|
|
|
|
|
git push https://%USER_ENC%:%PASS_ENC%@bdgit.educoder.net/pu6zrsfoy/mcslms.git HEAD:refs/heads/release --force
|
|
|
|
|
|
|
|
|
|
REM 恢复原分支
|
|
|
|
|
git checkout -f develop 2>nul || git checkout -f main 2>nul
|
|
|
|
|
|
|
|
|
|
echo ✓ 制品已推送到头歌 release 分支: !VERSION_TAG!
|
|
|
|
|
'''
|
|
|
|
|
parallel {
|
|
|
|
|
stage('9.1 推送源码到 main') {
|
|
|
|
|
steps {
|
|
|
|
|
echo '========== 推送源代码到头歌 main 分支 =========='
|
|
|
|
|
script {
|
|
|
|
|
try {
|
|
|
|
|
withCredentials([usernamePassword(
|
|
|
|
|
credentialsId: 'educoder-credentials',
|
|
|
|
|
usernameVariable: 'EDUCODER_USER',
|
|
|
|
|
passwordVariable: 'EDUCODER_PASS'
|
|
|
|
|
)]) {
|
|
|
|
|
bat '''
|
|
|
|
|
@echo off
|
|
|
|
|
setlocal EnableExtensions EnableDelayedExpansion
|
|
|
|
|
|
|
|
|
|
REM URL编码用户名和密码
|
|
|
|
|
for /f %%i in ('powershell -NoLogo -NoProfile -Command "[Console]::Out.Write([uri]::EscapeDataString($env:EDUCODER_USER))"') do set USER_ENC=%%i
|
|
|
|
|
for /f %%i in ('powershell -NoLogo -NoProfile -Command "[Console]::Out.Write([uri]::EscapeDataString($env:EDUCODER_PASS))"') do set PASS_ENC=%%i
|
|
|
|
|
|
|
|
|
|
git config user.name "Jenkins CI"
|
|
|
|
|
git config user.email "jenkins@mcslms.local"
|
|
|
|
|
git remote remove educoder 2>nul || echo Remote educoder does not exist
|
|
|
|
|
git remote add educoder https://bdgit.educoder.net/pu6zrsfoy/mcslms.git
|
|
|
|
|
git fetch --unshallow 2>nul || echo Already a complete repository
|
|
|
|
|
|
|
|
|
|
REM 获取当前提交的 SHA
|
|
|
|
|
for /f %%i in ('git rev-parse HEAD') do set CURRENT_SHA=%%i
|
|
|
|
|
echo 当前提交 SHA: !CURRENT_SHA!
|
|
|
|
|
|
|
|
|
|
REM 使用 SHA 推送到 main 分支
|
|
|
|
|
git push https://%USER_ENC%:%PASS_ENC%@bdgit.educoder.net/pu6zrsfoy/mcslms.git !CURRENT_SHA!:refs/heads/main --force
|
|
|
|
|
'''
|
|
|
|
|
}
|
|
|
|
|
echo '✓ 源代码推送到 main 成功'
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
echo "⚠ 推送代码到 main 失败: ${e.message}"
|
|
|
|
|
currentBuild.result = 'UNSTABLE'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stage('9.2 推送制品到 release') {
|
|
|
|
|
steps {
|
|
|
|
|
echo '========== 推送制品到头歌 release 分支 =========='
|
|
|
|
|
script {
|
|
|
|
|
try {
|
|
|
|
|
withCredentials([usernamePassword(
|
|
|
|
|
credentialsId: 'educoder-credentials',
|
|
|
|
|
usernameVariable: 'EDUCODER_USER',
|
|
|
|
|
passwordVariable: 'EDUCODER_PASS'
|
|
|
|
|
)]) {
|
|
|
|
|
bat '''
|
|
|
|
|
@echo off
|
|
|
|
|
setlocal EnableExtensions EnableDelayedExpansion
|
|
|
|
|
|
|
|
|
|
set "VERSION_TAG=v1.0.0.%BUILD_NUMBER%"
|
|
|
|
|
set "ARTIFACTS_DIR=artifacts\\!VERSION_TAG!"
|
|
|
|
|
|
|
|
|
|
echo ============================================
|
|
|
|
|
echo 准备制品目录: !VERSION_TAG!
|
|
|
|
|
echo ============================================
|
|
|
|
|
|
|
|
|
|
REM 创建制品目录
|
|
|
|
|
if not exist artifacts mkdir artifacts
|
|
|
|
|
if exist "!ARTIFACTS_DIR!" rmdir /S /Q "!ARTIFACTS_DIR!"
|
|
|
|
|
mkdir "!ARTIFACTS_DIR!"
|
|
|
|
|
|
|
|
|
|
REM 复制制品并重命名 (使用 fatJar)
|
|
|
|
|
echo 复制制品...
|
|
|
|
|
for %%f in (cli\\build\\libs\\mcslms-cli-*-all.jar) do (
|
|
|
|
|
copy /Y "%%f" "!ARTIFACTS_DIR!\\mcslms-cli-!VERSION_TAG!.jar" >nul
|
|
|
|
|
echo ✓ CLI JAR (fatJar)
|
|
|
|
|
)
|
|
|
|
|
for %%f in (gui\\build\\libs\\mcslms-gui-*-all.jar) do (
|
|
|
|
|
copy /Y "%%f" "!ARTIFACTS_DIR!\\mcslms-gui-!VERSION_TAG!.jar" >nul
|
|
|
|
|
echo ✓ GUI JAR (fatJar)
|
|
|
|
|
)
|
|
|
|
|
for %%f in (backend\\build\\libs\\mcslms-backend-*.jar) do (
|
|
|
|
|
copy /Y "%%f" "!ARTIFACTS_DIR!\\mcslms-backend-!VERSION_TAG!.jar" >nul
|
|
|
|
|
echo ✓ Backend JAR
|
|
|
|
|
)
|
|
|
|
|
for %%f in (backend\\build\\libs\\mcslms-web-*.war) do (
|
|
|
|
|
copy /Y "%%f" "!ARTIFACTS_DIR!\\mcslms-web-!VERSION_TAG!.war" >nul
|
|
|
|
|
echo ✓ Web WAR
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
REM 查找 APK
|
|
|
|
|
for %%f in (android\\build\\outputs\\apk\\debug\\*.apk) do (
|
|
|
|
|
copy /Y "%%f" "!ARTIFACTS_DIR!\\mcslms-app-!VERSION_TAG!.apk" >nul
|
|
|
|
|
echo ✓ Android APK
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
REM 复制 GUI EXE/ZIP
|
|
|
|
|
if exist artifacts\\mcslms-gui-!VERSION_TAG!.exe (
|
|
|
|
|
copy /Y artifacts\\mcslms-gui-!VERSION_TAG!.exe "!ARTIFACTS_DIR!\\\\" >nul
|
|
|
|
|
echo ✓ GUI EXE
|
|
|
|
|
)
|
|
|
|
|
if exist artifacts\\mcslms-gui.zip (
|
|
|
|
|
copy /Y artifacts\\mcslms-gui.zip "!ARTIFACTS_DIR!\\mcslms-gui-!VERSION_TAG!.zip" >nul
|
|
|
|
|
echo ✓ GUI ZIP
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
REM 生成清单文件
|
|
|
|
|
echo MCSLMS Release Manifest - !VERSION_TAG! > "!ARTIFACTS_DIR!\\manifest.txt"
|
|
|
|
|
echo Build ID: %BUILD_NUMBER% >> "!ARTIFACTS_DIR!\\manifest.txt"
|
|
|
|
|
echo 发布时间: %date% %time% >> "!ARTIFACTS_DIR!\\manifest.txt"
|
|
|
|
|
echo. >> "!ARTIFACTS_DIR!\\manifest.txt"
|
|
|
|
|
echo 制品列表: >> "!ARTIFACTS_DIR!\\manifest.txt"
|
|
|
|
|
for %%F in (!ARTIFACTS_DIR!\\*) do echo %%~nxF >> "!ARTIFACTS_DIR!\\manifest.txt"
|
|
|
|
|
|
|
|
|
|
echo.
|
|
|
|
|
echo 制品目录内容:
|
|
|
|
|
dir /B "!ARTIFACTS_DIR!"
|
|
|
|
|
|
|
|
|
|
REM URL编码凭据
|
|
|
|
|
for /f %%i in ('powershell -NoLogo -NoProfile -Command "[Console]::Out.Write([uri]::EscapeDataString($env:EDUCODER_USER))"') do set USER_ENC=%%i
|
|
|
|
|
for /f %%i in ('powershell -NoLogo -NoProfile -Command "[Console]::Out.Write([uri]::EscapeDataString($env:EDUCODER_PASS))"') do set PASS_ENC=%%i
|
|
|
|
|
|
|
|
|
|
echo.
|
|
|
|
|
echo ============================================
|
|
|
|
|
echo 推送到头歌 release 分支
|
|
|
|
|
echo ============================================
|
|
|
|
|
|
|
|
|
|
git config user.name "Jenkins CI"
|
|
|
|
|
git config user.email "jenkins@mcslms.local"
|
|
|
|
|
|
|
|
|
|
REM 创建 orphan 分支只包含制品
|
|
|
|
|
git checkout --orphan release-%BUILD_NUMBER%
|
|
|
|
|
git rm -rf . --ignore-unmatch >nul 2>&1
|
|
|
|
|
git add artifacts/
|
|
|
|
|
git commit -m "release: 发布 !VERSION_TAG! (Build #%BUILD_NUMBER%)"
|
|
|
|
|
|
|
|
|
|
echo 推送到头歌平台...
|
|
|
|
|
git push https://%USER_ENC%:%PASS_ENC%@bdgit.educoder.net/pu6zrsfoy/mcslms.git HEAD:refs/heads/release --force
|
|
|
|
|
|
|
|
|
|
REM 恢复原分支
|
|
|
|
|
git checkout -f develop 2>nul || git checkout -f main 2>nul
|
|
|
|
|
|
|
|
|
|
echo ✓ 制品已推送到头歌 release 分支: !VERSION_TAG!
|
|
|
|
|
'''
|
|
|
|
|
}
|
|
|
|
|
echo '✓ 头歌平台发布成功'
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
echo "⚠ 推送到头歌失败: ${e.message}"
|
|
|
|
|
currentBuild.result = 'UNSTABLE'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
echo '✓ 头歌平台发布成功'
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
echo "⚠ 推送到头歌失败: ${e.message}"
|
|
|
|
|
currentBuild.result = 'UNSTABLE'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -497,6 +542,7 @@ pipeline {
|
|
|
|
|
echo ' - Tomcat: http://localhost:8080/mcslms/'
|
|
|
|
|
echo ' - 测试报告: Jenkins -> Core 测试报告'
|
|
|
|
|
echo ' - SonarQube: http://localhost:9000/dashboard?id=mcslms'
|
|
|
|
|
echo ' - 头歌源码: https://bdgit.educoder.net/pu6zrsfoy/mcslms/tree/main'
|
|
|
|
|
echo ' - 头歌制品: https://bdgit.educoder.net/pu6zrsfoy/mcslms/tree/release'
|
|
|
|
|
echo '=========================================='
|
|
|
|
|
}
|
|
|
|
|
@ -504,10 +550,68 @@ pipeline {
|
|
|
|
|
echo '❌ 构建失败,请检查日志'
|
|
|
|
|
}
|
|
|
|
|
always {
|
|
|
|
|
echo "=== 构建完成: ${env.RELEASE_VERSION} ==="
|
|
|
|
|
// 清理临时目录
|
|
|
|
|
bat 'if exist jpackage-input rmdir /S /Q jpackage-input 2>nul'
|
|
|
|
|
bat 'if exist jpackage-output rmdir /S /Q jpackage-output 2>nul'
|
|
|
|
|
script {
|
|
|
|
|
echo "=== 构建完成: ${env.RELEASE_VERSION} ==="
|
|
|
|
|
|
|
|
|
|
// 清理临时目录
|
|
|
|
|
bat 'if exist jpackage-input rmdir /S /Q jpackage-input 2>nul'
|
|
|
|
|
bat 'if exist jpackage-output rmdir /S /Q jpackage-output 2>nul'
|
|
|
|
|
|
|
|
|
|
// 发送邮件通知
|
|
|
|
|
echo '========== 发送邮件通知 =========='
|
|
|
|
|
def finalResult = currentBuild.result ?: 'SUCCESS'
|
|
|
|
|
def emailSubject = ""
|
|
|
|
|
def emailStatus = ""
|
|
|
|
|
|
|
|
|
|
if (finalResult == 'SUCCESS') {
|
|
|
|
|
emailSubject = "✅ MCSLMS 构建成功 - ${env.RELEASE_VERSION} (Build #${BUILD_NUMBER})"
|
|
|
|
|
emailStatus = "成功"
|
|
|
|
|
} else if (finalResult == 'FAILURE') {
|
|
|
|
|
emailSubject = "❌ MCSLMS 构建失败 - ${env.RELEASE_VERSION} (Build #${BUILD_NUMBER})"
|
|
|
|
|
emailStatus = "失败"
|
|
|
|
|
} else if (finalResult == 'UNSTABLE') {
|
|
|
|
|
emailSubject = "⚠️ MCSLMS 构建不稳定 - ${env.RELEASE_VERSION} (Build #${BUILD_NUMBER})"
|
|
|
|
|
emailStatus = "不稳定"
|
|
|
|
|
} else {
|
|
|
|
|
emailSubject = "ℹ️ MCSLMS 构建完成 - ${env.RELEASE_VERSION} (Build #${BUILD_NUMBER})"
|
|
|
|
|
emailStatus = "完成"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
echo "准备发送邮件: ${emailSubject}"
|
|
|
|
|
echo "收件人: 602924803@qq.com"
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
mail to: '602924803@qq.com',
|
|
|
|
|
subject: emailSubject,
|
|
|
|
|
body: """MCSLMS 项目构建${emailStatus}
|
|
|
|
|
|
|
|
|
|
构建编号: #${BUILD_NUMBER}
|
|
|
|
|
Release 版本: ${env.RELEASE_VERSION}
|
|
|
|
|
构建状态: ${emailStatus}
|
|
|
|
|
构建时间: ${new Date(currentBuild.startTimeInMillis)}
|
|
|
|
|
Git 提交: ${env.GIT_COMMIT ?: 'N/A'}
|
|
|
|
|
|
|
|
|
|
制品列表:
|
|
|
|
|
- mcslms-cli-${env.RELEASE_VERSION}.jar (命令行版本)
|
|
|
|
|
- mcslms-gui-${env.RELEASE_VERSION}.jar (图形界面版本)
|
|
|
|
|
- mcslms-gui-${env.RELEASE_VERSION}.exe (Windows安装包)
|
|
|
|
|
- mcslms-web-${env.RELEASE_VERSION}.war (Web应用版本)
|
|
|
|
|
- mcslms-backend-${env.RELEASE_VERSION}.jar (后端服务)
|
|
|
|
|
- mcslms-app-${env.RELEASE_VERSION}.apk (Android版本)
|
|
|
|
|
|
|
|
|
|
访问地址:
|
|
|
|
|
- Tomcat: http://localhost:8080/mcslms/
|
|
|
|
|
- SonarQube: http://localhost:9000/dashboard?id=mcslms
|
|
|
|
|
- 头歌源码: https://bdgit.educoder.net/pu6zrsfoy/mcslms/tree/main
|
|
|
|
|
- 头歌制品: https://bdgit.educoder.net/pu6zrsfoy/mcslms/tree/release
|
|
|
|
|
|
|
|
|
|
查看构建详情: ${BUILD_URL}
|
|
|
|
|
"""
|
|
|
|
|
echo '✓ 邮件发送成功'
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
echo "⚠️ 邮件发送失败: ${e.message}"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|