Jenkins使用jenkinsfile脚本构建

jenkinsfile脚本使用

Jenkins 2.0的精髓是Pipeline as Code,是帮助Jenkins实现CI到CD转变的重要角色。

Pipeline就是一套运行于Jenkins上的工作流框架,将原本独立运行于单个或者多个节点的任务连接起来,实现单个任务难以完成的复杂发布流程。

持续交付管道(CD Pipeline)是将软件从版本控制阶段到交付给用户或客户的完整过程的自动化表现。软件的每一次更改(提交到源代码管理系统)都要经过一个复杂的过程才能被发布。

Pipeline提供了一组可扩展的工具,通过Pipeline Domain Specific Language(DSL)syntax可以达到Pipeline as Code(Jenkinsfile存储在项目的源代码库)的目的。

Pipeline的几个基本概念:

  • Stage:阶段,一个Pipeline可以划分成若干个Stage,每个Stage代表一组操作,例如:”Build”,”Test”,”Deploy”。

    Stage是一个逻辑分组的概念,可以跨多个Node
  • Node:节点,一个Node就是一个Jenkins节点,或者是Master,或者是Agent,是执行Step的具体运行环境。

  • Step:步骤,Step是最基本的操作单元,小到创建一个目录,大到构建一个Docker镜像,由各类Jenklins Plugin提供,例如:sh ‘make’

要使用Jenkins Pipeline,需要:Jenkins 2.x或更高版本和Pipeline插件

Pipeline定义

Pipeline脚本是用Groovy写的,可以通过以下任一方式创建基本Pipeline:

  • pipeline script:直接在Web UI的script输入框里面输入pipeline script语句即可,参考说明可以点击输入框下边的Pipeline Syntax,里面有很多示例操作说明,非常好用。
  • pipeline script from SCM:需要配置SCM代码存储Git地址或SVN地址,指定script文件Jenkinsfile所在路径,每次构建job会自动去指定的目录执行script文件

以上两种方法定义Pipeline的语法都是一样的。

Pipeline配有内置的文档功能192.168.1.112:8000/pipeline-syntax/

流水线方式搭建,安装好Pipeline Maven Integration Plugin插件:

pipeline-model-definition
build-pipeline-plugin
buildgraph-view
workflow-aggregator

也可以直接安装blueocean

1、在Web UI中定义Pipeline

要在Jenkins Web UI中创建基本Pipeline Job,单击Jenkins主页上的New Item。输入Pipeline的名称,选择Pipeline,然后单击确定。
在流水线里写入代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
node {
stage('build'){
echo 'build';
}

stage('test'){
echo 'test';
}

stage('deploy'){
echo 'deploy';
}
}

20200413163302

保存,立即构建

20200413163326

构建成功

20200413163345

2、在SCM中定义pipeline,也就是结合版本管理工具进行构建

复杂的Pipeline难以在Pipeline配置页面的文本区域内进行写入和维护。为了解决这一问题,jenkins Pipeline支持在文本编辑器中编写脚本文件jenkinsFile,Jenkins可以通过从SCM选项的控件中加载Pipeline脚本。指定要检索的Pipeline脚本的路径。更新指定的存储库时,只要Pipeline配置了SCM轮询触发器,就会触发一个新构建。

首先创建一个jenkinsfile文件上传到git,作为测试使用。创建构建,和上面一致,这里选择SCM方式。

20200413163427

20200413163441

保存后,立即构建成功

20200413163458

jenkinsfile脚本语法

支持两种语法

Declarative 声明式(在Pipeline plugin 2.5中引入)和 Scripted Pipeline 脚本式

如何创建最基本的PIpeline:直接在Jenkins Web UI 网页界面中输入脚本

通过创建一个jenkinsfile可以检入项目的源代码管理库

20200413163640

声明式Pipeline

声明式Pipeline的基本语法和表达式遵循与Groovy语法相同的规则,但有以下例外:

声明式pipeline必须包含在固定格式pipeline{}快内

每个声明语句必须独立一行,行尾无需使用分号

块(blocks{})只能包含章节(Sections),指令(Directives),步骤(Steps)或赋值语句

属性引用语句被视为无参数方法调用。例:输入被视为 input()

  • 块(blocks{})

由大括号括起来的语句,如pipeline{},Section{},parameters{},script{}

  • 章节(Sections)

通常包含一个或多个指令或步骤。如 agent 、post、stages、steps

  • 指令(Directives)

environment、options、parameters、triggers(触发)、stage、tools、when

  • 步骤(Steps)

Pipeline steps reference 执行脚本式pipeline:使用script{}

agent
必须存在,agent必须在pipeline块内的顶层定义,但stage内是否使用使可选的

参数:any/none/label/node/docker/dockerfile

常用选项 label/cuetomWorkspace/reuseNode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
agent { label 'my-label' }

agent {
node {
label 'my-label'
customWorkspace '/some/other/path'
}
}

agent {
docker {
image 'nginx:1.12.2'
label 'my-label'
args '-v /tmp:/tmp'
}
}
post 不是必须的,用于pipeline的最外层或者stage{}中

pipeline {
agent any
stages {
stage('Example'){
steps {
echo 'Hello world'
}
}
}
post {
always {
echo 'say goodbay'
}
}
}

