Day2-04月03日 Jenkins Pipeline As Code

实验代码:mypipeline.groovy

时间 标题 内容







上午 |






Pipeline 基础语法 |
1. 什么是Pipeline ? Pipeline的定义
2. 如何使用Jenkinsfile描述Pipeline?
3. 声明式管道与脚本式管道
4. Pipeline语法-Pipeline/Agent/Stages/Stage/Post
5. environment/options/parameters/triggers
6. tools/input/when/script
| | | |
1. Jenkins Pipeline开发技巧
2. 编写一条测试的Pipeline
3. Pipeline 问题排错思路
4. Jenkinsfile的常见管理方式
| | | | | | | | | |

|

下午 |


Groovy编程 |
1. 本地配置Groovy开发环境
2. Groovy数据类型
3. Groovy中的函数定义
4. Groovy中的常用方法
| | —- | —- | —- | | | |
1. Jenkins ShareLibrary 共享库简介
2. 配置Jenkins ShareLibrary使用
3. 熟悉Pipeline 中常用的DSL方法
|

1. 什么是Pipeline ?

Pipeline

Jenkins的核心是Pipeline(流水线项目),实现了Pipeline As Code。即我们将构建部署测试等步骤全部以代码的形式写到Jenkinsfile中。Jenkins在运行Pipeline任务的时候会按照Jenkinsfile中定义的代码顺序执行。写Jenkinsfile是一项很重的工作,如果稍不注意很容易造成Jenkins的流水线任务失败。Jenkinsfile类似于Dockerfile,具有一套特定的语法。

Stage

在Jenkins pipeline中,一条流水线是由多个阶段组成的,每个阶段一个stage。例如:构建、测试、部署等等。

Agent

Jenkins采用分布式架构,分为server节点和agent节点。server节点也是可以运行构建任务的,但我们一般使其主要来做任务的调度。(毕竟server节点挂了就都…)agent节点专门用于任务的执行。随着现在容器的盛行,我们可以将server节点和agent节点在容器或者基于Kubernetes中部署。关于agent节点借助容器可以实现动态的资源分配等等好处。agent节点可以分为静态节点和动态节点。静态节点是固定的一台vm虚机或者容器。动态节点是随着任务的构建来自动创建agent节点。

我们可以根据地铁线路图来理解pipeline :

  • pipeline 等同于 13号线
  • agent 等同于 13号线🚇
  • stages 等同于 13号线完整的站点路线
  • stage 等同于 13号线中的一个站点

image.png

image.png


Pipeline作业

安装Pipeline插件

在创建Pipeline类型的作业的时候,需要提前安装好pipeline插件,不然可能会出现找不到pipeline类型的作业。
进入插件管理, 搜索关键字”pipeline” 。安装后重启一下。
image.png

当Jenkins重启成功后,我们创建一个流水线类型的作业。
image.png
点击创建,会进入作业的配置页面。此时我们可以对比一下pipeline类型的项目和自由风格的项目的区别。

与自由风格项目对比

流水线类型作业
image.png
自由风格类型作业
image.png

总结: General和构建触发器都是相同的, 自由风格的作业需要在UI页面配置详细的构建过程和构建后操作,而流水线类型的作业是直接将构建过程和操作放到了”流水线”中配置,以代码的方式描述流水线


流水线回放功能

借助回放可以修改上次构建所使用的Jenkinsfile代码, 进行更改后可以立即运行进行调试。
image.png


Jenkinsfile

Jenkinsfile的是实现Pipeline as Code的核心功能。 该文件用于描述流水线的过程。以下是一个简单的实例:

  1. pipeline{
  2. //指定运行此流水线的节点
  3. agent { node { label "build"}}
  4. //管道运行选项
  5. options {
  6. skipStagesAfterUnstable()
  7. }
  8. //流水线的阶段
  9. stages{
  10. //阶段1 获取代码
  11. stage("CheckOut"){
  12. steps{
  13. script{
  14. println("获取代码")
  15. }
  16. }
  17. }
  18. stage("Build"){
  19. steps{
  20. script{
  21. println("运行构建")
  22. }
  23. }
  24. }
  25. }
  26. post {
  27. always{
  28. script{
  29. println("流水线结束后,经常做的事情")
  30. }
  31. }
  32. success{
  33. script{
  34. println("流水线成功后,要做的事情")
  35. }
  36. }
  37. failure{
  38. script{
  39. println("流水线失败后,要做的事情")
  40. }
  41. }
  42. aborted{
  43. script{
  44. println("流水线取消后,要做的事情")
  45. }
  46. }
  47. }
  48. }
  • 使用agent{},指定流水线要运行的节点(可以使用名称或者标签)
  • 指定options{} 定义流水线运行时的一些选项
  • 指定stages{}(stages包含多个stage,stage包含steps。是流水线的每个步骤)
  • 指定post{}(定义好此流水线运行成功或者失败后,根据状态做一些任务)

