
Jenkins Pipeline Post 部分完全指南6种条件块掌控构建全生命周期 Post 部分执行逻辑流程图一、核心概念Post 部分的本质与作用1. 定义位置2. 六种条件块及其触发时机二、实战场景一构建失败时自动发送钉钉/邮件通知三、实战场景二归档测试报告与构建产物四、实战场景三根据分支动态执行不同的post操作五、实战场景四Stage 级 Post 实现精准错误处理六、高级技巧post中的异常处理与脚本复用1. 防止post中的脚本二次失败2. 抽取公共post逻辑为共享库 Post 条件块决策矩阵 常见问题排查 总结The Begin点点关注收藏不迷路⬇ ⬇ 底部 ⬇ ⬇很多Jenkins初学者会犯一个致命错误只在stages的steps中编写正常逻辑却忽略了构建**失败、中止或不稳定**时的处理。一旦流水线异常日志丢失、资源残留、通知遗漏等问题接踵而至。post部分正是解决这些问题的利器——它允许你根据构建的**最终状态有条件地**执行清理、通知、归档等收尾操作。 Post 部分执行逻辑流程图先通过一张图理解post在整个Pipeline生命周期中的位置和触发逻辑成功失败不稳定中止成功失败不稳定 Pipeline 启动执行 stages 阶段块所有 stages 执行完毕进入 post 部分判断构建最终状态✅ always 块执行❌ always 块执行⚠️ always 块执行 always 块执行执行 success 块执行 failure 块执行 unstable 块执行 aborted 块执行 cleanup 块无论状态如何更新构建结果 蓝灯 红灯 黄灯核心逻辑post是Pipeline的收尾阶段根据最终构建状态选择性执行不同条件块且cleanup块无论如何都会执行。一、核心概念Post 部分的本质与作用1. 定义位置post部分可以出现在两个层级层级作用域执行时机全局 post整个Pipeline所有stages执行完毕后Stage 级 post单个Stage该Stage执行完毕后立即触发配置示例展示两个层级pipeline{agent any stages{stage(Build){steps{shmvn compile}post{// Stage级别的postsuccess{echoBuild阶段成功}}}}post{// 全局级别的postalways{echo无论成功失败我都在这里等你。}}}2. 六种条件块及其触发时机条件块触发条件不触发场景always无论如何都执行几乎没有例外success构建状态为SUCCESS失败、不稳定、中止failure构建状态为FAILURE成功、不稳定、中止unstable构建状态为UNSTABLE黄色成功、失败、中止aborted构建被手动中止正常结束的任何状态cleanup无论如何都执行在最后类似always但在其他所有条件块之后重要区别always和cleanup看起来相似但cleanup严格在所有其他post条件块之后执行适合做最终的资源清理。二、实战场景一构建失败时自动发送钉钉/邮件通知这是post最经典的应用——构建失败立即通知相关开发者。完整 Pipeline 配置pipeline{agent any stages{stage(Checkout){steps{git url:https://github.com/example/project.git,branch:main}}stage(Build){steps{shmvn clean compile}}stage(Test){steps{shmvn test}}stage(Deploy){steps{shkubectl apply -f deployment.yaml}}}post{// 构建成功记录成功日志success{script{defbuildDurationcurrentBuild.durationString echo✅ 构建成功耗时:${buildDuration}}// 发送成功通知可选emailext(subject:✅ [SUCCESS]${env.JOB_NAME}- Build #${env.BUILD_NUMBER},body:构建成功\n耗时:${currentBuild.durationString}\n链接:${env.BUILD_URL},to:dev-teamcompany.com)}// 构建失败发送告警通知failure{script{deflogcurrentBuild.rawBuild.getLog(50).join(\n)echo❌ 构建失败最后50行日志\n${log}}// 发送钉钉/企业微信通知dingtalk(robot:devops-robot,type:MARKDOWN,title: 构建失败告警,text:[### ❌ 流水线构建失败,- 项目:${env.JOB_NAME},- 构建编号: #${env.BUILD_NUMBER},- 失败阶段:${env.FAILED_STAGE_NAME},- [查看详情](${env.BUILD_URL})].join(\n),atAll:false,atMobiles:[13800138000])}// 构建不稳定标记需要关注unstable{echo⚠️ 构建不稳定测试未通过请检查测试报告。junit allowEmptyResults:true,testResults:**/target/surefire-reports/*.xml}// 构建被中止记录是谁中止的aborted{script{defcausecurrentBuild.rawBuild.getCause(hudson.model.CauseOfInterruption)echo 构建被中止操作用户:${cause?.UserInterruption?.user}}}// 清理工作区无论成败都执行cleanup{echo 执行最终清理...cleanWs(cleanWhenAborted:true,cleanWhenFailure:true,cleanWhenNotBuilt:true,cleanWhenUnstable:true)deleteDir()// 备用清理方案}}}关键变量说明${currentBuild.durationString}构建耗时字符串如 “2 min 15 sec”${env.FAILED_STAGE_NAME}失败的Stage名称${env.BUILD_URL}本次构建的Web URL三、实战场景二归档测试报告与构建产物无论构建成功与否测试报告都应该被保存下来供后续分析。配置示例post{always{// 无论成败都归档测试报告junit(allowEmptyResults:true,keepLongStdio:true,testResults:**/target/surefire-reports/*.xml)// 归档HTML报告publishHTML([allowMissing:true,alwaysLinkToLastBuild:true,keepAll:true,reportDir:target/site/jacoco,reportFiles:index.html,reportName:Code Coverage Report])// 归档构建产物archiveArtifacts artifacts:**/target/*.jar,fingerprint:true}success{// 仅在成功时归档到Nexusscript{defpomreadMavenPom file:pom.xmldefversionpom.versionnexusArtifactUploader(nexusVersion:nexus3,protocol:http,nexusUrl:nexus.company.com:8081,repository:releases,groupId:pom.groupId,artifactId:pom.artifactId,version:version,file:target/${pom.artifactId}-${version}.jar)}}}最佳实践将archiveArtifacts放在always块中确保即使构建失败也能保留产物用于调试。四、实战场景三根据分支动态执行不同的post操作结合when条件可以为不同分支定制部署后操作。配置示例post{success{script{if(env.BRANCH_NAMEmain){// 生产环境推送Docker镜像 部署通知shdocker push myapp:latestslackSend(color:good,message:✅ 生产环境部署成功:${env.JOB_NAME}#${env.BUILD_NUMBER})}elseif(env.BRANCH_NAME.startsWith(release/)){// 预发布环境推送到测试仓库shdocker push myapp:${env.BRANCH_NAME.replace(/,-)}}else{// 开发分支仅构建不推送echo开发分支构建完成不推送镜像}}}failure{script{// 根据分支确定通知对象defnotifyUsers(env.BRANCH_NAMEmain)?all-teamcompany.com:env.CHANGE_AUTHOR_EMAIL// PR构建失败通知提交者emailext(subject:❌ [FAILURE]${env.JOB_NAME}-${env.BRANCH_NAME},to:notifyUsers,body:构建失败请检查:${env.BUILD_URL})}}}五、实战场景四Stage 级 Post 实现精准错误处理全局post适合整体把控但**Stage级post** 可以针对特定阶段做精准处理。配置示例pipeline{agent any stages{stage(Unit Test){steps{shmvn test}post{success{echo单元测试全部通过}failure{error单元测试失败终止流水线// 阻断后续阶段}}}stage(Integration Test){steps{shmvn verify -Pintegration-test}post{unstable{// 集成测试失败标记为不稳定但不阻断部署echo集成测试部分失败流水线标记为不稳定}}}stage(Performance Test){steps{shjmeter -n -t test.jmx -l results.jtl}post{success{// 性能测试通过后自动创建Git Tagscript{defversionreadMavenPom file:pom.xmlshgit tag v${version}shgit push origin v${version}}}failure{// 性能不达标但允许后续阶段继续echo⚠️ 性能测试未达标但流水线继续执行}}}}post{always{echo所有阶段执行完毕执行全局清理...}}}Stage级post优势错误隔离某个阶段失败可以立即处理而非等到全部结束。条件转发测试失败可以标记unstable而非failure让部署阶段仍能执行。六、高级技巧post中的异常处理与脚本复用1. 防止post中的脚本二次失败如果在post的failure块中调用API又失败了可能导致构建状态混乱。使用catchError保护post{failure{script{catchError(buildResult:FAILURE,stageResult:FAILURE){// 即使通知发送失败也保留原始构建状态dingtalk(robot:devops-robot,text:构建失败通知)}}}}2. 抽取公共post逻辑为共享库如果多个项目使用相同的通知逻辑应封装到Jenkins Shared Library中vars/notifyBuildResult.groovydefcall(Map config){pipeline{post{success{slackSend(channel:config.slackChannel?:#devops,color:good,message:✅${env.JOB_NAME}#${env.BUILD_NUMBER}构建成功)}failure{slackSend(channel:config.slackChannel?:#devops-alert,color:danger,message:❌${env.JOB_NAME}#${env.BUILD_NUMBER}构建失败)}}}} Post 条件块决策矩阵构建状态alwayssuccessfailureunstableabortedcleanup SUCCESS✅✅❌❌❌✅ FAILURE✅❌✅❌❌✅ UNSTABLE✅❌❌✅❌✅ ABORTED✅❌❌❌✅✅ 常见问题排查问题原因解决方案post块完全不执行语法错误导致Pipeline解析失败检查post是否与stages同级缩进一致failure块未触发但构建失败构建状态为UNSTABLE而非FAILURE添加unstable条件块或修改测试阈值cleanup中的变量为空构建已中止某些变量未初始化使用try/catch包裹或设置默认值Stage级post和全局post都执行了正常行为两个层级的post都会执行如需避免重复在全局post中检查阶段名通知发送了两次always和success/failure重叠触发不要在always中放通知仅用success/failure 总结通过本文你已经完全掌握Jenkins Pipelinepost部分的使用方法六种条件块always、success、failure、unstable、aborted、cleanup。两个层级全局post控制整个流水线收尾Stage级post实现精准阶段处理。四大实战场景通知告警、产物归档、分支差异化、精确错误处理。防御性编程用catchError保护post内部逻辑避免二次失败覆盖原始状态。核心原则一个健壮的Pipelinepost部分应当和stages部分同样重要。永远不要让构建失败后悄无声息地结束——用post让你的流水线有始有终可追溯、可恢复。The End点点关注收藏不迷路⬆ ⬆ 顶部 ⬆ ⬆