共享库 #

共享库(Shared Library)是Jenkins提供的一种代码复用机制,可以将通用的Pipeline代码抽取出来,在多个Pipeline中共享使用。

为什么需要共享库? #

问题场景 #

  • 多个Pipeline重复相同代码
  • 维护困难,修改需要多处同步
  • 代码质量难以保证

解决方案 #

共享库提供:

  • 代码复用
  • 集中维护
  • 版本控制
  • 统一标准

创建共享库 #

目录结构 #

text
shared-library/
├── vars/
│   ├── standardBuild.groovy
│   ├── deployToK8s.groovy
│   └── notifySlack.groovy
├── src/
│   └── org/
│       └── company/
│           ├── Constants.groovy
│           └── Utilities.groovy
└── resources/
    └── templates/
        └── deployment.yaml

目录说明 #

目录 说明
vars/ 全局变量/函数
src/ Groovy类库
resources/ 资源文件

配置共享库 #

全局配置 #

  1. 进入 Manage Jenkins → System
  2. 找到 Global Pipeline Libraries
  3. 添加共享库:
text
Name: my-shared-library
Default version: main
Retrieval method: Modern SCM
  Git:
    Repository URL: https://github.com/org/shared-library.git
    Credentials: github-credentials

在Pipeline中使用 #

groovy
@Library('my-shared-library') _

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                standardBuild()
            }
        }
    }
}

指定版本 #

groovy
@Library('my-shared-library@v1.0') _

@Library('my-shared-library@feature-branch') _

@Library('my-shared-library@abc123') _

动态加载 #

groovy
pipeline {
    agent any
    
    stages {
        stage('Load Library') {
            steps {
                script {
                    library 'my-shared-library'
                }
            }
        }
    }
}

全局变量(vars/) #

简单函数 #

创建 vars/standardBuild.groovy

groovy
def call() {
    sh 'mvn clean package'
}

使用:

groovy
@Library('my-shared-library') _

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                standardBuild()
            }
        }
    }
}

带参数函数 #

groovy
def call(String appName, String version = 'latest') {
    echo "Building ${appName}:${version}"
    sh "mvn clean package -Dapp.name=${appName} -Dapp.version=${version}"
}

使用:

groovy
standardBuild('myapp', '1.0.0')
standardBuild('myapp')

块参数 #

groovy
def call(Closure body) {
    node {
        stage('Setup') {
            sh 'setup.sh'
        }
        body()
        stage('Cleanup') {
            sh 'cleanup.sh'
        }
    }
}

使用:

groovy
standardBuild {
    sh 'mvn clean package'
}

配置参数 #

groovy
def call(Map config) {
    def appName = config.appName ?: 'myapp'
    def version = config.version ?: "${BUILD_NUMBER}"
    def environment = config.environment ?: 'dev'
    
    echo "Building ${appName}:${version} for ${environment}"
    sh "mvn clean package -Dapp.name=${appName} -Dapp.version=${version}"
}

使用:

groovy
standardBuild(
    appName: 'myapp',
    version: '1.0.0',
    environment: 'production'
)

完整示例 #

创建 vars/buildAndDeploy.groovy

groovy
def call(Map config) {
    def appName = config.appName ?: error("appName is required")
    def version = config.version ?: "${BUILD_NUMBER}"
    def environment = config.environment ?: 'dev'
    def skipTests = config.skipTests ?: false
    
    pipeline {
        agent any
        
        environment {
            APP_NAME = "${appName}"
            VERSION = "${version}"
            ENVIRONMENT = "${environment}"
        }
        
        stages {
            stage('Checkout') {
                steps {
                    checkout scm
                }
            }
            
            stage('Build') {
                steps {
                    sh "mvn clean package ${skipTests ? '-DskipTests' : ''}"
                }
            }
            
            stage('Test') {
                when {
                    expression { !skipTests }
                }
                steps {
                    sh 'mvn test'
                }
                post {
                    always {
                        junit '**/target/surefire-reports/*.xml'
                    }
                }
            }
            
            stage('Docker Build') {
                steps {
                    sh "docker build -t ${appName}:${version} ."
                }
            }
            
            stage('Deploy') {
                steps {
                    sh "kubectl set image deployment/${appName} ${appName}=${appName}:${version} -n ${environment}"
                }
            }
        }
        
        post {
            always {
                cleanWs()
            }
        }
    }
}

使用:

groovy
@Library('my-shared-library') _

buildAndDeploy(
    appName: 'myapp',
    version: '1.0.0',
    environment: 'production',
    skipTests: false
)

类库(src/) #

创建类 #

创建 src/org/company/Constants.groovy

groovy
package org.company

class Constants {
    static final String DOCKER_REGISTRY = 'registry.example.com'
    static final String KUBERNETES_NAMESPACE = 'default'
    
