Jenkins Share Library教程 —— 企业级 Jenkins Shared Library 实战示例

Jenkins Share Library教程 —— 企业级 Jenkins Shared Library 实战示例

写在前面

好久不见~最近状态稍缓,更新也慢了些,这篇文章同样让大家等了挺久,先跟大家说声抱歉。

如果你认真读了前面几篇,还跟着实践了,那到这里,咱们就要正式开启真正的 “进阶阶段” 啦!

确实,大多数公司内部的 Jenkins Shared Library 不只是简单的“封装几个 stage”而已,它们往往包含:

  • workspace 清理机制(避免磁盘爆满)
  • 缓存/依赖重用逻辑
  • 多分支/多环境配置
  • 动态参数和条件逻辑
  • 流水线钩子(pre/post hooks)
  • 高级通知系统(Slack、邮件、飞书、Teams)

下面,我们可以一起写一个更“企业级”的案例,会让你看懂为什么公司那套 Shared Library 那么复杂了。

目标:构建一个带 workspace 清理、缓存管理、错误恢复、通知系统的可复用 CI Pipeline。

一、项目结构

jenkins-shared-lib-enterprise/ ├── vars/ │   ├── enterprisePipeline.groovy       # 主入口 Pipeline │   ├── workspaceManager.groovy         # 清理与准备工作区 │   ├── notifyManager.groovy            # 通知模块 │   ├── gitHelper.groovy                # Git 拉取与分支操作 ├── src/org/company/ │   ├── Utils.groovy                    # 工具类(时间戳、日志、重试等) │   └── ConfigLoader.groovy             # YAML/JSON 配置读取器 └── resources/templates/     └── notifyTemplate.txt 

二、清理函数

📄 vars/cleanWorkspace.groovy

def call(Map config = [:]) {     def cleanBeforeBuild = config.get('clean', true)     def keepPatterns = config.get('keep', ['.git', '.gradle'])      if (!cleanBeforeBuild) {         echo "⏭️ Skipping workspace cleanup."         echo "✅ Workspace ready at: ${pwd()}"         return     }      echo "🧹 Cleaning workspace, preserving: ${keepPatterns}"      def os = getOS()      if (os == 'Windows') {         cleanWindows(keepPatterns)     } else {         cleanUnix(keepPatterns)     }      echo "✅ Workspace ready at: ${pwd()}" }  // 判断操作系统 private String getOS() {     def osName = System.getProperty('os.name').toLowerCase()     return osName.contains('windows') ? 'Windows' : 'Unix' }  // Unix/Linux/macOS 清理方式 private void cleanUnix(List keepPatterns) {     def patternStr = keepPatterns.join('|')     sh """         echo "Running on Unix/Linux..."         ls -A1 | grep -v -E '^(${patternStr})$' | xargs rm -rf || true     """ }  // Windows 清理方式(使用 cmd 或 PowerShell) private void cleanWindows(List keepPatterns) {     // 转成小写用于比较     def keepSet = keepPatterns.collect { it.toLowerCase() } as Set      // 获取当前目录下所有文件/目录(包括隐藏)     def files = new File(pwd()).listFiles()     if (!files) return      files.each { file ->         def name = file.name.toLowerCase()         if (!keepSet.contains(name)) {             echo "🗑️ Deleting: ${file.name}"             deleteFileOrDir(file)         }     } }  // 安全删除文件或目录(递归) private void deleteFileOrDir(File file) {     try {         if (file.directory) {             file.deleteDir() // 递归删除目录         } else {             file.delete()         }     } catch (Exception e) {         echo "⚠️ Failed to delete ${file.name}: ${e.message}"     } } 

功能说明:

  • 默认在每次构建前清理工作区(但保留 .git.gradle 等缓存目录)

  • 公司里这样做是为了避免:

    • Jenkins 节点磁盘爆满
    • 前次构建残留文件导致构建异常

Jenkinsfile 调用方式

