Jenkins Share Library教程 —— 高级实战与最佳实践教程

写在前面

搞了近一天的PPT,讲真写英文PPT,确实比中文难多了,中午都没休息,最后还是在同事的帮忙下才搞完。

值得说的是,我今天算是见到了,做PPT强的人,是真的强,从色彩搭配到一些图形选择上,真的很丝滑,没一点多余动作,我看他调PPT就像给我化妆一样,一点点的变好看了。

见证成品那一刻,我就真的有那种,“哇,居然可以这么好看的感觉!”,心生羡慕!


项目结构

经过昨天的学习,你现在已经掌握了基础的 Shared Library 概念,接下来我们直接进入 高级实战 + 最佳实践案例

我会一步步讲给你听,像带你写项目一样,所有代码都能直接放进 Jenkins 跑起来。

在你的共享库 Git 仓库中创建以下结构:

jenkins-shared-lib-advanced/
├── vars/
│ ├── ciPipeline.groovy
│ ├── notifySlack.groovy
│ ├── deployApp.groovy
├── src/org/example/
│ └── Utils.groovy
└── resources/templates/
 └── slackMessage.txt

我们会用这套结构完成:

  • 参数化构建
  • 错误处理(try/catch)
  • 构建 + 测试 + 部署 + 通知
  • 可重用 pipeline 封装

编写工具类

? src/org/example/Utils.groovy

package org.example
class Utils {
 static void printHeader(script, String msg) {
 script.echo "========== ${msg} =========="
 }
 static String getTimestamp() {
 return new Date().format("yyyy-MM-dd HH:mm:ss")
 }
}

说明:

  • 所有公共函数写这里(类似工具包)。
  • import org.example.Utils 即可调用。

Jenkinsfile 调用方式

@Library('my-shared-lib') _
import org.example.Utils
pipeline {
 agent any
 stages {
 stage('Demo') {
 steps {
 script {
 Utils.printHeader(this, "开始构建")
 echo "时间:${Utils.getTimestamp()}"
 }
 }
 }
 }
}

运行后,你会在控制台输出看到:


Slack 通知函数(notifySlack.groovy)

? vars/notifySlack.groovy

// vars/sendSlack.groovy
def call(Map config = [:]) {
 def message = config.message ?: "Build finished"
 def status = config.status ?: "SUCCESS"
 def color = config.color ?: (status == "SUCCESS" ? "good" : "danger")
 def channel = config.channel ?: '#builds'
 echo "? Sending Slack message to ${channel}: ${message} (${status})"
 slackSend(
 channel: channel,
 message: message,
 color: color
 )
}

说明:

  • Jenkins要安装Slack Notification Plugin插件
  • config 是参数化对象,可传入 message、status 等。
  • 这里先用 echo 模拟发送 Slack 通知。

Jenkinsfile 调用方式

@Library('my-shared-lib') _
pipeline {
 agent any
 // 可选:启用彩色日志
 options {
 ansiColor('xterm') // 需要安装 AnsiColor 插件
 }
 environment {
 BUILD_TITLE = 'CI Pipeline'
 SLACK_CHANNEL = '#builds'
 }
 stages {
 stage('Build') {
 steps {
 script {
 echo "?️ Building..."
 // 实际构建命令
 // sh 'make build'
 }
 }
 }
 stage('Test') {
 steps {
 script {
 echo "? Running tests..."
 // sh 'exit 1' // 模拟失败,实际替换为 sh 'make test'
 }
 }
 }
 }
 post {
 always {
 script {
 def buildStatus = currentBuild.result ?: 'SUCCESS'
 def color = buildStatus == 'SUCCESS' ? 'good' : 'danger'
 def buildUrl = env.BUILD_URL // 或 currentBuild.rawBuild.absoluteUrl
 def message = "Pipeline ${buildStatus}: <${buildUrl}|${env.JOB_NAME} #${env.BUILD_NUMBER}>"
 sendSlack(
 message: message,
 status: buildStatus,
 color: color
 )
 }
 }
 success {
 echo "\u001B[32m✅ ${env.BUILD_TITLE} 成功!\u001B[0m"
 }
 failure {
 echo "\u001B[31m❌ ${env.BUILD_TITLE} 失败!\u001B[0m"
 }
 }
}

运行后,你会在控制台输出看到:


部署函数(deployApp.groovy)

