惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

大猫的无限游戏
大猫的无限游戏
Webroot Blog
Webroot Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
T
Threat Research - Cisco Blogs
V2EX - 技术
V2EX - 技术
L
LINUX DO - 热门话题
Google DeepMind News
Google DeepMind News
Recorded Future
Recorded Future
S
Schneier on Security
I
InfoQ
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
The GitHub Blog
The GitHub Blog
S
Security @ Cisco Blogs
O
OpenAI News
W
WeLiveSecurity
Vercel News
Vercel News
阮一峰的网络日志
阮一峰的网络日志
Simon Willison's Weblog
Simon Willison's Weblog
人人都是产品经理
人人都是产品经理
Cloudbric
Cloudbric
The Last Watchdog
The Last Watchdog
The Hacker News
The Hacker News
Google Online Security Blog
Google Online Security Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
GbyAI
GbyAI
NISL@THU
NISL@THU
T
Tailwind CSS Blog
V
Visual Studio Blog
PCI Perspectives
PCI Perspectives
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Jina AI
Jina AI
D
DataBreaches.Net
B
Blog RSS Feed
N
News and Events Feed by Topic
N
News and Events Feed by Topic
H
Heimdal Security Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
腾讯CDC
Latest news
Latest news
V
Vulnerabilities – Threatpost
Hacker News: Ask HN
Hacker News: Ask HN
WordPress大学
WordPress大学
V
V2EX
aimingoo的专栏
aimingoo的专栏
博客园 - 司徒正美
Apple Machine Learning Research
Apple Machine Learning Research
D
Darknet – Hacking Tools, Hacker News & Cyber Security
The Register - Security
The Register - Security
Help Net Security
Help Net Security

博客园 - 久曲健

我帮你测过了,测试圈排名第二的 Skill 依然很牛逼 我帮你测过了,测试圈排名第一的 Skill 果然牛逼 AI测试不是工具升级,是思维革命:从OpenClaw看测试工程师的生死劫 OpenAI卸载量暴增295%,Claude登顶第一:AI竞争进入价值观分层时代 当测试自动化率达到80%,测试工程师还剩下什么? AI渗透测试工具:从"脚本跑腿"到"Agent大脑"的范式革命 2026年AI测试工具评测:谁在解决问题,谁在割韭菜? 被这些测试框架坑过?我的选型避坑指南 LLM应用测试,终于有了趁手武器?深度评测Product Hunt爆火的LLM Testing Tool 当Claude Code负责人说"编程已解决",测试工程师该慌吗? 4步搞定!人人都能拥有18岁OpenClaw AI女友Clawra 无套路分享|我自用的全套自学视频 + 资料,网盘直接领 某豪猪发的 “跑通了!Deepseek 自动生成测试用例,太牛了!”,看起来好像很厉害的样子! 智驾“内卷”下的压力下:车企如何以AI测试抢占车机质效高地 Jenkins Share Library教程 —— 企业级 Jenkins Shared Library 实战示例 测试人请查收:金融级系统“三高”挑战下的AI测试工具栈与技术内幕 Jenkins Share Library教程 —— 开发入门 记一次AI Agent开发的思维误区 向量数据库 Chroma 和 Milvus的使用
Jenkins Share Library教程 —— 高级实战与最佳实践教程
久曲健 · 2025-10-14 · via 博客园 - 久曲健

image

写在前面

搞了近一天的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()}"
                }
            }
        }
    }
}

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

image


Slack 通知函数

📄 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"
        }
    }
}

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

image


部署函数

📄 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'
                    )
                }
            }
        }

    }

}

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

image


核心封装 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."'
    }
}

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

image

image


最佳实践建议

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

写在最后

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

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

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

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