@Library('my-shared-lib') _  pipeline {     agent any       stages {         stage('Cleanup') {             steps {                 script {                     cleanWorkspace(                         clean: true,                         keep: ['.git', '.gradle', 'settings.gradle']                     )                 }             }         }         // ... 其他阶段     } } 

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

Jenkins Share Library教程 —— 企业级 Jenkins Shared Library 实战示例

三、通知模块

📄 vars/notifyManager.groovy

def call(Map args = [:]) {     def status = args.status ?: 'SUCCESS'     def message = args.message ?: "Build completed."     def color = status == 'SUCCESS' ? 'good' : (status == 'FAILURE' ? 'danger' : 'warning')     def project = env.JOB_NAME     def buildUrl = env.BUILD_URL      def fullMessage = """     [${status}] ${project}     ${message}     👉 ${buildUrl}     """     echo "🔔 Notify: ${fullMessage.trim()}" } 

Jenkinsfile 调用方式

@Library('my-shared-lib') _  pipeline {     agent any  // 可以是 linux、windows、docker 等      stages {         stage('Cleanup') {             steps {                 script {                     notifyManager(                         status: 'SUCCESS',                         message: 'Build completed.'                     )                 }             }         }         // ... 其他阶段     } } 

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

Jenkins Share Library教程 —— 企业级 Jenkins Shared Library 实战示例


四、Git 操作封装

📄 vars/gitHelper.groovy

// vars/gitCheckout.groovy def call(Map config = [:]) {     def repo = config.repo     def branch = config.get('branch', 'main')     def credentialsId = config.get('credentialsId', 'git-credentials')      if (!repo) {         error "❌ gitCheckout: 'repo' parameter is required!"     }      echo "🔁 Checking out ${repo} (branch: ${branch})"      checkout([         $class: 'GitSCM',         branches: [[name: branch]],         userRemoteConfigs: [[             url: repo,             credentialsId: credentialsId         ]]     ]) } 

Jenkinsfile 调用方式

@Library('my-shared-lib') _  pipeline {     agent any      options {         skipDefaultCheckout()  // 👈 关键!跳过默认的 SCM 步骤     }      parameters {         string(name: 'GIT_REPO', defaultValue: 'your giturl', description: 'Git repository URL')         string(name: 'GIT_BRANCH', defaultValue: 'master', description: 'Branch to build')     }      stages {         stage('Checkout Code') {             steps {                 script {                     def repo = params.GIT_REPO                     def branch = params.GIT_BRANCH                      echo "🔁 开始拉取代码:${repo} (分支:${branch})"                      // 调用 vars/gitHelper.groovy                     gitHelper(                         repo: repo,                         branch: branch,                         credentialsId: 'gitee-credentials'  // 替换为你的实际凭据 ID                     )                 }             }         }         stage('Debug') {             steps {                 echo "📦 当前路径:${pwd()}"                 bat 'git branch -a'                 bat 'git log --oneline -5'             }         }     }      post {         failure {             echo "❌ 构建失败!"         }     } } 

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

Jenkins Share Library教程 —— 企业级 Jenkins Shared Library 实战示例


五、核心 Pipeline

📄 vars/enterprisePipeline.groovy

import com.company.Utils  def call(Map config = [:], Closure customStages = null) {     echo "repo: ${config.repo}, branch: ${config.branch}"     // 初始化     Utils.printHeader(this, "Initializing Pipeline")     cleanWorkspace([clean: true, keep: ['.git']])     gitHelper([repo: config.repo, branch: config.branch])      // 构建     Utils.printHeader(this, "Build Stage")     try {         bat config.buildCommand ?: 'mvn clean package -DskipTests'     } catch (err) {         notifyManager([status: 'FAILURE', message: "Build failed: ${err.message}"])         error("Build failed.")     }      // 测试     Utils.printHeader(this, "Test Stage")     try {         bat config.testCommand ?: 'mvn compile test'     } catch (err) {         notifyManager([status: 'FAILURE', message: "Tests failed: ${err.message}"])         error("Tests failed.")     }      // 自定义阶段     if (customStages != null) {         Utils.printHeader(this, "Custom Stages")         customStages()     }      // 部署     if (config.deploy == true) {         Utils.printHeader(this, "Deploy Stage")         // bat config.deployCommand ?: './deploy.sh'         notifyManager([status: 'SUCCESS', message: "Deployed successfully!"])     }      // 收尾     def result = currentBuild.result ?: 'SUCCESS'     notifyManager([status: result, message: "Pipeline finished with status: ${result}"])     Utils.printHeader(this, "Cleaning workspace after build")     cleanWorkspace([clean: true]) } 

Jenkinsfile 调用方式

@Library('my-shared-lib') _  pipeline {     agent any     tools {         maven 'maven'     }     parameters {         string(name: 'REPO_URL', defaultValue: 'your giturl', description: 'Git仓库地址')         string(name: 'BRANCH', defaultValue: 'master', description: '分支')     }     stages {         stage('企业流水线') {             steps {                 script {                     enterprisePipeline([                         repo: params.REPO_URL,                         branch: params.BRANCH                     ])                 }             }         }     } } 

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

Jenkins Share Library教程 —— 企业级 Jenkins Shared Library 实战示例

写在最后

本文以 Maven 项目为示例,核心思路可迁移至其他语言项目,后续仍有扩展空间,感兴趣者可自行探索。

感谢你的认真阅读!若文章对你有价值,欢迎文末留言交流,也请帮忙点赞转发,谢谢支持!

发表评论

评论已关闭。

相关文章