stages 必须,包括顺序执行的一个或多个stage命令,在pipeline内仅能使用一次,通常位于agent/options后面,例子如上

steps 必须,steps位于stage指令块内部,包括一个或多个step。仅有一个step的情况下可以忽略关键字step及其{},例子如上

environment 不是必须的,environment定义了一组全局的环境变量键值对,存在于pipeline{}或者stage指令内。执行特殊方法credentials()可以获取jenkins中预定义的凭证明文内容

1
2
3
4
5
6
7
8
9
10
11
12
13
environment {CC='clang'}
environment {AN_ACCESS_KEY = credentials('my-prefined-secret-text')}
steps {sh 'printenv'}

options 不是必须的 预定义pipeline专有的配置信息,仅可定义一次

pipeline {
agent any
options{
timeout(time:1,unit: 'HOURS')
}
...
}

parameters 不是必须的 定义参数化构建的参数可选参数 booleanParam,choice,file,text,password,run,string

1
2
3
4
5
6
7
8
paramenters {
choice(name:'PerformMavenRelease',choices:'False\nTrue',description:'desc')
password(name:'CredsToUse',description:'Apassword to build with',defaultValue:'')
}
environment {
BUILD_USR_CHOICE="${params.PerformMavenRelease}"
BUILD_USR_CREDS="${params.CredsToUse}"
}

triggers 不是必须的 定义pipeline被自动触发的方式选项 cron、pollSCM、upstream

triggers {cron('H 4/* 0 0 1-5')}
triggers {pollSCM('H 4/* 0 0 1-5')}
triggers {upstream(upstreamProjects:'job1,job2',threshold:hudson.model.Result.SUCCESS)}

常用的辅助工具

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
Snipper Generator(代码片段生成器,语法检查器)
Replay Pipeline(重放pipeline,可以修改script,修改后的不存入config.xml)
DSL Reference 语法参考手册
全局变量引用
Stage View
BlueOcean(可视化)
Pipeline神器:可视化编辑器
命令行Pipeline调试工具
变量的传递

自定义变量(局部)
def username = 'Jenkins'
echo "Hello Mr.${username}"
#注意一定要用双引号,单引号识别为字符串
环境变量(局部)
withEnv(['MYTOOL_HOME=/usr/local/mytool']){
sh '$MYTOOL_HOME/bin/start'
}
环境变量(全局)
environment {CC='clang'}
echo "Compiler is ${env.CC}"
参数化构建(全局)
parameters {string(name:'Jenkins',defaultValue:'Hello',description:'How should I greet the world')}
ehco "${params.Greeting} World!"
判断
when仅用于stage内部
when的内置条件为:
- when {branch 'master'}
- when {environment name:'DEPLOY_TO',value:'production'}
#当有环境变量 name 为 DEPLOY_TO 值是 production 条件成立
- when {expression {return params.DEBUG_BUILD} }
#表达式返回值为真时
- when {not {branch 'master'} }
- when {allOf {branch 'master'; environment name:'DEBUG_TO',value:'production'} }
#allOf 所有条件都满足时
- when {anyOf {branch 'master' ; branch 'staging'} }
#anyOf有一个条件满足时即可

判断和异常处理 流程控制if/else条件

1
2
3
4
5
6
7
8
9
node {
stage('Example'){
if(env.BRANCH_NAME == 'master'){
echo 'I only execute on the master branch'
}else {
echo 'Iexecute elsewhere'
}
}
}

异常处理try/catch/finally

1
2
3
4
5
6
7
8
9
10
11
node{
stage('Example'){
try{
sh 'exit 1'
}
catch (exc) {
echo 'something failed,I should sound the klaxons!'
throw
}
}
}

循环

for循环仅存在域脚本式pipeline中,但是可以通过在声明式pipeline中调用script step来执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
pipeline {
agent any
stages {
stage('Example'){
steps{
echo 'Hello world!'
script {
def browsers = ['chrome','firefox']
for (int i = 0;i < browers.size();++i){
echo "Testing the ${browsers[i]} browser"
}
}
}
}
}
}

并发需要放在stages中,stages可以嵌套使用 stage下的steps和parallel不能共存,只能二选一
使用了并发的stage不能再有agent/tools 强制所有并发任务退出,加参数 failFast true

脚本式 Pipeline

在脚本式 Pipeline 语法中,一个或多个 node 块执行贯穿整个 Pipeline 的核心工作。虽然这不是脚本式 Pipeline 语法的强制性要求,但将管道 work 限制在 node 块内部会做两件事情:

通过将 item 添加到 Jenkins 队列来运行块中包含的 step。只要执行程序在 node 上空闲,这些步骤就会运行。
创建一个工作空间(特定于该特定 Pipeline 的目录),其中可以对从源代码管理检出的文件执行工作。
注意:根据不同的 Jenkins 配置,部分 workspaces 不会在一段不活动时间之后自动清理。查看与 JENKINS-2111 相关的标记和讨论以获取更多信息。
1
2
3
4
5
6
7
8
9
10
11
12
Jenkinsfile (Scripted Pipeline)
node { //在任何可用的代理上执行这个 Pipeline 或其任意 stage
stage('Build') { //定义 "Build" stage
// 执行和 "Build" stage 相关的 step
}
stage('Test') {
//
}
stage('Deploy') {
//
}
}