持续集成系统jenkins[全局变量|Groovy编程|共享库实践]
BUILD_NUMBER //构建号 BUILD_ID //构建号 BUILD_DISPLAY_NAME //构建显示名称 JOB_NAME //项目名称 EXECUTOR_NUMBER //执行器数量 NODE_NAME //构建节点名称 WORKSPACE //工作目录 JENKINS_HOME //Jenkins home JENKINS_URL //Jenkins地址 BUILD_URL //构建地址 JOB_URL //项目地址
println(env) env.branchName = "develop" env.commitID = "${UUID.randomUUID().toString()}" env.commitID = "${env.commitID.split("-")[0]}" currentBuild.displayName = "#${env.branchName}-${env.commitID}" currentBuild.description = "Trigger by user jenkins \n branch: master" pipeline { agent { label "build"} stages{ stage("test"){ steps{ script{ echo "${BUILD_NUMBER}" echo "${BUILD_ID}" //currentBuild.displayName = "#${env.branchName}-${env.commitID}" //currentBuild.description = "Trigger by user jenkins \n branch: master" echo "当前下载代码分支为: ${env.branchName}" } } } } }
currentbuild变量
result currentResult //构建结果 displayName //构建名称 #111 description //构建描述 duration //持续时间
流水线中变量定义引用
变量的类型:两种类型的变量。
1.Jenkins系统内置变量 (全局变量)
2.Pipeline中定义变量(全局/局部变量)
Jenkins系统内置变量:是Jenkins系统在安装部署后预先定义好的变量。这些变量可以通过Jenkins流水线语法页面看到具体有哪些。这些变量都是全局的可以使用"${env.变量名}"引用。
首先你要先理解pipeline可以用groovy语法来编写,而groovy是一门编程语言。所有的编程语言也都有各自的变量定义方式。 这就容易让大家产生疑惑的地方,pipeline中可以有很多种写法。
def name = "devops"
String name = "devops"
以上这两种写法是一样,def可以自动推导出变量类型,而String这种写法是精确这个变量是一个字符串类型的。
如果你在Jenkins图形界面设置了参数化构建,那么这些参数也都变成了Jenkins全局变量,可以使用与Jenkins内置变量相同的引用方式。
如果在某个stage定义的变量默认是局部变量,在后续的stage中可能语法引用,所以如果需要引用最好定义为全局变量。
全局变量的定义方式:
env.name = "devops"
引用方式: "${env.name}"
总之变量是我们在编写Jenkins流水线是经常用到的。无处不在。如果你要定义全局的变量就用env.变量名的方式定义。 变量也不仅仅只有这几种写法,我建议如果想了解更多,可以多看下groovy这门需要的更多语法。
Groovy编程
参考文档:http://docs.groovy-lang.org/docs/latest/html/documentation/#_map_coercion
http://groovy-lang.org/groovy-dev-kit.html
Groovy是一种功能强大,可选类型和动态 语言,支持Java平台。旨在提高开发人员的生产力得益于简洁,熟悉且简单易学的语法。可以与任何Java程序顺利集成,并立即为您的应用程序提供强大的功能,包括脚本编写功能,特定领域语言编写,运行时和编译时元编程以及函数式编程。
安装
vi /etc/profile export GROOVY_HOME=/usr/local/groovy-3.0.7/ export PATH=$PATH:$GROOVY_HOME/bin source /etc/profile groovysh
注释:
- 单行注释 //
- 多行注释 /**/
数据类型
字符串string
//字符串表示方式: 单引号、双引号、三单双引号。
//定义一个字符串类型变量name String name = 'zhangsan' String name = "zhangsan"
//定义一个变量包含多行内容
String zeyang = """ devops devops """ println(zeyang)
//字符串分割操作
String branchName = "release-1.1.1" println(branchName.split("-")[1]) 效果: [release, 1.1.1] String branchName = "release-1.1.1" println(branchName.split("-")[0]) 效果: [release] -1就是从最后一个开始 println(branchName.split("-")[-1]) 效果: [release] println("${env.JOB_NAME}".split("-")[0])
//是否包含release字符串
println(branchName.contains("release"))
//字符串的长度
println(branchName.size()) println(branchName.length())
//使用变量作为值
def message = "hello ${name}" println(message) println(message.toString())
//获取元素索引值
println(branchName.indexOf("-"))
//判断字符串以DEV结尾/test开头
String jobName = "test-service_DEV" println(jobName.endsWith("DEV")) println(jobName.startsWith("test"))
true true
//字符串增添操作拼接
String log = "error: xxxxxx aa" println(log.minus("a")) println(log - "a") println(log.plus("aa")) println(log + "aa")
//字符串反转倒叙
String nums = "1234567" println(nums.reverse())
列表list
列表的表示: [] [1,2,3,4]
// list // 定义一个list def mylist = [1,2,3,4,4,"devops"] println(mylist) // list的元素增删 println(mylist + "jenkins") println(mylist - "devops") println(mylist << "java") def newlist = mylist.add("gitlab") println(newlist) // 判断元素是否为空 println(mylist.isEmpty()) // 列表去重 println(mylist.unique()) // 列表反转 println(mylist.reverse()) // 列表排序 println(mylist.sort()) // 判断列表是否包含元素 println(mylist.contains("devops")) // 列表的长度 println(mylist.size()) //扩展列表定义方式 String[] stus = ["zhangsan", "lisi","wangwu"] def numList = [1,2,3,4,4,4] as int[] // 通过索引获取列表元素 println(numList[2]) // 计算列表中元素出现的次数 println(numList.count(4))
Scripts not permitted to use staticMethod org.codehaus.groovy.runtime.DefaultGroovyMethods count int[] java.lang.Object. Administrators can decide whether to approve or reject this signature. [Pipeline] End of Pipeline
映射map
types = [“maven”:“mvn”] [:]
// 定义map def mytools = [ "mvn": "/usr/local/maven", "gradle": "/usr/local/gradle" ] // 根据key获取value println(mytools["mvn"]) println(mytools["gradle"]) // 根据key重新赋值 mytools["mvn"] = "/opt/local/maven" println(mytools) mytools.gradle = "/opt/local/gradle" println(mytools) // 获取key的value println(mytools.key("mvn")) println(mytools.get("mvn")) // 判断map是否包含某个key或者value println(mytools.containsKey("gradle")) println(mytools.containsValue("/usr/local/gradle")) // 返回map的key 列表 println(mytools.keySet()) // 根据key删除元素 println(mytools.remove("mvn")) println(mytools)
条件语句
if语句
在Jenkinsfile中可用于条件判断。
/* 定义变量参数branchName 如果branchName 等于dev则打印dev, 如果branchName 等于test则打印test, 上面都不匹配则打印skipdeploy */ String branchName = "dev" if ( branchName == "dev" ){ println("dev....") } else if (branchName == "test"){ println("test....") } else { println("skipdeploy......") }
switch语句
/* 定义参数branchName 匹配 develop 则打印develop ,跳出。 匹配 release 则打印release ,跳出。 默认匹配, 打印 error ,退出。 */ String branchName = "release" switch(branchName) { case "develop": println("develop .....") break case "release": println("release.....") break default: println("error。。。。。。") }
for循环语句
// for // 遍历0-9,打印 for (i=1; i<10; i++ ){ println(i) } // 循环5次 5.times { println("hello") } // 遍历 0-4 5.times { i -> println(i) } // 遍历List def serverList = ["server-1", "server-2", "server-3"] for ( i in serverList){ println(i) } // 使用each遍历map def stus = ["zeyang":"177", "jenkins":"199"] stus.each { k, v -> println(k+"="+v) } // 使用for遍历map for (k in stus.keySet()){ println(k+"="+stus[k]) }
while循环语句
// while 循环 String name = "jenkins" while (name == "jenkins"){ println("true....") name = "lisi" }
异常处理
/* 如果println(a,b)失败(肯定失败,因为有语法错误) catch捕获错误,并打印错误。 finally 总是执行。 */ try { println(a,b) } catch(Exception e) { //如果try里错误,捕获异常信息 println(e) } finally { println("done") }
函数定义与使用
/* def关键字 定义函数名为PrintMes, 带有一个参数msg,语句块内容是打印msg参数的值,返回msg值。 将PrintMsg函数的执行结果返回给response变量。 打印response */ def PrintMsg(msg){ println(msg) return msg } response = PrintMsg("jenkins ok okok!") println(response) 也是可以在spript 中直接用 PrintMag("xx")
Jenkins共享库实践
要先安装git
共享库这并不是一个全新的概念,其实在编程语言Python中,我们可以将Python代码写到一个文件中,当代码数量增加,我们可以将代码打包成模块然后再以import的方式使用此模块中的方法。
在Jenkins中使用Groovy语法,共享库中存储的每个文件都是一个groovy的类,每个文件(类)中包含一个或多个方法。每个方法包含groovy语句块。
可以在Git等版本控制系统中创建一个项目用于存储共享库。共享流水线有助于减少冗余并保持代码整洁。
属性:
- 共享库名称
- 共享库版本
- 共享库地址
├── src │ └── org │ └── devops │ └── tools.groovy ├── vars │ └── GetHosts.groovy │ └── GetCommitId.groovy │ └── resources │ └── org │ └── devops │ └── config.json
库结构:
- src: 类似于java的源码目录,执行流水线时会加载到class路径中。
- vars: 存放全局变量脚本,小的功能函数。
- resources: 存放资源文件,类似于配置信息文件。
共享库配置
1. 创建一个共享库
可以直接在github中创建一个公开类型的仓库,仓库名称自定义。公开类型的仓库是为了便于验证,也可以创建私有类型的,但是需要提前配置好仓库的认证凭据。
2. 创建groovy类文件
参考文件: https://github.com/zeyangli/myjenkinslib/blob/main/src/org/devops/jenkinstest.groovy
直接在github仓库的页面操作即可:
使用共享库
1.gitlab创建组,组里创建项目
1.创建jenkinsfile
在Jenkinsfile中使用@Library('mylib') _
来加载共享库,注意后面符号_
用于加载。 hwf.devops.Tools()就是你gitlab,src里脚本的位置,使用类中的方法 `mytools.PrintMsg(msg)` 。
@Library('hwf') _ def mytools = new hwf.devops.Tools() pipeline { agent { label "build" } stages { stage("build"){ steps{ script{ msg = "hello jenkins" mytools.PrintMsg(msg) } } } } }
2.jenkins里设置共享库
系统设置-->系统配置
- 这里的共享库的名称要和gitlab定义的项目里jenkinsfile里共享库的名称相同
- 版本就是分支的名称
gitlab项目里的地址[这个地址这里错了,需要改]
3.打开jenkins任务流水线,进行设置
- 分支名称和gitlab里面定义的一致
- 脚本路径里的名称要和你gitlab库里定义的一致
运行流水线查看测试结果
共享库扩展
共享库加载
// 加载mylib共享库 @Library('mylib') _ // 加载mylib共享库的1.0版本 @Library('mylib@1.0') _ // 加载多个共享库, mylib共享库的默认版本, yourlib共享库的2.0版本(分支) @Library(['mylib', 'yourlib@2.0']) _
把pipeline定义在变量里在jenkinsfile里引用变量方法
1.Tools.groovy
hwflib/src/hwf/devops/Tools.groovy
package hwf.devops
//打印信息
def PrintMsg(msg) {
println(msg)
return value
}
public String PrintMsg(String value){
println(value);
return value
}
2.Pipeline.groovy
jenkinslib/vars/Pipeline.groovy
import hwf.devops.Tools def call(Map args){ def tools = new Tools() pipeline { agent { label "build"} stages{ stage("build"){ steps{ script{ value = tools.PrintMsg("hwf") println(value) println(args.name) } } } } } }
3.jenkinsfile
jenkinslib/jenkinsfile
@Library("hwf@main") _ demoPipeline( name: "hwf" )
使用resource/里的文件
用法:
1.resources/xxx.json文件
jenkinslib/resources/config.json
{ "name": "jin tian" }
2.vars/Pipeline.groovy
jenkinslib/vars/Pipeline.groovy
import hwf.devops.Tools def call(Map args){ def tools = new Tools() pipeline { agent { label "build"} stages{ stage("build"){ steps{ script{ //加载resource里的文件 config = libraryResource '/config.json' config = readJSON text: config -"\n" value = tools.PrintMsg("hwf") println(config.name) } } } } } }

评论