什么是Pipeline
简单来说,Pipeline是由一系列任务构成的脚本,这些任务以串行的方式执行。脚本可以用jenkins code(Jenkins插件提供支持)、bash script(Linux)、bat/powershell(Windows)等编写。
这些脚本可以保存在Jenkins的Web UI或Jenkinsfile中。基于以下三个原因,官方推荐把Pipeline保存在Jenkinsfile中
- 便于Pipeline脚本的审查/迭代
- 便于Pipeline脚本的审计跟踪
- Pipeline的唯一真实来源,可以由项目组的多个成员查看和编辑
为什么要使用Pipeline
使用Pipeline有以下好处(翻译自官方文档):
- 代码:Pipeline以代码的形式实现,通常被检入源代码控制,使团队能够编辑,审查和迭代其传送流程。
- 持久:无论是计划内的还是计划外的服务器重启,Pipeline都是可恢复的。
- 可停止:Pipeline可接收交互式输入,以确定是否继续执行Pipeline。
- 多功能:Pipeline支持现实世界中复杂的持续交付要求。它支持fork/join、循环执行,并行执行任务的功能。
- 可扩展:Pipeline插件支持其DSL的自定义扩展 ,以及与其他插件集成的多个选项。
Pipeline的两种语法
Pipeline可以使用两种语法编写,分别是Delcarative Pipeline(声明式)和Scripted Pipeline(脚本式)。声明式的语法出现比脚本式语法晚,目的是让使用这更容易地编写Pipeline,前者结构性更强,而后者则更简洁,但它更像一门编程语言,因此对使用者的编程知识要求更高。
Declarative Pipeline
声明式Pipeline必须包含在名为pipeline的语句块中,典型的声明式Pipeline语法如下,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
pipeline { agent any environment { } stages { stage("Build") { steps { sh 'echo Building... } } stage("Test") { steps { sh 'echo Testing...' } } } } |
一个合法的Pipeline遵从下面的几个原则:
- 顶层语句块只能是
pipeline {}
- 每一个语句只能写在一行,没有分隔符,例如分号“
;
” - 结构块只能是Sections、Directive、steps或者赋值语句其中之一
- 所有的属性引用都被视为没有参数的方法调用,例如
input
等同于input()
Sections
Section可以包含一个或多个Directive、steps,常见的Section有
agent
agent指的是一台远程计算机,或者一个docker服务,通常是一台Jenkins slave服务器。agent必须在pipeline{}
块里面的顶层中定义。stage块中可选,如果pipeline块中agent的值为none,则每一个stage中都必须设置agent的值。
它的值可以是
- any
- none
- label
- node
- label
- customWorkspace
- docker
- dockerfile
post
post 是一个后处理阶段,取决于post的位置,如果post定义在pipeline块中,则所有stage构建完毕,post中的代码被执行,如果post定义在某个stage中,则该stage构建完毕之后post被执行。
post的值有:
- always
- changed
- fixed
- regression
- aborted
- failure
- success
- unstable
- cleanup
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
pipeline { agent any stages { stage('stage 1') { agent any } post { always { echo 'I will always execute after stage 1 finish' } } } post { always { echo 'I will always execute' } } } |
stages
stages可以包含一个或多个stage,一个stage指一个构建阶段
stage
代表stages中的每一个阶段,stage中可以嵌套包含stages,嵌套stages中的stage属于串行(Sequential)任务,即串行stage不能再包含parallel或stages。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
pipeline { agent any stages { stage { agent any stages { stage("nested stage") { //此stage中不能继续包含parallel或stages } } } } } |
steps
steps里面包含真正的可执行脚本
Directives
environment
用于定义环境变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
pipeline { agent any environment { BUILD_VERSION = '1.0' } stages { stage('Get The Evn'){ steps { sh 'pintenv' //or sh 'env' } } } } |
parameters
定义参数,可定义的参数类型有两种,分别是字符串和布尔值。parameters中定义的参数可以在steps中通过params对象引用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
pipeline { agent any parameters { string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?') } stages { stage('Example') { steps { echo "Hello ${params.PERSON}" } } } } |
triggers
触发器,可定义的触发器类型如下:
- cron 定时执行
- pollSCM 定时拉取仓库中的源码
- upstream 某个上层项目构建完毕触发
1 2 3 4 5 6 7 8 9 10 |
pipeline { agent any triggers { cron('H */4 * * 1-5') } stages { .... } } |
parallel
定义并行任务,并行任务通常用于多分支Pipeline构建任务中
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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
pipeline { agent any stages { stage('Non-Parallel Stage') { steps { echo 'This stage will be executed first.' } } stage('Parallel Stage') { when { branch 'master' } failFast true parallel { stage('Branch A') { agent { label "for-branch-a" } steps { echo "On Branch A" } } stage('Branch B') { agent { label "for-branch-b" } steps { echo "On Branch B" } } stage('Branch C') { agent { label "for-branch-c" } stages { stage('Nested 1') { steps { echo "In stage Nested 1 within Branch C" } } stage('Nested 2') { steps { echo "In stage Nested 2 within Branch C" } } } } } } } } |
Scripted Pipeline
Scripted Pipeline对语法的要求比较宽松,顶层可以是node,也可以是stage。node可以嵌套stage,stage反过来也可以嵌套node。典型的脚本式Pipeline语法如下:
1 2 3 4 5 6 7 8 9 10 |
node { //node可以指定label 例如 node ('label_name') {} stage("Build") { sh 'echo Building...' } stage("Test"){ sh 'echo Testing...' } } |
基础语法
相比起Declarative Pipeline语法中使用块或指定的形式定义构建过程,Scripted Pipeline则是使用方法(函数)
我们先列出一个基本的Scripted Pipeline,比较以下两者的不同
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
node('master'){ withEnv(['BUILD_VERSION=1.0', //withEnv方法对应前面的environment块 'DB_ENGINE=sqlite']){ try{ //try catch finally语句块对应于前者的post后处理 stage('Build'){ echo 'Building...' } }catch(err){ //catch和finally二者不必同时存在 echo 'someting went wrong' }finally{ echo 'I will always execute' } } } node('slave'){ stage('Build'){ echo 'Building...' } } |
node
这里的node对应于Declarative Pipeline的agent,用于指定构建步骤应该在哪个构建服务器执行。
1 2 3 4 5 6 |
node('master'){ stage('Build'){ echo 'Building...' } } |
node可以嵌套stage,也可以被stage嵌套
1 2 3 4 5 6 7 8 9 10 |
stage('Build'){ node('linux'){ sh 'echo building in linux' } node('windows'){ bat 'echo building in windows' } } |
withEnv
withEnv方法和environment语句块对应,用于定义环境变量。
try catch finally
对应于post后处理语句块
1 2 3 4 5 6 7 8 9 10 |
try{ stage('Build'){ echo 'do something' } }catch(err){ }finally{ } |
properties
可用于添加参数,有Delcarative Pipeline的parameters
的作用,也用于建立触发器
parameters
1 2 3 4 5 6 7 |
properties([parameters([string(name: 'username', defaultValue: 'jenkins', description: 'remote user')])]) node { stage('Build'){ echo "${params.username}" } } |
triggers
1 2 3 4 5 6 7 |
node { properties([pipelineTriggers([cron('H */1 * * *')])]) stage('Build') { echo 'Building...' } } |
parallel
语法和Declarative Pipeline有点不一样,并行任务之间使用逗号”,
“分隔。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
stage('Test') { parallel linux: { node('linux') { checkout scm try { unstash 'app' sh 'make check' } finally { junit '**/target/*.xml' } } }, windows: { node('windows') { /* .. snip .. */ } } } |
使用blue ocean
blue ocean是一个为Pipeline重新设计的Web UI。jenkins默认没有安装这个插件,因此使用之前需要安装该插件,只需要在插件管理中搜索Blue Ocean,勾选安装即可,安装的过程会连同其他依赖插件一起安装。
安装完毕重启,左侧面板会自动出现Blue Ocean的菜单
Blue Ocean的整体外观如下:
通过Blue Ocean创建Pipeline
第一步,点击右上角的创建流水线
第二步,我们选择Git(也可以选择GitHub,不同的是GitHub需要生成token才能访问)
第三部,输入仓库地址,用户名和密码,点击创建证书,然后点击创建Pipeline
如果仓库没有包含Jenkinsfile文件,则会出现下面的提示,点击创建Pipeline即可。
如果仓库已经有Jenkinsfile,那么jenkins则会直接进入构建阶段。
点击后会跳转到Jenkinsfile创建页面,点击左边start后面的加号,添加一个stage
第二步是输入stage名称,然后点击添加步骤
进入第三步
第三步,选择Shell script
第四步编写shell script,完成后保存
最后把改变提交到github仓库
所有步骤完成之后,jenkins就会根据之前创建的shell script自动构建项目。
转载请注明:Pure nonsense » jenkins使用pipeline提高生产效率