2. Pipeline 开发工具

选择任意pipeline类型的作业,点击“流水线语法”即可进入pipeline开发工具页面。

片段生成器

流水线代码片段生成器, 非常好用。在这里可以找到每个插件以及Jenkins内置的方法的使用方法。使用片段生成器可以根据个人需要生成方法,有些方法来源于插件,则需要先安装相关的插件才能使用哦。
image.png
image.png

声明式语法生成器

可以生成声明式流水线语法的语句块。
image.png

全局变量参考

这些是已经安装的Jenkins插件和Jenkins内置的全局变量清单。
image.png


3. Pipeline的核心语法

声明式流水线的定义, 一个pipeline{}。

  1. pipeline {
  2. //pipeline
  3. }

agent 构建节点

参数:

  • any: 运行在任一可用节点。
  • none:当pipeline全局指定agent为none,则根据每个stage中定义的agent运行(stage必须指定)。
  • label:在指定的标签的节点运行。(标签=分组)
  • node:支持自定义流水线的工作目录。 ```groovy

    pipeline { agent any }

pipeline { agent { label “label Name” } }

三 自定义节点

pipeline { agent { node { label “labelName”, customWorkspace “/opt/agent/workspace” } } }

  1. <a name="EpMqn"></a>
  2. ### stages构建阶段
  3. - 关系: stages > stage > steps > script
  4. - 定义:
  5. - stages:包含多个stage阶段
  6. - stage:包含多个steps步骤
  7. - steps: 包含一组特定的脚本(加上**script后就可以实现在声明式脚本中嵌入脚本式语法**了)
  8. ```groovy
  9. pipeline {
  10. agent { label "build" }
  11. stages {
  12. stage("build") {
  13. steps {
  14. echo "hello"
  15. }
  16. }
  17. }
  18. }

扩展: 在阶段中定义agent

  1. ## 在阶段中定义agent
  2. pipeline {
  3. agent none
  4. stages{
  5. stage('Build'){
  6. agent { label "build" }
  7. steps {
  8. echo "building......"
  9. }
  10. }
  11. }
  12. }

post 构建后操作

  • 定义: 根据流水线的最终状态匹配后做一些操作。
  • 状态:
    • always: 不管什么状态总是执行
    • success: 仅流水线成功后执行
    • failure: 仅流水线失败后执行
    • aborted: 仅流水线被取消后执行
    • unstable:不稳定状态,单侧失败等等
  1. pipeline {
  2. .....
  3. .....
  4. post {
  5. always{
  6. script{
  7. println("流水线结束后,经常做的事情")
  8. }
  9. }
  10. success{
  11. script{
  12. println("流水线成功后,要做的事情")
  13. }
  14. }
  15. failure{
  16. script{
  17. println("流水线失败后,要做的事情")
  18. }
  19. }
  20. aborted{
  21. script{
  22. println("流水线取消后,要做的事情")
  23. }
  24. }
  25. }
  26. }

env 构建时变量

  • 定义: 通过键值对(k-v)格式定义流水线在运行时的环境变量, 分为流水线级别和阶段级别。

流水线级别环境变量参考

  1. pipeline {
  2. environment {
  3. NAME = "zeyang"
  4. VERSION = "1.1.10"
  5. ENVTYPE = "DEV"
  6. }
  7. }

阶段级别环境变量参考

  1. pipeline {
  2. ...
  3. ...
  4. stages {
  5. stage("build"){
  6. environment {
  7. VERSION = "1.1.20"
  8. }
  9. steps {
  10. script {
  11. echo "${VERSION}"
  12. }
  13. }
  14. }
  15. }
  16. }

