「Jenkins Pipeline」- 在 Jenkinsfile 中使用共享库

更新日期:2020年03月10日

在Jenkins中,如果共享库被标记为 Load implicitly ,这允许 Pipeline 立即使用共享库中的类和全局变量。

方法一、使用注解(@Library)

要访问其他的共享库,需要在Jenkinsfile中使用@Library注解来指定库名:

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

/* Using a version specifier, such as branch, tag, etc */
@Library('my-shared-library@1.0') _

/* Accessing multiple libraries with one statement */
@Library(['my-shared-library', 'otherlib@abc1234']) _

只要符合Groovy语法规范,注解可以写在脚本中的任何地方。当使用类库(src/)时,通常注解会后续import语句:

@Library('somelib')
import com.mycorp.pipeline.somelib.UsefulClass

# 对于仅定义全局变量(vars/)的共享库,或仅需要使用全局变量的 Jenkinsfile 文件,注释模式 @Library('my-shared-library') _ 可能对于保持代码简洁有用。
# 在本质上,符号 _ 是注解,而不是注释一个不必要的import语句。

# 不建议 import 全局变量/函数,因为这会强制编译器将字段和方法解释为静态(static),即使它们意图需要实例化。 
# 在这种情况下,Groovy 编译器可能会产生令人困惑的错误消息。

在编译脚本期间进行库的解析并加载,这在库开始执行之前。这允许Groovy编译器理解“在静态类型检查中使用的符号”的含义,并允许它们在脚本中的类型声明中使用。例如:

@Library('somelib')
import com.mycorp.pipeline.somelib.Helper

int useSomeLib(Helper helper) {
    helper.prepare()
    return helper.count()
}

echo useSomeLib(new Helper('some text'))

但是全局变量在运行时得到解析。

方法二、动态加载(library)

从 Pipeline: Shared Groovy Libraries 插件的2.7版开始,在脚本中加载(非隐式)共享库有一个新方式:一个library步骤,可以在构建期间的任何时间动态加载库。

对于全局变量

如果只对使用全局变量/函数感兴趣(来自 vars/ 目录),则语法非常简单:

library 'my-shared-library'

此后,脚本可以访问该库中的任何全局变量。

对于类库

这种方法也可以直接使用类(src/),但是麻烦一些。因为库在执行之前,它在脚本编译期间进行了加载和解析。注解@Library在编译期间准备脚本的“classpath”。但是在执行到library时,脚本已经被编译,因此你不能再进行import操作或“静态”引用库中的类型。

但是可以动态地使用库的类(不进行类型检查),从library步骤的返回值通过完全限定名称访问它们。可以使用类似Java的语法调用静态方法:

################################################################################
# 使用类库中的静态方法
################################################################################
library('my-shared-library').com.mycorp.pipeline.Utils.someStaticMethod()

################################################################################
# 你也可以访问「static」字段
# 并且调用构造器,就好像定义了一个名为「new」的「static」方法
################################################################################
def useSomeLib(helper) { // dynamic: cannot declare as Helper
    helper.prepare()
    return helper.count()
}
def lib = library('my-shared-library').com.mycorp.pipeline // preselect the package
echo useSomeLib(lib.Helper.new(lib.Constants.SOME_TEXT))

共享库的版本

Default version

(1)在共享库的配置中,当勾选 Load implicitly 选项时,会使用 Default version 选项。
(2)或者在 Pipeline 中只通过名称引用共享库(@Library('my-shared-library') _),也会使用 Default version 选项。
(3)如果在共享库的配置中,没有定义 Default version 选项,则 Pipeline 必须明确指定版本(@Library('my-shared-library@master') _)。

Allow default version to be overridden

启用 Allow default version to be overridden 后,可以在@Library中覆盖默认的版本。这也允许「Load implicitly」的库加载不同的版本。

library

使用 library 步骤也可以指定版本:library 'my-shared-library@master'

可以通过变量指定版本:library "my-shared-library@$BRANCH_NAME",测试分支使用测试分支的共享库,可以实现多分支不同配置。

还可以从parameters中动态获取分支:

properties([parameters([string(name: 'LIB_VERSION', defaultValue: 'master')])])
library "my-shared-library@${params.LIB_VERSION}"

注意,虽然可以在@Library中覆盖默认的版本,但是library步骤可能无法用来覆盖隐含加载的库的版本:因为在脚本启动时已经加载了库,给定名字的库无法加载两次;

拉取共享库的方法

取回共享库可以使用 SCM Plugin ,将 SCM Plugin 升级到支持新API的版本,以支持任意命名版本(Modern SCM)。目前(04/25/2019)GIT和SVN支持该功能。

对于旧的SCM插件

在这种情况下,可以为该特定 SCM Plugin 的branch/tag/ref任何地方配置${library.yourlibrarynamehere.version}参数。 这样可以确保在检出库的源代码时, SCM Plugin 会扩展此变量以检出适当的库版本。

动态取回

library identifier: 'custom-lib@master', retriever: modernSCM([
   $class: 'GitSCMSource',
   remote: 'git@git.mycorp.com:my-jenkins-utils.git',
   credentialsId: 'my-private-key'
])

参阅「Pipeline Syntax」来获取精准的语法。!!!库的版本必须指定!!!

关于取回方法

有关取回共享库的细节参考官方的「Retrieval Method」文档。

参考文献


ToC

方法一、使用注解(@Library)

方法二、动态加载(library)

对于全局变量

对于类库

共享库的版本

Default version

Allow default version to be overridden

library

拉取共享库的方法

对于旧的SCM插件

动态取回

关于取回方法

参考文献