? vars/deployApp.groovy

def call(Map config = [:]) {
 def envName = config.env ?: 'staging'
 echo "? Deploying application to ${envName}..."
 sh "echo 'Deploy to ${envName} successful!'"
}

Jenkinsfile 调用方式

@Library('my-shared-lib') _
pipeline {
 agent any
 stages {
 stage('deploy') {
 steps {
 script {
 echo "?️ Building..."
 deployApp(
 envName: 'prod'
 )
 }
 }
 }
 }
}

运行后,你会在控制台输出看到:


核心封装 Pipeline

? vars/ciPipeline.groovy

import org.example.Utils
def call(Map config = [:], Closure body = null) {
 pipeline {
 agent any
 parameters {
 string(name: 'BRANCH', defaultValue: 'main', description: 'Git branch to build')
 choice(name: 'DEPLOY_ENV', choices: ['dev', 'staging', 'prod'], description: 'Environment to deploy')
 }
 stages {
 stage('Init') {
 steps {
 script {
 Utils.printHeader(this,"CI Started")
 echo "Branch: ${params.BRANCH}"
 }
 }
 }
 stage('Build') {
 steps {
 script {
 try {
 Utils.printHeader(this,"Build Stage")
 echo 'mvn clean install'
 } catch (err) {
 sendSlack(message: "Build failed!", status: "FAILURE")
 error("Build failed: ${err}")
 }
 }
 }
 }
 stage('Test') {
 steps {
 script {
 try {
 Utils.printHeader(this,"Test Stage")
 echo 'mvn compile test'
 } catch (err) {
 sendSlack(message: "Tests failed!", status: "FAILURE")
 error("Tests failed: ${err}")
 }
 }
 }
 }
 stage('Deploy') {
 when {
 expression { return params.DEPLOY_ENV != 'dev' }
 }
 steps {
 script {
 try {
 deployApp(env: params.DEPLOY_ENV)
 sendSlack(message: "Deployment to ${params.DEPLOY_ENV} successful")
 } catch (err) {
 sendSlack(message: "Deployment failed!", status: "FAILURE")
 error("Deployment failed: ${err}")
 }
 }
 }
 }
 stage('Custom Steps') {
 steps {
 script {
 if (body != null) {
 Utils.printHeader(this,"Running custom steps")
 body()
 }
 }
 }
 }
 }
 post {
 always {
 script {
 sendSlack(
 message: "Pipeline completed at ${Utils.getTimestamp()}",
 status: currentBuild.result ?: 'SUCCESS'
 )
 }
 }
 }
 }
}

? 功能亮点:

  • 支持 Jenkins 参数(BRANCH、DEPLOY_ENV)
  • 内置错误捕获与 Slack 通知
  • 可注入自定义阶段(body)
  • 自动后置通知(post always)

调用示例 Jenkinsfile

@Library('my-shared-lib') _
ciPipeline(env: 'prod') {
 stage('Custom Verification') {
 echo '? Running custom security scan...'
 echo '"Scan complete."'
 }
}

运行后,你会在控制台输出看到:


最佳实践建议(超实用)

类别最佳实践说明
? 目录结构vars/ 放函数入口,src/ 放类让代码更干净、易维护
? 命名规则函数名用动词开头,如 deployApp()runTests()一目了然
? 参数管理Map config + 默认值方式兼容性强
? 错误处理try/catch + notifySlack保证失败有反馈
? 通知用 post 块统一收尾防止遗漏通知
? 测试本地用 Jenkinsfile Runner 测试 Shared Library避免推错到主库
? 版本管理用 tag 固定版本 @Library('lib@v1.2.0')稳定性保障

写在最后

这也许是最近一直想做的事情把,把自己练习和所学,从语雀中移到博客来,坚持输出,如果可以我希望明天的阅读量是200,HH,比昨天强就行。

当然,最近也在尝试收心,收回自己的注意力和能量,虽然说不太明白,但是总体感觉算是舒服把,先甭管别的,感动自己再说吧!

最后,感谢屏幕前认真阅读的你,如果文章对您有帮助,老规矩,还请帮忙点赞转发,谢谢啦!

今天就到这里啦,晚安,好梦!

作者:久曲健原文地址:https://www.cnblogs.com/longronglang/p/19139489

%s 个评论

要回复文章请先登录注册