options 运行时选项

  1. ## 设置保存最近的记录
  2. options { buildDiscarder(logRotator(numToKeepStr: '1')) }
  3. ## 禁止并行构建
  4. options { disableConcurrentBuilds() }
  5. ## 跳过默认的代码检出
  6. options { skipDefaultCheckout() }
  7. ## 设定流水线的超时时间(可用于阶段级别)
  8. options { timeout(time: 1, unit: 'HOURS') }
  9. ## 设定流水线的重试次数(可用于阶段级别)
  10. options { retry(3) }
  11. ## 设置日志时间输出(可用于阶段级别)
  12. options { timestamps() }

参考:

  1. pipeline {
  2. options {
  3. disableConcurrentBuilds()
  4. skipDefaultCheckout()
  5. timeout(time: 1, unit: 'HOURS')
  6. }
  7. stages {
  8. stage("build"){
  9. options {
  10. timeout(time: 5, unit: 'MINUTES')
  11. retry(3)
  12. timestamps()
  13. }
  14. }
  15. }
  16. }
  17. }

FAQ: timestamps 报错, 需要安装插件 **Timestamper**

  1. WorkflowScript: 21: Invalid option type "timestamps". Valid option types: [authorizationMatrix, buildDiscarder, catchError, checkoutToSubdirectory, disableConcurrentBuilds, disableResume, durabilityHint, lock, overrideIndexTriggers, parallelsAlwaysFailFast, preserveStashes, quietPeriod, rateLimitBuilds, retry, script, skipDefaultCheckout, skipStagesAfterUnstable, timeout, waitUntil, warnError, withChecks, withContext, withCredentials, withEnv, wrap, ws] @ line 21, column 3.
  2. timestamps()
  3. ^

image.png


休息20分钟 11点继续


parameters 流水线参数

  • 定义: 流水线在运行时设置的参数,UI页面的参数。所有的参数都存储在params对象中。
  • 将web ui页面中定义的参数,以代码的方式定义。
  1. pipeline {
  2. agent any
  3. parameters {
  4. string(name: 'VERSION', defaultValue: '1.1.1', description: '')
  5. }
  6. stages {
  7. stage("Build"){
  8. steps {
  9. echo "${params.VERSION}"
  10. }
  11. }
  12. }
  13. }

FAQ: 没有找到相关的环境变量, 这个是我们在parameters中引用了流水线中的变量导致的,可能因为加载顺序不同导致的,解决方法是可以在pipeline{} 外部定义变量进行引用。

  1. roovy.lang.MissingPropertyException: No such property: DEPLOY_DESC for class: groovy.lang.Binding
  2. at groovy.lang.Binding.getVariable(Binding.java:63)

triggers 触发器

  • 流水线的触发方式
    • cron 定时触发: triggers { cron('H */7 * * 1-5') }
    • pollSCM: triggers { pollSCM('H */7 * * 1-5') } ```groovy

      upstream

triggers { upstream(upstreamProjects: ‘job1,job2’, threshold: hudson.model.Result.SUCCESS) }

  1. demo
  2. ```groovy
  3. pipeline {
  4. agent any
  5. triggers {
  6. cron('H */7 * * 1-5')
  7. }
  8. stages {
  9. stage('build') {
  10. steps {
  11. echo 'Hello World'
  12. }
  13. }
  14. }
  15. }

input 流水线交互

参数解析

  • message: 提示信息
  • ok: 表单中确认按钮的文本
  • submitter: 提交人,默认所有人可以
  • parameters: 交互时用户选择的参数
    1. pipeline {
    2. agent any
    3. stages {
    4. stage('Deploy') {
    5. input {
    6. message "是否继续发布"
    7. ok "Yes"
    8. submitter "zeyang,aa"
    9. parameters {
    10. string(name: 'ENVTYPE', defaultValue: 'DEV', description: 'env type..[DEV/STAG/PROD]')
    11. }
    12. }
    13. steps {
    14. echo "Deploy to ${ENVTYPE}, doing......."
    15. }
    16. }
    17. }
    18. }

when 阶段运行控制

