Jenkins Pipeline 实战指南
🚀 Jenkins Pipeline 实战指南
从代码到部署,一条流水线搞定所有!让CI/CD像搭积木一样简单
🎯 快速导航
- 📝 Pipeline基础:两种语法大PK
- 🏗️ 流水线设计:多阶段构建的艺术
- 🔗 版本控制集成:Git家族全搞定
- ⚙️ 参数化构建:让Pipeline更智能
📝 Pipeline基础:两种语法大PK
🤔 选择困难症?先了解两兄弟
Jenkins Pipeline有两种写法,就像写作文有记叙文和议论文一样,各有千秋:
特性 | Scripted Pipeline | Declarative Pipeline |
---|---|---|
🎯 学习难度 | 较难(需要Groovy基础) | 简单(结构化语法) |
🔧 灵活性 | 极高(编程式) | 中等(声明式) |
📖 可读性 | 一般 | 优秀 |
🛠️ 维护性 | 较难 | 容易 |
🎨 适用场景 | 复杂逻辑、高度定制 | 标准流程、团队协作 |
🔥 Scripted Pipeline:老司机的选择
基础语法结构
// Jenkinsfile (Scripted)
node {// 这里是你的构建逻辑stage('准备阶段') {echo '开始构建...'}stage('代码检出') {checkout scm}stage('构建') {sh 'mvn clean package'}stage('测试') {sh 'mvn test'}stage('部署') {sh 'docker build -t myapp .'sh 'docker run -d -p 8080:8080 myapp'}
}
高级特性示例
// 复杂的Scripted Pipeline
node {def buildNumber = env.BUILD_NUMBERdef gitCommittry {stage('环境准备') {// 清理工作空间deleteDir()// 设置构建描述currentBuild.description = "构建 #${buildNumber}"}stage('代码检出') {// 检出代码并获取commit信息def scmVars = checkout scmgitCommit = scmVars.GIT_COMMITecho "当前提交: ${gitCommit}"}stage('条件构建') {// 根据分支执行不同逻辑if (env.BRANCH_NAME == 'master') {echo '主分支构建,执行完整流程'sh 'mvn clean package -P production'} else if (env.BRANCH_NAME.startsWith('feature/')) {echo '功能分支构建,快速验证'sh 'mvn clean compile test'} else {echo '其他分支,跳过构建'return}}stage('并行测试') {parallel ('单元测试': {sh 'mvn test'},'集成测试': {sh 'mvn integration-test'},'代码质量检查': {sh 'sonar-scanner'})}} catch (Exception e) {currentBuild.result = 'FAILURE'throw e} finally {// 清理资源sh 'docker system prune -f'}
}
🎨 Declarative Pipeline:新手友好型
基础语法结构
// Jenkinsfile (Declarative)
pipeline {agent anystages {stage('代码检出') {steps {checkout scm}}stage('构建') {steps {sh 'mvn clean package'}}stage('测试') {steps {sh 'mvn test'}post {always {junit 'target/surefire-reports/*.xml'}}}stage('部署') {when {branch 'master'}steps {sh 'docker build -t myapp .'sh 'docker run -d -p 8080:8080 myapp'}}}post {success {echo '构建成功!🎉'}failure {echo '构建失败!😭'}always {cleanWs()}}
}
完整功能示例
// 生产级Declarative Pipeline
pipeline {agent {docker {image 'maven:3.8.1-openjdk-11'args '-v /root/.m2:/root/.m2'}}environment {DOCKER_REGISTRY = 'registry.company.com'APP_NAME = 'my-awesome-app'SONAR_TOKEN = credentials('sonar-token')}parameters {choice(name: 'DEPLOY_ENV',choices: ['dev', 'test', 'prod'],description: '选择部署环境')booleanParam(name: 'SKIP_TESTS',defaultValue: false,description: '是否跳过测试')}triggers {pollSCM('H/5 * * * *') // 每5分钟检查一次代码变更}stages {stage('环境信息') {steps {script {echo "构建环境: ${params.DEPLOY_ENV}"echo "跳过测试: ${params.SKIP_TESTS}"echo "分支: ${env.BRANCH_NAME}"echo "构建号: ${env.BUILD_NUMBER}"}}}stage('代码检出') {steps {checkout scmscript {env.GIT_COMMIT_SHORT = sh(script: 'git rev-parse --short HEAD',returnStdout: true).trim()}}}stage('构建') {steps {sh 'mvn clean compile'}}stage('测试') {when {not { params.SKIP_TESTS }}parallel {stage('单元测试') {steps {sh 'mvn test'}post {always {junit 'target/surefire-reports/*.xml'publishHTML([allowMissing: false,alwaysLinkToLastBuild: true,keepAll: true,reportDir: 'target/site/jacoco',reportFiles: 'index.html',reportName: '代码覆盖率报告'])}}}stage('代码质量') {steps {withSonarQubeEnv('SonarQube') {sh '''mvn sonar:sonar \-Dsonar.projectKey=${APP_NAME} \-Dsonar.host.url=${SONAR_HOST_URL} \-Dsonar.login=${SONAR_TOKEN}'''}}}}}stage('质量门禁') {when {not { params.SKIP_TESTS }}steps {timeout(time: 5, unit: 'MINUTES') {waitForQualityGate abortPipeline: true}}}stage('打包') {steps {sh 'mvn package -DskipTests'archiveArtifacts artifacts: 'target/*.jar', fingerprint: true}}stage('Docker构建') {steps {script {def imageTag = "${env.BUILD_NUMBER}-${env.GIT_COMMIT_SHORT}"def imageName = "${DOCKER_REGISTRY}/${APP_NAME}:${imageTag}"sh "docker build -t ${imageName} ."sh "docker push ${imageName}"env.DOCKER_IMAGE = imageName}}}stage('部署') {when {anyOf {branch 'master'branch 'develop'}}steps {script {def deployScript = """kubectl set image deployment/${APP_NAME} \${APP_NAME}=${env.DOCKER_IMAGE} \-n ${params.DEPLOY_ENV}kubectl rollout status deployment/${APP_NAME} -n ${params.DEPLOY_ENV}"""sh deployScript}}}}post {success {script {def message = """✅ 构建成功!📋 构建信息:• 项目: ${APP_NAME}• 分支: ${env.BRANCH_NAME}• 构建号: ${env.BUILD_NUMBER}• 提交: ${env.GIT_COMMIT_SHORT}• 环境: ${params.DEPLOY_ENV}🔗 查看详情: ${env.BUILD_URL}"""// 发送钉钉通知dingtalk(robot: 'jenkins-bot',type: 'MARKDOWN',title: '构建成功通知',text: message)}}failure {script {def message = """❌ 构建失败!📋 构建信息:• 项目: ${APP_NAME}• 分支: ${env.BRANCH_NAME}• 构建号: ${env.BUILD_NUMBER}• 失败阶段: ${env.STAGE_NAME}🔗 查看日志: ${env.BUILD_URL}console"""dingtalk(robot: 'jenkins-bot',type: 'MARKDOWN',title: '构建失败通知',text: message)}}always {cleanWs()}}
}
🏗️ 流水线设计:多阶段构建的艺术
🎯 阶段设计原则
1. 快速失败原则
pipeline {agent anystages {// 第一阶段:快速检查(1-2分钟)stage('快速验证') {parallel {stage('语法检查') {steps {sh 'mvn validate'}}stage('代码规范') {steps {sh 'checkstyle:check'}}stage('安全扫描') {steps {sh 'dependency-check.sh'}}}}// 第二阶段:编译构建(3-5分钟)stage('编译构建') {steps {sh 'mvn clean compile'}}// 第三阶段:测试验证(5-10分钟)stage('测试验证') {parallel {stage('单元测试') {steps {sh 'mvn test'}}stage('集成测试') {steps {sh 'mvn integration-test'}}}}// 第四阶段:打包部署(2-3分钟)stage('打包部署') {when {branch 'master'}steps {sh 'mvn package'sh 'docker build -t myapp .'}}}
}
2. 并行任务编排
// 复杂并行任务示例
stage('并行处理') {parallel {stage('前端构建') {agent {docker { image 'node:16' }}steps {dir('frontend') {sh 'npm install'sh 'npm run build'sh 'npm run test'}}post {always {publishHTML([allowMissing: false,alwaysLinkToLastBuild: true,keepAll: true,reportDir: 'frontend/coverage',reportFiles: 'index.html',reportName: '前端测试报告'])}}}stage('后端构建') {agent {docker { image 'maven:3.8.1-openjdk-11' }}steps {dir('backend') {sh 'mvn clean package'sh 'mvn test'}}post {always {junit 'backend/target/surefire-reports/*.xml'}}}stage('数据库迁移') {agent {docker { image 'flyway/flyway' }}steps {sh 'flyway migrate'}}stage('文档生成') {agent {docker { image 'python:3.9' }}steps {sh 'pip install mkdocs'sh 'mkdocs build'}post {always {publishHTML([allowMissing: false,alwaysLinkToLastBuild: true,keepAll: true,reportDir: 'site',reportFiles: 'index.html',reportName: 'API文档'])}}}}
}
3. 矩阵构建(多环境测试)
pipeline {agent nonestages {stage('多环境测试') {matrix {axes {axis {name 'JAVA_VERSION'values '8', '11', '17'}axis {name 'OS'values 'linux', 'windows'}}excludes {exclude {axis {name 'JAVA_VERSION'values '8'}axis {name 'OS'values 'windows'}}}stages {stage('测试') {agent {docker {image "openjdk:${JAVA_VERSION}"}}steps {echo "在 ${OS} 系统上使用 Java ${JAVA_VERSION} 进行测试"sh 'mvn test'}}}}}}
}
🔄 流水线优化策略
1. 缓存优化
pipeline {agent anystages {stage('依赖缓存') {steps {script {// Maven依赖缓存def cacheKey = "maven-${hashFiles('**/pom.xml')}"cache(maxCacheSize: 250, caches: [arbitraryFileCache(path: '.m2/repository',fingerprinting: true)]) {sh 'mvn dependency:go-offline'}}}}stage('Node模块缓存') {steps {script {// Node.js依赖缓存def cacheKey = "node-${hashFiles('**/package-lock.json')}"cache(maxCacheSize: 250, caches: [arbitraryFileCache(path: 'node_modules',fingerprinting: true)]) {sh 'npm ci'}}}}}
}
2. 增量构建
stage('增量构建') {steps {script {// 检查文件变更def changedFiles = sh(script: 'git diff --name-only HEAD~1',returnStdout: true).trim().split('\n')def frontendChanged = changedFiles.any { it.startsWith('frontend/') }def backendChanged = changedFiles.any { it.startsWith('backend/') }if (frontendChanged) {echo '前端代码有变更,执行前端构建'sh 'cd frontend && npm run build'}if (backendChanged) {echo '后端代码有变更,执行后端构建'sh 'cd backend && mvn package'}if (!frontendChanged && !backendChanged) {echo '没有代码变更,跳过构建'}}}
}
🔗 版本控制集成:Git家族全搞定
🐙 GitHub集成
1. GitHub Webhook配置
// Jenkinsfile for GitHub
pipeline {agent anytriggers {// GitHub webhook触发githubPush()}stages {stage('GitHub集成') {steps {script {// 获取GitHub信息def prNumber = env.CHANGE_IDdef prTitle = env.CHANGE_TITLEdef prAuthor = env.CHANGE_AUTHORif (prNumber) {echo "处理PR #${prNumber}: ${prTitle} by ${prAuthor}"// 设置GitHub状态githubNotify(status: 'PENDING',description: '构建进行中...',context: 'jenkins/build')}}}}stage('代码检出') {steps {checkout([$class: 'GitSCM',branches: [[name: '*/master']],userRemoteConfigs: [[url: 'https://github.com/company/project.git',credentialsId: 'github-token']]])}}stage('PR检查') {when {changeRequest()}steps {script {// PR特定检查sh 'mvn checkstyle:check'sh 'mvn test'// 发布PR评论pullRequest.comment('✅ 自动化检查通过!')}}}}post {success {script {if (env.CHANGE_ID) {githubNotify(status: 'SUCCESS',description: '构建成功!',context: 'jenkins/build')}}}failure {script {if (env.CHANGE_ID) {githubNotify(status: 'FAILURE',description: '构建失败!',context: 'jenkins/build')pullRequest.comment('❌ 构建失败,请检查代码!')}}}}
}
2. GitHub Actions集成
# .github/workflows/jenkins-trigger.yml
name: Trigger Jenkins Buildon:push:branches: [ master, develop ]pull_request:branches: [ master ]jobs:trigger-jenkins:runs-on: ubuntu-lateststeps:- name: Trigger Jenkins Jobrun: |curl -X POST \-H "Authorization: Bearer ${{ secrets.JENKINS_TOKEN }}" \"${{ secrets.JENKINS_URL }}/job/my-project/build"
🦊 GitLab集成
1. GitLab CI与Jenkins联动
# .gitlab-ci.yml
stages:- trigger- wait- reporttrigger-jenkins:stage: triggerscript:- |JENKINS_JOB_URL="${JENKINS_URL}/job/${CI_PROJECT_NAME}/buildWithParameters"curl -X POST \-H "Authorization: Bearer ${JENKINS_TOKEN}" \-d "GITLAB_BRANCH=${CI_COMMIT_REF_NAME}" \-d "GITLAB_COMMIT=${CI_COMMIT_SHA}" \-d "GITLAB_MR_ID=${CI_MERGE_REQUEST_IID}" \"${JENKINS_JOB_URL}"only:- merge_requests- master- developwait-jenkins:stage: waitscript:- |# 等待Jenkins构建完成while true; doSTATUS=$(curl -s "${JENKINS_URL}/job/${CI_PROJECT_NAME}/lastBuild/api/json" | jq -r '.result')if [ "$STATUS" = "SUCCESS" ]; thenecho "Jenkins构建成功"breakelif [ "$STATUS" = "FAILURE" ]; thenecho "Jenkins构建失败"exit 1fisleep 30done
2. Jenkins中的GitLab集成
// Jenkinsfile for GitLab
pipeline {agent anytriggers {gitlab(triggerOnPush: true,triggerOnMergeRequest: true,branchFilterType: 'All')}stages {stage('GitLab集成') {steps {script {// 更新GitLab提交状态updateGitlabCommitStatus(name: 'jenkins-build',state: 'running')// 获取GitLab信息def mrId = env.gitlabMergeRequestIddef mrTitle = env.gitlabMergeRequestTitledef sourceBranch = env.gitlabSourceBranchdef targetBranch = env.gitlabTargetBranchif (mrId) {echo "处理MR !${mrId}: ${mrTitle}"echo "${sourceBranch} -> ${targetBranch}"}}}}stage('代码检出') {steps {checkout([$class: 'GitSCM',branches: [[name: "origin/${env.gitlabSourceBranch}"]],userRemoteConfigs: [[url: env.gitlabSourceRepoHttpUrl,credentialsId: 'gitlab-token']]])}}stage('MR检查') {when {expression { env.gitlabMergeRequestId != null }}steps {sh 'mvn checkstyle:check'sh 'mvn test'script {// 添加MR评论addGitLabMRComment(comment: '✅ Jenkins自动化检查通过!')}}}}post {success {updateGitlabCommitStatus(name: 'jenkins-build',state: 'success')}failure {updateGitlabCommitStatus(name: 'jenkins-build',state: 'failed')script {if (env.gitlabMergeRequestId) {addGitLabMRComment(comment: '❌ Jenkins构建失败,请检查代码!')}}}}
}
🔀 多仓库协同
// 多仓库构建Pipeline
pipeline {agent anystages {stage('多仓库检出') {parallel {stage('主项目') {steps {dir('main-project') {git(url: 'https://github.com/company/main-project.git',branch: 'master',credentialsId: 'github-token')}}}stage('共享库') {steps {dir('shared-lib') {git(url: 'https://github.com/company/shared-lib.git',branch: 'master',credentialsId: 'github-token')}}}stage('配置仓库') {steps {dir('config') {git(url: 'https://github.com/company/config.git',branch: env.DEPLOY_ENV ?: 'dev',credentialsId: 'github-token')}}}}}stage('依赖构建') {steps {script {// 先构建共享库dir('shared-lib') {sh 'mvn clean install'}// 再构建主项目dir('main-project') {sh 'mvn clean package'}}}}stage('配置合并') {steps {script {// 合并配置文件sh '''cp config/application-${DEPLOY_ENV}.yml main-project/src/main/resources/cp config/docker/Dockerfile-${DEPLOY_ENV} main-project/Dockerfile'''}}}}
}
⚙️ 参数化构建:让Pipeline更智能
🎛️ 参数类型大全
1. 基础参数类型
pipeline {agent anyparameters {// 字符串参数string(name: 'APP_VERSION',defaultValue: '1.0.0',description: '应用版本号')// 文本参数(多行)text(name: 'RELEASE_NOTES',defaultValue: '',description: '发布说明(支持多行)')// 布尔参数booleanParam(name: 'SKIP_TESTS',defaultValue: false,description: '是否跳过测试')// 选择参数choice(name: 'DEPLOY_ENV',choices: ['dev', 'test', 'staging', 'prod'],description: '部署环境')// 密码参数password(name: 'DB_PASSWORD',defaultValue: '',description: '数据库密码')// 文件参数file(name: 'CONFIG_FILE',description: '上传配置文件')}stages {stage('参数展示') {steps {script {echo "应用版本: ${params.APP_VERSION}"echo "部署环境: ${params.DEPLOY_ENV}"echo "跳过测试: ${params.SKIP_TESTS}"echo "发布说明: ${params.RELEASE_NOTES}"}}}}
}
2. 高级参数配置
// 动态参数Pipeline
pipeline {agent anyparameters {// 级联选择参数activeChoice(choiceType: 'PT_SINGLE_SELECT',description: '选择项目',name: 'PROJECT',script: [$class: 'GroovyScript',fallbackScript: [classpath: [],sandbox: false,script: 'return ["项目A", "项目B", "项目C"]'],script: [classpath: [],sandbox: false,script: '''def projects = []def url = "http://api.company.com/projects"def response = new URL(url).textdef json = new groovy.json.JsonSlurper().parseText(response)json.each { project ->projects.add(project.name)}return projects''']])// 依赖选择参数reactiveChoice(choiceType: 'PT_SINGLE_SELECT',description: '选择分支',name: 'BRANCH',referencedParameters: 'PROJECT',script: [$class: 'GroovyScript',fallbackScript: [classpath: [],sandbox: false,script: 'return ["master", "develop"]'],script: [classpath: [],sandbox: false,script: '''def branches = []def project = PROJECTif (project) {def url = "http://api.company.com/projects/${project}/branches"def response = new URL(url).textdef json = new groovy.json.JsonSlurper().parseText(response)json.each { branch ->branches.add(branch.name)}}return branches''']])}stages {stage('动态参数处理') {steps {script {echo "选择的项目: ${params.PROJECT}"echo "选择的分支: ${params.BRANCH}"// 根据参数动态检出代码def repoUrl = "https://github.com/company/${params.PROJECT}.git"checkout([$class: 'GitSCM',branches: [[name: "*/${params.BRANCH}"]],userRemoteConfigs: [[url: repoUrl,credentialsId: 'github-token']]])}}}}
}
🌍 环境变量管理
1. 内置环境变量
stage('环境变量展示') {steps {script {echo "构建信息:"echo " 构建号: ${env.BUILD_NUMBER}"echo " 构建ID: ${env.BUILD_ID}"echo " 构建URL: ${env.BUILD_URL}"echo " 任务名称: ${env.JOB_NAME}"echo " 任务URL: ${env.JOB_URL}"echo " 工作空间: ${env.WORKSPACE}"echo "Git信息:"echo " 分支: ${env.BRANCH_NAME}"echo " 提交: ${env.GIT_COMMIT}"echo " 提交者: ${env.GIT_COMMITTER_NAME}"echo " 提交邮箱: ${env.GIT_COMMITTER_EMAIL}"echo "Jenkins信息:"echo " Jenkins URL: ${env.JENKINS_URL}"echo " 节点名称: ${env.NODE_NAME}"echo " 执行器号: ${env.EXECUTOR_NUMBER}"}}
}
2. 自定义环境变量
pipeline {agent anyenvironment {// 全局环境变量APP_NAME = 'my-awesome-app'DOCKER_REGISTRY = 'registry.company.com'MAVEN_OPTS = '-Xmx1024m -XX:MaxPermSize=256m'// 从凭据获取DOCKER_CREDENTIALS = credentials('docker-registry')SONAR_TOKEN = credentials('sonar-token')// 动态生成BUILD_TIMESTAMP = sh(script: 'date +"%Y%m%d-%H%M%S"',returnStdout: true).trim()// 条件环境变量DEPLOY_ENV = "${env.BRANCH_NAME == 'master' ? 'prod' : 'dev'}"}stages {stage('阶段级环境变量') {environment {// 仅在此阶段有效STAGE_SPECIFIC_VAR = 'stage-value'DATABASE_URL = "jdbc:mysql://db-${DEPLOY_ENV}.company.com:3306/myapp"}steps {script {echo "应用名称: ${env.APP_NAME}"echo "构建时间戳: ${env.BUILD_TIMESTAMP}"echo "部署环境: ${env.DEPLOY_ENV}"echo "数据库URL: ${env.DATABASE_URL}"// 运行时设置环境变量env.DYNAMIC_VAR = "runtime-${env.BUILD_NUMBER}"echo "动态变量: ${env.DYNAMIC_VAR}"}}}stage('环境变量文件') {steps {script {// 生成环境变量文件def envFile = """APP_NAME=${env.APP_NAME}APP_VERSION=${params.APP_VERSION ?: '1.0.0'}BUILD_NUMBER=${env.BUILD_NUMBER}BUILD_TIMESTAMP=${env.BUILD_TIMESTAMP}DEPLOY_ENV=${env.DEPLOY_ENV}GIT_COMMIT=${env.GIT_COMMIT}"""writeFile file: '.env', text: envFile// 在Docker中使用sh 'docker run --env-file .env my-app:latest'}}}}
}
3. 环境变量最佳实践
// 环境变量管理最佳实践
pipeline {agent anyenvironment {// 使用凭据管理敏感信息DB_CREDENTIALS = credentials('database-credentials')API_KEY = credentials('api-key')// 环境特定配置CONFIG_FILE = "config-${env.BRANCH_NAME}.yml"// 版本信息VERSION = sh(script: 'git describe --tags --always',returnStdout: true).trim()}stages {stage('环境验证') {steps {script {// 验证必需的环境变量def requiredVars = ['APP_NAME','DEPLOY_ENV','DB_CREDENTIALS','API_KEY']requiredVars.each { varName ->if (!env[varName]) {error "缺少必需的环境变量: ${varName}"}}echo "✅ 环境变量验证通过"}}}stage('配置文件生成') {steps {script {// 使用模板生成配置文件def configTemplate = libraryResource 'config-template.yml'def config = configTemplate.replace('{{APP_NAME}}', env.APP_NAME).replace('{{VERSION}}', env.VERSION).replace('{{DB_HOST}}', env.DB_CREDENTIALS_USR).replace('{{DB_PASSWORD}}', env.DB_CREDENTIALS_PSW).replace('{{API_KEY}}', env.API_KEY)writeFile file: 'application.yml', text: config}}}stage('安全处理') {steps {script {// 敏感信息脱敏def maskedApiKey = env.API_KEY.replaceAll(/.{4}$/, '****')echo "使用API Key: ${maskedApiKey}"// 临时环境变量withEnv(["TEMP_TOKEN=${UUID.randomUUID().toString()}","SESSION_ID=session-${env.BUILD_NUMBER}"]) {sh 'echo "临时Token: $TEMP_TOKEN"'sh 'echo "会话ID: $SESSION_ID"'}}}}}post {always {script {// 清理敏感信息sh 'rm -f .env application.yml'}}}
}
🎯 总结
🔑 Pipeline核心要点
- 🎨 语法选择:新手用Declarative,老手用Scripted
- 🏗️ 阶段设计:快速失败,并行优化,增量构建
- 🔗 版本控制:深度集成GitHub/GitLab,自动化触发
- ⚙️ 参数化:灵活配置,环境变量管理,安全第一
💡 最佳实践清单
实践项 | 重要性 | 实施建议 |
---|---|---|
🚀 快速反馈 | ⭐⭐⭐⭐⭐ | 5分钟内给出初步结果 |
🔄 并行执行 | ⭐⭐⭐⭐ | 充分利用多核资源 |
📦 缓存优化 | ⭐⭐⭐⭐ | 依赖缓存,构建缓存 |
🔒 安全管理 | ⭐⭐⭐⭐⭐ | 凭据管理,权限控制 |
📊 监控告警 | ⭐⭐⭐ | 构建状态,性能指标 |
🆘 常见问题速查
// Pipeline调试技巧
stage('调试信息') {steps {script {// 打印所有环境变量sh 'printenv | sort'// 打印构建参数params.each { key, value ->echo "参数 ${key}: ${value}"}// 检查文件系统sh 'ls -la'sh 'pwd'sh 'df -h'}}
}// 错误处理
try {sh 'mvn test'
} catch (Exception e) {echo "测试失败: ${e.getMessage()}"currentBuild.result = 'UNSTABLE'
} finally {// 清理资源sh 'docker system prune -f'
}
🎉 恭喜你! 现在你已经掌握了Jenkins Pipeline的核心技能。记住,Pipeline不只是工具,更是一种思维方式。从代码提交到生产部署,让每一步都自动化、可视化、可追溯!
下一步: 开始设计你的第一条生产级Pipeline吧!让CI/CD成为你的超级助手! 🚀
如果这篇文章对你有帮助,别忘了点赞收藏哦!有问题欢迎在评论区交流讨论! 😊