Jenkins实践指南-09-pipeline 扩展
5. pipeline 扩展
如果在大量使用pipelin后,会发现Jenkins内置的功能并不能满足我们的需求,这时就需要pipeline 扩展。
5.1 pipeline中使用函数
pipeline本质上就是一个Groovy脚本
。因此,也可以在pipeline中定义函数,这样就可以使用Groovy的特性了。示例如下所示:
// 定义一个函数
def hello(name="Kevin"){
return "Hello,${name}"
}
pipeline{
agent any
options{
timestamps()
}
stages{
stage("pipeline extend demo"){
steps{
// 调用函数
echo "${hello('Surpass')}"
}
}
}
}
另外也可以将变量定义在environment中,如下所示:
// 定义一个函数
def hello(name="Kevin"){
return "Hello,${name}"
}
pipeline{
agent any
options{
timestamps()
}
environment{
// 调用函数
HELLO=hello("Surpass")
}
stages{
stage("pipeline extend demo"){
steps{
echo "${env.HELLO}"
}
}
}
}
运行结果如下所示:
0501 pipeline中定义函数.png5.2 使用共享库
如果在pipeline中定义的函数具有通用性,那很可能另外一个pipeline也会使用,这个时候该怎么办呢?针对这一问题,Jenkins提供了共享库(Shared Library)
功能,从而可以将重复代码定义一个独立的代码仓库中,其他的pipeline通过摘取加载使用,达到共享功能
。
5.2.1 目录结构
共享库存储库的目录结构如下:
|--src
| └──org
| └──foo
| └──Bar.groovy # org.foo.Bar 类
|--vars
| └──foo.groovy # 全局变量 foo
| └──foo.txt # 全局变更 foo 帮助文档
|--resources
| └──org
| └──foo
| └──bar.json #
以上各目录详细解释如下所示:
-
src
: 该目录是一个标准的Java源码结构。目录中的类称这为库类,在执行pipeline时,将被添加到classpath路径中,文件格式为.groovy
在pipeline中使用时@Library("surpass-shared-library") _,其中
-
代表一次性静态加载src目录下所有代码到classpath中
-
vars
:该目录用于存放pipeline可以直接使用的全局变量
假设现在有一个文件名var/log.groovy
,其文件内容如下所示:
// vars/logger.groovy
def info(message){
println "message is ${message}"
}
在pipeline中,我们可以这样进行调用
logger.info "Hello,Surpass"
其注意事项如下所示:
-
1.每个groovy文件应该是一个Groovy标识符,遵循
camelCased
命名规范 -
2.存在相应的使用帮助文档,可以HTML、Markdown等,但却需要以.txt做为扩展名
-
resources
:该目录允许从外部库中使用该步骤libraryResource
来加载相关联的非groovy文件。目前暂内部库不支持该功能
以上参考来自于:https://www.jenkins.io/doc/book/pipeline/shared-libraries/
5.2.2 创建共享库
按共享库目录分别创建文件,如下所示:
// src/org/surpass/SharedLibrarySample.groovy
package org.surpass
class SharedLibrarySample{
String name
String location
SharedLibrarySample(String name,String location){
this.name=name
this.location=location
}
def greet(){
return "Hello ${this.name},welcome to ${this.location}"
}
}
// var/logger.groovy
def info(message){
println "[INFO] ${message}"
}
def error(message){
println "[ERROR] ${message}"
}
def warning(message){
println "[WARNNING] ${message}"
}
将以上代码推送至代码仓库中,在Jenkins中按以下进行配置:
Manage Jenkins -> Configure System -> Global Pipeline Libraries
0502 共享库配置.png
主要配置说明如下所示:
-
Name
:共享库的唯一标识
,在pipeline中会使用到 -
Default version
:默认版本,可以是branchname、tag等 -
Load implicitly
:隐式加载。若勾选,将自动加载全局共享库,在pipeline中不需要显式引用,就可以直接使用。 -
Allow default version to be overridden
:若勾选,则表示允许默认被 pipeline中的配置覆盖 -
Include @Library changes in job recent changes
:若勾选,则共享库的最近变更信息将会打印在构建日志中 -
Cache fetched versions on controller for quick retrieval
:若勾选,则表示允许从当前节点缓存中加载共享库 -
Retrieval method
:获取共享库代码的方法
5.2.3 使用共享库
使用共享库全局变量的示例如下所示:
@Library("surpass-shared-library") _
pipeline{
agent any
options{
timestamps()
}
stages{
stage("use shared library demo"){
steps{
script{
logger.error "use shared library demo"
}
}
}
}
}
运行结果如下所示:
0503 共享库运行全局变量示例.png使用共享库中类库的示例如下所示:
@Library("surpass-shared-library@master") _
pipeline{
agent any
options{
timestamps()
}
stages{
stage("use shared library demo"){
steps{
script{
def sharedLibraySample=new org.surpass.SharedLibrarySample("Surpass","Shanghai")
def ret=sharedLibraySample.greet()
println "result is ${ret}"
}
}
}
}
}
运行结果如下所示:
0504 共享库运行类库.png 若要使用共享库,需要在pipeline的最上方,使用@Library
指定共享库,以上示例中surpass-shared-library
为Jenkins中配置的共享库唯一标识符。在引入共享库后,就可以在pipeline中直接使用vars
目录中的logger
中的函数了。
通过以上步骤,我们可以总结出,使用共享库的基本步骤为:
- 按照共享给定的源码目录结构,创建实现自身逻辑的代码
- 将共享库代码上传至代码仓库中用以托管
- 在Jenkins中配置共享库信息,用于获取共享库代码
- 在pipeline中使用@Library引用共享库
使用@Library注解可以指定共享库在代码仓库中的版本,示例如下所求:
@Library("surpass-shared-library@<version>") _
其中version可以是以下任意一种
- branch:分支,如
@Library("surpass-shared-library@master") _
- tag:标签,如
@Library("surpass-shared-library@release-v3.5.0") _
- commit id: 提交的commit id,如
@Library("surpass-shared-library@908d5d889bfaa0b5221b66c260a7c004114f0750") _
在一个共享库无法满足要求进,Jenkins也支持添加多个共享库,使用方法如下所求:
@Library(["surpass-shared-library-a","surpass-shared-library-2","surpass-shared-library-3"]) _
若多个共享库存在相同的函数时,则
优先使用先定义的共享库函数
5.2.4 使用共享库实现pipeline 模板
在pipeline 1.2 版本后,可以在共享库定义pipeline。通过该特性,我们可以定义pipeline的模板。示例如下所求:
// vars/pipelineTemplate.groovy
def call(String opType){
if (opType == "build"){
pipeline{
agent any
options{
timestamps()
}
parameters{
string(name:"build",
defaultValue:"generate pipelin template by build",
description:"build demo"
)
}
stages{
stage("build demo"){
steps{
echo "generatePipelineTemplate demo to build"
echo "params is ${params.build}"
}
}
}
}
} else if (opType == "test"){
pipeline{
agent any
options{
timestamps()
}
parameters{
string(name:"test",
defaultValue:"generate pipelin template by test",
description:"test demo"
)
}
stages{
stage("test demo"){
steps{
echo "generatePipelineTemplate demo to test"
echo "params is ${params.test}"
}
}
}
}
} else if (opType == "deploy"){
pipeline{
agent any
options{
timestamps()
}
parameters{
string(name:"deploy",
defaultValue:"generate pipelin template by deploy",
description:"deploy demo"
)
}
stages{
stage("deploy demo"){
steps{
echo "generatePipelineTemplate demo to deploy"
echo "params is ${params.deploy}"
}
}
}
}
}
}
在使用Jenkins时,Jenkinsfile仅有两行
,是不是特别简洁,如下所示:
@Library("surpass-shared-library@master") _
pipelineTemplate("test")
最终运行日志如下所示:
0505 使用共享库生成pipeline 模板.png生成的pipeline项目示意图如下所示:
0506 使用共享库生成pipeline项目示意图.png当项目结构都是非常标准化的时候 ,利用pipeline模板可以批量生成统一的模板,同时也降低了维护pipeline的的成本。