判断条件

  • 根据环境变量判断
  • 根据表达式判断
  • 根据条件判断(not/allOf/anyOf) ```groovy pipeline { agent any stages {
    1. stage('Build') {
    2. steps {
    3. echo 'build......'
    4. }
    5. }
    6. stage('Deploy') {
    7. when {
    8. environment name: 'DEPLOY_TO', value: 'DEV'
    9. }
    10. steps {
    11. echo 'Deploying.......'
    12. }
    13. }
    } }

allOf 条件全部成立

when { allOf { environment name: ‘CAN_DEPLOY’, value: ‘true’ environment name: ‘DEPLOY_ENV’, value: ‘dev’ } }

anyOf 条件其中一个成立

when { anyOf { environment name: ‘CAN_DEPLOY’, value: ‘true’ environment name: ‘DEPLOY_ENV’, value: ‘dev’ } }

  1. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/2584012/1617420741700-e23e84c7-937e-4e39-93d2-723d6e2e0503.png#align=left&display=inline&height=252&id=bnlI8&originHeight=503&originWidth=1225&size=58063&status=done&style=none&width=612.5)
  2. <a name="UGrKY"></a>
  3. ### parallel 阶段并行
  4. 场景: 自动化测试,多主机并行发布。
  5. ```groovy
  6. pipeline {
  7. agent any
  8. stages {
  9. stage('Parallel Stage') {
  10. failFast true
  11. parallel {
  12. stage('windows') {
  13. agent {
  14. label "master"
  15. }
  16. steps {
  17. echo "windows"
  18. }
  19. }
  20. stage('linux') {
  21. agent {
  22. label "build"
  23. }
  24. steps {
  25. echo "linux"
  26. }
  27. }
  28. }
  29. }
  30. }
  31. }

image.png

4.流水线全局变量参考

内置变量

  1. BUILD_NUMBER //构建号
  2. BUILD_ID //构建号
  3. BUILD_DISPLAY_NAME //构建显示名称
  4. JOB_NAME //项目名称
  5. EXECUTOR_NUMBER //执行器数量
  6. NODE_NAME //构建节点名称
  7. WORKSPACE //工作目录
  8. JENKINS_HOME //Jenkins home
  9. JENKINS_URL //Jenkins地址
  10. BUILD_URL //构建地址
  11. JOB_URL //项目地址

currentbuild变量

  1. result currentResult //构建结果
  2. displayName //构建名称 #111
  3. description //构建描述
  4. duration //持续时间

image.png


流水线中变量定义引用



变量的类型:两种类型的变量。
1.Jenkins系统内置变量 (全局变量)
2.Pipeline中定义变量(全局/局部变量)

Jenkins系统内置变量:是Jenkins系统在安装部署后预先定义好的变量。这些变量可以通过Jenkins流水线语法页面看到具体有哪些。这些变量都是全局的可以使用”${env.变量名}引用。

Pipeline中的变量:

首先你要先理解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这门需要的更多语法。


5. DSL方法

此处不做本次课强制要求,暂时先了解即可,后面做实验会用到的。

JSON数据格式解析

插件: Pipeline Utils Steps

  1. // 插件
  2. def response = readJSON text: "${scanResult}"
  3. println(scanResult)
  4. //原生方法
  5. import groovy.json.*
  6. @NonCPS
  7. def GetJson(text){
  8. def prettyJson = JsonOutput.prettyPrint(text)
  9. new JsonSlurperClassic().parseText(prettyJson)
  10. }

流水线中使用凭据

  1. withCredentials([string(credentialsId: "xxxxx", variable: "sonarToken")]) {
  2. println(sonarToken)
  3. }

代码管理下载代码

  1. //Git
  2. checkout([$class: 'GitSCM', branches: [[name: "brnachName"]],
  3. doGenerateSubmoduleConfigurations: false,
  4. extensions: [], submoduleCfg: [],
  5. userRemoteConfigs: [[credentialsId: "${credentialsId}",
  6. url: "${srcUrl}"]]])
  7. //Svn
  8. checkout([$class: 'SubversionSCM', additionalCredentials: [],
  9. filterChangelog: false, ignoreDirPropChanges: false,
  10. locations: [[credentialsId: "${credentialsId}",
  11. depthOption: 'infinity', ignoreExternalsOption: true,
  12. remote: "${svnUrl}"]], workspaceUpdater: [$class: 'CheckoutUpdater']]
  13. )

展示HTML报告

插件:

  1. publishHTML([allowMissing: false,
  2. alwaysLinkToLastBuild: false,
  3. keepAll: true,
  4. reportDir: './report/',
  5. reportFiles: "a.html, b.html",
  6. reportName: 'InterfaceTestReport',
  7. reportTitles: 'HTML'])

获取当前的管道运行用户

插件:build user vars

  1. wrap([$class: 'BuildUser']){
  2. echo "full name is $BUILD_USER"
  3. echo "user id is $BUILD_USER_ID"
  4. echo "user email is $BUILD_USER_EMAIL"
  5. }

