持续集成高级篇之Jenkins参数传入与常见任务

系列目录html

有的童鞋可能已经发现,PipeLine项目与自由式项目相比,可配置的项少了不少,好比说环境变量定义,全部步骤完成后执行动做,拉git代码库等.其实这些功能并无缺,而是配置的方式不同了,之前是经过图形化界面配置,虽然直观简便,可是功能不能包罗万像,对于一些复杂的项目显得捉襟见肘,而Jenkins PipeLine使用代码配置功能更增强大.之后的章节中咱们会介绍经常使用的配置如何经过PipeLine里的Groovy脚原本实现.node

前面讲参数化构建的时候已经讲到对于复杂的构建把一些重复的,经常使用的代码作成变量的重要性,这里讲解如何经过PipeLine方式定义项目级别的参数以及环境变量.git

首先须要说明的是,节点级别和全局级别以及文件参数变量的配置在PipeLine里依然有效,读取的方式也同样,只是会有一些小坑,这里也会介绍程序员

PipeLine中能够定义变量和环境变量,下面分别介绍如何定义变量和环境变动.sql

PipeLine中定义变量

PipeLine中定义变量很是简单,只须要使用def 变量名=变量值的形式便可shell

看以下PipeLine代码(你们本身建立项目)ui

node {
    def hello="world"
    stage("echo"){
        bat "echo $hello"
    }
}

以上脚本中咱们先是定义了一个名为hello的变量,而后经过$变量名方式获取到它,而后把它打印到控制台.插件

有些童鞋对以上代码可能有点懵圈,bat执行的字符串怎么能包含$变量名这样的内容呢,bat不是只能解析%变量名%类型的变量吗.其实是$变量名是groovy脚本插值语法,执行到这行文本的时候groovy就会去尝试解析$变量名,对于本实例,groovy会解析$hello,上面已经定义过,它的值是world,所以 groovy会把 echo $hello先解析为'echo world'这样纯字符串,而后再传给bat执行.code

须要注意的是以上定义的变量并不是环境变量,对于bat脚本,不能经过%变量名%的形式被解析,由于环境变量中不存在这样一个环境变量名,所以bat没法解析它.固然对于定义的节点级别的或者全局的变量bat脚本仍然能够经过%变量名%形式被解析.你们不要迷糊.sqlite

PipeLine中定义环境变量

上面定义变量的方式是定义了一个groovy变量,咱们也说过它不能被传入到脚本内部被解析(好比bat 经过%变量名%形式解析),它必须经过groovy脚本解析成普通字符串而后传给相应的脚本执行程序.实际上PipeLine中也提供了一种建立环境变量的方法.这里咱们就介绍一下.

咱们仍是经过一段demo来说解

node {
    withEnv(['build=Production',
             'DB_ENGINE=sqlite']) {
        stage('Build') {
           bat "echo $build"
        }
    }
}

以上经过WithEnv来定义环境变量,值放在中括号里,你们注意写法是"变量名=变量值",也就是变量名和赋值都放在一个引号内(单引号和双引号均可以),而不是"变量名"="变量值"这种形式,必定要注意.

bat命令里的解析方法是经过$变量名形式,咱们讲过,它是groovy的插件方式,经过这里咱们能够看到,在PipeLine里,环境变量也被看成了普通变量(便可以经过$变量名形式解析).固然咱们说了这里定义的是环境变量,环境变量是能够传入脚本内部被解析的,咱们把bat这段代码改成以下

bat "echo %build%"

控制台仍然可以输出world.

对于powershell脚本能够经过$env:变量名方式获取.可是对于powershell脚本有一个坑必须注意,那就是Powershell获取环境变量名使用$开头,同时groovy脚本插值变量也是以$开头,这就会致使Groovy会尝试解析 powershell的变量,这样显然没法获取正确结果.如何解决这一问题呢?答案是执行powershell脚本的时候使用powershell '要执行的脚本',也即把双引号改成单引号,若是双引号改单引号,则groovy再也不进行插值计算.

最佳实践

1) 前面说过,groovy除了能够获取经过def定义的变量外,也可以获取环境变量,所以建议使用$变量名的方式获取变量的值,这样groovy会提交对它们进行插值计算,这样就弥补了不一样脚本使用环境变量方法不同的问题.同也没必要考虑powrshell 引用变量会被插值计算,必须使用单引号包括脚本的问题,减小脑细胞消耗量.

2) 经过以上咱们能够看到PipeLine里便可以经过def来定义变量,也能够经过WithEnv来定义,实际使用中发现WithEnv更麻烦,全部使用到它的代码块都必须包含在withEnv代码块内,若是嵌套过深,代码可读性很是差.而def便可以声明为全局的(这里说的全局是对整个当前脚本有效),也能够是块级的,而且不用花括号,可读性也更好.

常见任务在PipeLine中的处理

保证某一步骤最终必定执行

咱们知道PipeLine里能够书写Groovy脚本,脚本若是出错则代码将不会再继续往下走,咱们如何保证不论如何最终都会执行某一步动做呢,好比说释放非托管资源,脚本出错时发出邮件通知等,这里其实处理办法很是简单,那就是使用groovy的try finally语法,把最终要执行的代码写在finally里,这对程序员来讲应该很是容易理解.

Script代码块

咱们前面已经说过,能够在jenkins PipeLine里直接执行groovy脚本,若是仅仅是定义一个变量这样简单的动做无所谓,若是有大量的代码和业务逻辑掺杂在一块,则势必影响代码可读性.此时可使用script代码块把要执行的大段groovy脚本包在里面

以下图示

node {
     def hello="world"
    
    stage("echo"){
        
           script{
                for(i=0;i<=3;i++){
                println(i)
            }
           }
       
        bat "echo $version"
    }
   
}

以上咱们把循环语句放在代码块里,println能够把内容打印到Jenkins控制台.

逻辑分支

这里仅仅是列出来但愿引发你们的注意,在脚本式PipeLine里逻辑分支很是简单,只须要使用if分支语句便可,熟悉groovy脚本的童鞋能够尽情发挥所掌握知识

并行任务

在PipeLine里能够执行并行任务,充分利用并行任务在特定场景下将极大节约构建时间,提高构建效率.好比说咱们的项目是一个模块很是多的项目,每一个模块存在不一样的仓库里,则咱们在拉取项目进行编译的时候能够并行拉取这个库,把这些并行任务放在一个步骤里,完成后再执行下一步编译工做.

请看下面示例代码

node{
    stage("poll source"){
        parallel(
      a: {
        echo "This is branch a"
         },
      b: {
        echo "This is branch b"
         }
            )
    }
   stage("build"){
       echo "build successfully"
   }
}

以上代码在poll source步骤里,咱们经过parallel并行执行了ab两个任务.这样将极大节约代码拉取时间.

咱们保存项目后点击构建,构建完成后打开BlueOcean视图,点击进入本次构建,就会看到以下图

img

能够从图形界面形象地看到poll source步骤分为a和b两个并行的任务.而后它们聚集到下一步.

使用并行任务时必定要梳理好构建的逻辑,不然将会出现意想不到的结果.若是以上a b 和build并行执行,则将会致使构建失败,由于构建依赖于以上两个步骤都执行完成.