pipeline { agent any environment { // 项目配置 PROJECT_NAME = 'novalon-manage-system' FRONTEND_DIR = 'novalon-manage-web' BACKEND_DIR = 'novalon-manage-api' // Node.js 配置 NODE_VERSION = '20' PNPM_VERSION = '8.15.0' // Java 配置 JAVA_VERSION = '17' MAVEN_VERSION = '3.9.0' // Docker 配置 DOCKER_REGISTRY = credentials('docker-registry') DOCKER_IMAGE_FRONTEND = "${PROJECT_NAME}-frontend" DOCKER_IMAGE_BACKEND = "${PROJECT_NAME}-backend" // 数据库配置(用于E2E测试) DB_HOST = 'localhost' DB_PORT = '5432' DB_NAME = 'novalon_test' DB_USER = credentials('db-user') DB_PASSWORD = credentials('db-password') // 测试配置 TEST_TIMEOUT = '30' RETRY_COUNT = '2' } tools { nodejs "NodeJS-${NODE_VERSION}" maven "Maven-${MAVEN_VERSION}" jdk "JDK-${JAVA_VERSION}" } stages { stage('环境准备') { steps { echo '🔧 准备构建环境...' sh ''' # 安装 pnpm npm install -g pnpm@${PNPM_VERSION} # 验证工具版本 node --version pnpm --version java -version mvn --version ''' } } stage('代码检查') { parallel { stage('前端代码检查') { steps { dir(FRONTEND_DIR) { echo '🔍 执行前端代码检查...' sh ''' pnpm install pnpm run lint pnpm run type-check ''' } } } stage('后端代码检查') { steps { dir(BACKEND_DIR) { echo '🔍 执行后端代码检查...' sh 'mvn clean compile -DskipTests' } } } } } stage('单元测试') { parallel { stage('前端单元测试') { steps { dir(FRONTEND_DIR) { echo '🧪 执行前端单元测试...' sh 'pnpm run test:unit' } } post { always { dir(FRONTEND_DIR) { // 发布测试报告 publishHTML(target: [ allowMissing: false, alwaysLinkToLastBuild: true, keepAll: true, reportDir: 'coverage', reportFiles: 'index.html', reportName: '前端单元测试覆盖率报告' ]) } } } } stage('后端单元测试') { steps { dir(BACKEND_DIR) { echo '🧪 执行后端单元测试...' sh 'mvn test' } } post { always { dir(BACKEND_DIR) { // 发布测试报告 junit '**/target/surefire-reports/*.xml' // 发布代码覆盖率报告 publishHTML(target: [ allowMissing: false, alwaysLinkToLastBuild: true, keepAll: true, reportDir: 'target/site/jacoco', reportFiles: 'index.html', reportName: '后端单元测试覆盖率报告' ]) } } } } } } stage('构建') { parallel { stage('前端构建') { steps { dir(FRONTEND_DIR) { echo '📦 构建前端项目...' sh ''' pnpm run build:prod # 创建构建产物归档 tar -czf frontend-dist.tar.gz dist/ ''' } } post { success { archiveArtifacts artifacts: "${FRONTEND_DIR}/frontend-dist.tar.gz", fingerprint: true } } } stage('后端构建') { steps { dir(BACKEND_DIR) { echo '📦 构建后端项目...' sh ''' mvn clean package -DskipTests # 创建构建产物归档 tar -czf backend-jars.tar.gz */target/*.jar ''' } } post { success { archiveArtifacts artifacts: "${BACKEND_DIR}/backend-jars.tar.gz", fingerprint: true } } } } } stage('E2E测试') { steps { echo '🎭 执行E2E测试...' dir(FRONTEND_DIR) { sh ''' # 安装Playwright浏览器 pnpm exec playwright install --with-deps chromium # 执行E2E测试 pnpm run test:e2e:journeys ''' } } post { always { dir(FRONTEND_DIR) { // 发布E2E测试报告 publishHTML(target: [ allowMissing: false, alwaysLinkToLastBuild: true, keepAll: true, reportDir: 'test-results', reportFiles: 'custom-report.html', reportName: 'E2E测试报告' ]) // 归档测试失败截图和视频 archiveArtifacts artifacts: 'test-results/**/*.png, test-results/**/*.webm', allowEmptyArchive: true } } } } stage('构建Docker镜像') { when { branch 'develop' } steps { echo '🐳 构建Docker镜像...' // 构建前端镜像 dir(FRONTEND_DIR) { sh """ docker build -t ${DOCKER_REGISTRY}/${DOCKER_IMAGE_FRONTEND}:${BUILD_NUMBER} . docker tag ${DOCKER_REGISTRY}/${DOCKER_IMAGE_FRONTEND}:${BUILD_NUMBER} ${DOCKER_REGISTRY}/${DOCKER_IMAGE_FRONTEND}:latest """ } // 构建后端镜像 dir(BACKEND_DIR) { sh """ docker build -t ${DOCKER_REGISTRY}/${DOCKER_IMAGE_BACKEND}:${BUILD_NUMBER} . docker tag ${DOCKER_REGISTRY}/${DOCKER_IMAGE_BACKEND}:${BUILD_NUMBER} ${DOCKER_REGISTRY}/${DOCKER_IMAGE_BACKEND}:latest """ } } } stage('推送Docker镜像') { when { branch 'develop' } steps { echo '📤 推送Docker镜像到仓库...' sh """ docker push ${DOCKER_REGISTRY}/${DOCKER_IMAGE_FRONTEND}:${BUILD_NUMBER} docker push ${DOCKER_REGISTRY}/${DOCKER_IMAGE_FRONTEND}:latest docker push ${DOCKER_REGISTRY}/${DOCKER_IMAGE_BACKEND}:${BUILD_NUMBER} docker push ${DOCKER_REGISTRY}/${DOCKER_IMAGE_BACKEND}:latest """ } } stage('部署到测试环境') { when { branch 'develop' } steps { echo '🚀 部署到测试环境...' sh """ # 这里可以添加部署脚本 # 例如:使用docker-compose或kubernetes部署 echo "部署前端镜像: ${DOCKER_REGISTRY}/${DOCKER_IMAGE_FRONTEND}:${BUILD_NUMBER}" echo "部署后端镜像: ${DOCKER_REGISTRY}/${DOCKER_IMAGE_BACKEND}:${BUILD_NUMBER}" """ } } stage('部署到生产环境') { when { branch 'main' } steps { echo '🚀 部署到生产环境...' input message: '确认部署到生产环境?', ok: '确认部署' sh """ # 这里可以添加生产环境部署脚本 # 例如:使用kubernetes进行滚动更新 echo "部署前端镜像: ${DOCKER_REGISTRY}/${DOCKER_IMAGE_FRONTEND}:${BUILD_NUMBER}" echo "部署后端镜像: ${DOCKER_REGISTRY}/${DOCKER_IMAGE_BACKEND}:${BUILD_NUMBER}" """ } } } post { always { echo '🧹 清理工作空间...' cleanWs() } success { echo '✅ 流水线执行成功!' // 可以添加通知,例如发送邮件或Slack消息 } failure { echo '❌ 流水线执行失败!' // 可以添加失败通知 } unstable { echo '⚠️ 流水线执行不稳定!' // 可以添加不稳定状态通知 } } }