使用HttpRequest发起请求

插件: HTTP Request

  1. ApiUrl = "http://xxxxxx/api/project_branches/list?project=${projectName}"
  2. Result = httpRequest authentication: 'xxxxxxxxx',
  3. quiet: true,
  4. contentType: 'APPLICATION_JSON' ,
  5. url: "${ApiUrl}"

6. Groovy编程

参考文档:http://docs.groovy-lang.org/docs/latest/html/documentation/#_map_coercion
http://groovy-lang.org/groovy-dev-kit.html

Groovy是一种功能强大,可选类型和动态 语言,支持Java平台。旨在提高开发人员的生产力得益于简洁,熟悉且简单易学的语法。可以与任何Java程序顺利集成,并立即为您的应用程序提供强大的功能,包括脚本编写功能,特定领域语言编写,运行时和编译时元编程以及函数式编程。

image.png

安装

  • 下载安装包(先安装JDK)
  • 解压安装包 获取安装包bin目录
  • 设置环境变量写入/etc/profile文件

https://groovy.apache.org/download.html

  1. vi /etc/profile
  2. export GROOVY_HOME=/usr/local/groovy-3.0.7/
  3. export PATH=$PATH:$GROOVY_HOME/bin
  4. source /etc/profile
  5. groovysh

注释:

  • 单行注释 //
  • 多行注释 /**/

数据类型

字符串string

字符串表示方式: 单引号、双引号、三单双引号。

  1. //定义一个字符串类型变量name
  2. String name = 'zhangsan'
  3. String name = "zhangsan"
  4. //定义一个变量包含多行内容
  5. String zeyang = """
  6. devops
  7. """
  8. println(zeyang)
  9. //字符串分割操作
  10. String branchName = "release-1.1.1"
  11. println(branchName.split("-"))
  12. println(branchName.split("-")[-1])
  13. println("${env.JOB_NAME}".split("-")[0])
  14. //是否包含release字符串
  15. println(branchName.contains("release"))
  16. //字符串的长度
  17. println(branchName.size())
  18. println(branchName.length())
  19. //使用变量作为值
  20. def message = "hello ${name}"
  21. println(message)
  22. println(message.toString())
  23. //获取元素索引值
  24. println(branchName.indexOf("-"))
  25. //判断字符串以DEV结尾
  26. String jobName = "test-service_DEV"
  27. println(jobName.endsWith("DEV"))
  28. //字符串增添操作
  29. String log = "error: xxxxxx aa"
  30. println(log.minus("a"))
  31. println(log - "a")
  32. println(log.plus("aa"))
  33. println(log + "aa")
  34. //字符串反转
  35. String nums = "1234567"
  36. println(nums.reverse())

列表list

列表的表示: [] [1,2,3,4]

  1. // list
  2. // 定义一个list
  3. def mylist = [1,2,3,4,4,"devops"]
  4. println(mylist)
  5. // list的元素增删
  6. println(mylist + "jenkins")
  7. println(mylist - "devops")
  8. println(mylist << "java")
  9. def newlist = mylist.add("gitlab")
  10. println(newlist)
  11. // 判断元素是否为空
  12. println(mylist.isEmpty())
  13. // 列表去重
  14. println(mylist.unique())
  15. // 列表反转
  16. println(mylist.reverse())
  17. // 列表排序
  18. println(mylist.sort())
  19. // 判断列表是否包含元素
  20. println(mylist.contains("devops"))
  21. // 列表的长度
  22. println(mylist.size())
  23. //扩展列表定义方式
  24. String[] stus = ["zhangsan", "lisi","wangwu"]
  25. def numList = [1,2,3,4,4,4] as int[]
  26. // 通过索引获取列表元素
  27. println(numList[2])
  28. // 计算列表中元素出现的次数
  29. println(numList.count(4))
  1. 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.
  2. [Pipeline] End of Pipeline

映射map