    static final Map ENVIRONMENTS = [
        dev: [
            namespace: 'dev',
            replicas: 1
        ],
        staging: [
            namespace: 'staging',
            replicas: 2
        ],
        prod: [
            namespace: 'production',
            replicas: 3
        ]
    ]
}

创建 src/org/company/Utilities.groovy

groovy
package org.company

class Utilities implements Serializable {
    def steps
    
    Utilities(steps) {
        this.steps = steps
    }
    
    def buildDockerImage(String appName, String version) {
        steps.sh "docker build -t ${appName}:${version} ."
    }
    
    def pushDockerImage(String appName, String version, String registry) {
        steps.sh "docker tag ${appName}:${version} ${registry}/${appName}:${version}"
        steps.sh "docker push ${registry}/${appName}:${version}"
    }
    
    def deployToK8s(String appName, String version, String namespace) {
        steps.sh """
            kubectl set image deployment/${appName} \
                ${appName}=${appName}:${version} \
                -n ${namespace}
        """
    }
}

使用类库 #

groovy
@Library('my-shared-library') _
import org.company.Constants
import org.company.Utilities

pipeline {
    agent any
    
    stages {
        stage('Build') {
            steps {
                script {
                    def utils = new Utilities(this)
                    utils.buildDockerImage('myapp', "${BUILD_NUMBER}")
                    utils.pushDockerImage('myapp', "${BUILD_NUMBER}", Constants.DOCKER_REGISTRY)
                }
            }
        }
        
        stage('Deploy') {
            steps {
                script {
                    def utils = new Utilities(this)
                    def env = Constants.ENVIRONMENTS[params.ENVIRONMENT]
                    utils.deployToK8s('myapp', "${BUILD_NUMBER}", env.namespace)
                }
            }
        }
    }
}

资源文件(resources/) #

创建模板 #

创建 resources/templates/deployment.yaml

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ${APP_NAME}
  namespace: ${NAMESPACE}
spec:
  replicas: ${REPLICAS}
  selector:
    matchLabels:
      app: ${APP_NAME}
  template:
    metadata:
      labels:
        app: ${APP_NAME}
    spec:
      containers:
      - name: ${APP_NAME}
        image: ${IMAGE}
        ports:
        - containerPort: 8080

使用资源文件 #

groovy
def call(Map config) {
    def template = libraryResource 'templates/deployment.yaml'
    
    def deployment = template
        .replace('${APP_NAME}', config.appName)
        .replace('${NAMESPACE}', config.namespace)
        .replace('${REPLICAS}', config.replicas.toString())
        .replace('${IMAGE}', "${config.registry}/${config.appName}:${config.version}")
    
    writeFile file: 'deployment.yaml', text: deployment
    sh 'kubectl apply -f deployment.yaml'
}

最佳实践 #

1. 版本控制 #

使用Git管理共享库,并使用标签管理版本。

2. 文档注释 #

groovy
/**
 * 构建并部署应用
 * 
 * @param appName 应用名称
 * @param version 版本号
 * @param environment 部署环境
 * @param skipTests 是否跳过测试
 */
def call(Map config) {
}

3. 参数验证 #

groovy
def call(Map config) {
    if (!config.appName) {
        error "appName is required"
    }
}

4. 错误处理 #

groovy
def call(Map config) {
    try {
        sh 'deploy.sh'
    } catch (e) {
        echo "Deployment failed: ${e.message}"
        throw e
    }
}

5. 单元测试 #

使用JenkinsPipelineUnit测试共享库:

groovy
class StandardBuildTest extends BasePipelineTest {
    @Test
    void testBuild() {
        def script = loadScript('vars/standardBuild.groovy')
        script.call()
        printCallStack()
        assertJobStatusSuccess()
    }
}

完整示例 #

共享库结构 #

text
jenkins-shared-library/
├── vars/
│   ├── standardJavaBuild.groovy
│   ├── dockerBuild.groovy
│   ├── kubernetesDeploy.groovy
│   └── notify.groovy
├── src/
│   └── org/
│       └── company/
│           ├── Constants.groovy
│           └── Utilities.groovy
└── resources/
    └── kubernetes/
        ├── deployment.yaml
        └── service.yaml

使用示例 #

groovy
@Library('jenkins-shared-library@v1.0') _

standardJavaBuild(
    appName: 'myapp',
    environment: 'production',
    skipTests: false
) {
    dockerBuild(
        registry: 'registry.example.com',
        push: true
    )
    
    kubernetesDeploy(
        namespace: 'production',
        replicas: 3
    )
    
    notify(
        slack: true,
        email: true
    )
}

下一步学习 #

小结 #

  • 共享库实现代码复用
  • vars/目录存放全局变量
  • src/目录存放Groovy类
  • resources/目录存放资源文件
  • 使用版本控制管理共享库
  • 遵循最佳实践提高代码质量
最后更新:2026-03-28