types = [“maven”:“mvn”] [:]

  1. // 定义map
  2. def mytools = [ "mvn": "/usr/local/maven",
  3. "gradle": "/usr/local/gradle" ]
  4. // 根据key获取value
  5. println(mytools["mvn"])
  6. println(mytools["gradle"])
  7. // 根据key重新赋值
  8. mytools["mvn"] = "/opt/local/maven"
  9. println(mytools)
  10. mytools.gradle = "/opt/local/gradle"
  11. println(mytools)
  12. // 获取key的value
  13. println(mytools.key("mvn"))
  14. println(mytools.get("mvn"))
  15. // 判断map是否包含某个key或者value
  16. println(mytools.containsKey("gradle"))
  17. println(mytools.containsValue("/usr/local/gradle"))
  18. // 返回map的key 列表
  19. println(mytools.keySet())
  20. // 根据key删除元素
  21. println(mytools.remove("mvn"))
  22. println(mytools)

条件语句

if语句

在Jenkinsfile中可用于条件判断。

  1. /*
  2. 定义变量参数branchName
  3. 如果branchName 等于dev则打印dev,
  4. 如果branchName 等于test则打印test,
  5. 上面都不匹配则打印skipdeploy
  6. */
  7. String branchName = "dev"
  8. if ( branchName == "dev" ){
  9. println("dev....")
  10. } else if (branchName == "test"){
  11. println("test....")
  12. } else {
  13. println("skipdeploy......")
  14. }

switch语句

  1. /*
  2. 定义参数branchName
  3. 匹配 develop 则打印develop ,跳出。
  4. 匹配 release 则打印release ,跳出。
  5. 默认匹配, 打印 error ,退出。
  6. */
  7. String branchName = "release"
  8. switch(branchName) {
  9. case "develop":
  10. println("develop .....")
  11. break
  12. case "release":
  13. println("release.....")
  14. break
  15. default:
  16. println("error。。。。。。")
  17. }

for循环语句

  1. // for
  2. // 遍历0-9,打印
  3. for (i=1; i<10; i++ ){
  4. println(i)
  5. }
  6. // 循环5次
  7. 5.times {
  8. println("hello")
  9. }
  10. // 遍历 0-4
  11. 5.times { i ->
  12. println(i)
  13. }
  14. // 遍历List
  15. def serverList = ["server-1", "server-2", "server-3"]
  16. for ( i in serverList){
  17. println(i)
  18. }
  19. // 使用each遍历map
  20. def stus = ["zeyang":"177", "jenkins":"199"]
  21. stus.each { k, v ->
  22. println(k+"="+v)
  23. }
  24. // 使用for遍历map
  25. for (k in stus.keySet()){
  26. println(k+"="+stus[k])
  27. }

while循环语句

  1. // while 循环
  2. String name = "jenkins"
  3. while (name == "jenkins"){
  4. println("true....")
  5. name = "lisi"
  6. }

异常处理

  1. /*
  2. 如果println(a,b)失败(肯定失败,因为有语法错误)
  3. catch捕获错误,并打印错误。
  4. finally 总是执行。
  5. */
  6. try {
  7. println(a,b)
  8. }
  9. catch(Exception e) {
  10. println(e)
  11. }
  12. finally {
  13. println("done")
  14. }

函数定义与使用

在共享库中每个类中的方法。

  1. /*
  2. def关键字 定义函数名为PrintMes, 带有一个参数msg,语句块内容是打印msg参数的值,返回msg值。
  3. 将PrintMsg函数的执行结果返回给response变量。
  4. 打印response
  5. */
  6. def PrintMsg(msg){
  7. println(msg)
  8. return msg
  9. }
  10. response = PrintMsg("jenkins ok okok!")
  11. println(response)

7. Jenkins共享库实践

共享库这并不是一个全新的概念,其实在编程语言Python中,我们可以将Python代码写到一个文件中,当代码数量增加,我们可以将代码打包成模块然后再以import的方式使用此模块中的方法。

在Jenkins中使用Groovy语法,共享库中存储的每个文件都是一个groovy的类每个文件(类)中包含一个或多个方法。每个方法包含groovy语句块

可以在Git等版本控制系统中创建一个项目用于存储共享库。共享流水线有助于减少冗余并保持代码整洁。

属性:

  • 共享库名称
  • 共享库版本
  • 共享库地址 ```groovy ├── src │ └── org │ └── devops │ └── tools.groovy ├── vars │ └── GetHosts.groovy │ └── GetCommitId.groovy │
    └── resources │ └── org │ └── devops │ └── config.json
  1. 库结构:
  2. - src 类似于java的源码目录,执行流水线时会加载到class路径中。
  3. - vars: 存放全局变量脚本,小的功能函数。
  4. - resources 存放资源文件,类似于配置信息文件。
  5. ---
  6. <a name="PJfiO"></a>
  7. ### 共享库配置
  8. <a name="wR7jJ"></a>
  9. #### 1. 创建一个共享库
  10. 可以直接在github中创建一个公开类型的仓库,**仓库名称自定义**。公开类型的仓库是为了便于验证,也可以创建私有类型的,但是需要提前配置好仓库的认证凭据。
  11. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/2584012/1617438797125-c58c985d-4516-47a5-b590-62d6c427a2fc.png#align=left&display=inline&height=409&id=ddEqA&originHeight=1228&originWidth=1235&size=168292&status=done&style=none&width=411.6666666666667)
  12. <a name="BEnah"></a>
  13. #### 2. 创建groovy类文件
  14. 参考文件: [https://github.com/zeyangli/myjenkinslib/blob/main/src/org/devops/jenkinstest.groovy](https://github.com/zeyangli/myjenkinslib/blob/main/src/org/devops/jenkinstest.groovy)<br />直接在github仓库的页面操作即可: <br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/2584012/1617439790855-cbdde339-d208-45cb-8f44-de8b6576d68d.png#align=left&display=inline&height=184&id=O0pH4&originHeight=552&originWidth=1098&size=53697&status=done&style=none&width=366)
  15. <a name="XJ1Ly"></a>
  16. ### 使用共享库
  17. **Jenkins系统配置 -> Global Pipeline Libraries**
  18. 首先,我们为共享库设置一个名称** mylib** (**自定义,无需与github仓库一致**),**注意这个名称后续在Jenkinsfile中引用**。 再设置一个默认的版本,这里的版本是**分支的名称**。我默认配置的是`main`版本。(github默认版本必须是main
  19. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/2584012/1617439924379-1aa1d9ac-6690-4dcd-bb57-f91135047a34.png#align=left&display=inline&height=230&id=Kp0xE&originHeight=689&originWidth=1834&size=88707&status=done&style=none&width=611.3333333333334)
  20. 接下来我们配置**共享库的仓库地址,**我的仓库在github中,所以这里我填写的是github的方式。(如果你用的是gitlab可以使用gitlab方式或者git方式)。如果仓库是私有的方式,需要在jenkins的凭据中添加一个账号用于下载共享库。
  21. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/2584012/1617440018227-d524ed82-ef28-4b0a-92ec-8ce6fc5ea4f1.png#align=left&display=inline&height=351&id=u2l12&originHeight=1052&originWidth=1798&size=147495&status=done&style=none&width=599.3333333333334)
  22. Jenkinsfile中使用`@Library('mylib') _ `来**加载共享库**,注意后面符号`_`**用于加载**。 类的实例化`def mytools = new org.devops.jenkinstest()`,使用类中的方法 `mytools.PrintMsg(msg)`
  23. ```groovy
  24. @Library('mylib') _
  25. def mytools = new org.devops.jenkinstest()
  26. pipeline {
  27. agent { label "master" }
  28. stages {
  29. stage("build"){
  30. steps{
  31. script{
  32. msg = "hello jenkins"
  33. mytools.PrintMsg(msg)
  34. }
  35. }
  36. }
  37. }
  38. }

运行流水线查看测试结果
image.png
可能遇到的错误: github api问题

  1. 08:42:54 Jenkins-Imposed API Limiter: Current quota for Github API usage has 48 remaining (2 over budget). Next quota of 60 in 53 min. Sleeping for 5 min 27 sec.
  2. 08:42:54 Jenkins is attempting to evenly distribute GitHub API requests. To configure a different rate limiting strategy, such as having Jenkins restrict GitHub API requests only when near or above the GitHub rate limit, go to "GitHub API usage" under "Configure System" in the Jenkins settings.

解决方法: Jenkins系统设置 ,改下参数。
image.png

FAQ: 找不到Github master 分支

  1. Attempting to resolve master as a branch
  2. Attempting to resolve master as a tag
  3. ERROR: Could not resolve master
  4. ERROR: No version master found for library mylib
  5. org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
  6. WorkflowScript: Loading libraries failed

共享库扩展

共享库加载

  1. // 加载mylib共享库
  2. @Library('mylib') _
  3. // 加载mylib共享库的1.0版本
  4. @Library('mylib@1.0') _
  5. // 加载多个共享库, mylib共享库的默认版本, yourlib共享库的2.0版本(分支)
  6. @Library(['mylib', 'yourlib@2.0']) _