Jenkins Pipeline 参数详解
Pipeline 是什么
Jenkins Pipeline 实际上是基于 Groovy 实现的 CI/CD 领域特定语言(DSL),主要分为两类,一类叫做 Declarative Pipeline
,一类叫做 Scripted Pipeline
。
Declarative Pipeline
体验上更接近于我们熟知的 travis CI
的 travis.yml
,通过声明自己要做的事情来规范流程,形如:
pipeline {
agent any
stages {
stage('Build') {
steps {
//
}
}
stage('Test') {
steps {
//
}
}
stage('Deploy') {
steps {
//
}
}
}
}
而 Scripted Pipeline
则是旧版本中 Jenkins 支持的 Pipeline 模式,主要是写一些 groovy 的代码来制定流程:
node {
stage('Build') {
//
}
stage('Test') {
//
}
stage('Deploy') {
//
}
}
一般情况下声明式的流水线已经可以满足我们的需要,只有在复杂的情况下才会需要脚本式流水线的参与。
过去大家经常在 Jenkins 的界面上直接写脚本来实现自动化,但是现在更鼓励大家通过在项目中增加 Jenkinsfile
的方式把流水线固定下来,实现 Pipeline As Code
,Jenkins 的 Pipeline 插件将会自动发现并执行它。
语法
Declarative Pipeline
最外层有个 pipeline
表明它是一个声明式流水线,下面会有 4 个主要的部分: agent
,post
,stages
,steps
,我会逐一介绍一下。
Agent
agent
主要用于描述整个 Pipeline 或者指定的 Stage 由什么规则来选择节点执行。Pipeline 级别的 agent 可以视为 Stage 级别的默认值,如果 stage 中没有指定,将会使用与 Pipeline 一致的规则。在最新的 Jenkins 版本中,可以支持指定任意节点(any
),不指定(none
),标签(label
),节点(node
),docker
,dockerfile
和 kubernetes
等,具体的配置细节可以查看文档,下面是一个使用 docker 的样例:
agent {
docker {
image 'myregistry.com/node'
label 'my-defined-label'
registryUrl 'https://myregistry.com/'
registryCredentialsId 'myPredefinedCredentialsInJenkins'
args '-v /tmp:/tmp'
}
}
Tips:
- 如果 Pipeline 选择了 none,那么 stage 必须要指定一个有效的 agent,否则无法执行
- Jenkins 总是会使用 master 来执行 scan multibranch 之类的操作,即使 master 配置了 0 executors
- agent 指定的是规则而不是具体的节点,如果 stage 各自配置了自己的 agent,需要注意是不是在同一个节点执行的
Stages && Stage
Stages 是 Pipeline 中最主要的组成部分,Jenkins 将会按照 Stages 中描述的顺序从上往下的执行。Stages 中可以包括任意多个 Stage,而 Stage 与 Stages 又能互相嵌套,除此以外还有 parallel
指令可以让内部的 Stage 并行运行。实际上可以把 Stage 当作最小单元,Stages 指定的是顺序运行,而 parallel 指定的是并行运行。
接下来的这个 case 很好的说明了这一点:
pipeline {
agent none
stages {
stage('Sequential') {
stages {
stage('In Sequential 1') {
steps {
echo "In Sequential 1"
}
}
stage('In Sequential 2') {
steps {
echo "In Sequential 2"
}
}
stage('Parallel In Sequential') {
parallel {
stage('In Parallel 1') {
steps {
echo "In Parallel 1"
}
}
stage('In Parallel 2') {
steps {
echo "In Parallel 2"
}
}
}
}
}
}
}
}
除了指定 Stage 之间的顺序关系之外,我们还可以通过 when
来指定某个 Stage 指定与否:比如要配置只有在 Master 分支上才执行 push,其他分支上都只运行 build
stages {
stage('Build') {
when {
not { branch 'master' }
}
steps {
sh './scripts/run.py build'
}
}
stage('Run') {
when {
branch 'master'
}
steps {
sh './scripts/run.py push'
}
}
}
还能在 Stage 的级别设置 environment
,这些就不展开了,文档里有更详细的描述。
Steps
steps
是 Pipeline 中最核心的部分,每个 Stage 都需要指定 Steps。Steps 内部可以执行一系列的操作,任意操作执行出错都会返回错误。完整的 Steps 操作列表可以参考 Pipeline Steps Reference,这里只说一些使用时需要注意的点。
- groovy 语法中有不同的字符串类型,其中
'abc'
是 Plain 字符串,不会转义${WROKSPACE}
这样的变量,而"abc"
会做这样的转换。此外还有''' xxx '''
支持跨行字符串,"""
同理。 - 调用函数的
()
可以省略,使得函数调用形如updateGitlabCommitStatus name: 'build', state: 'success'
,通过,
来分割不同的参数,支持换行。 - 可以在声明式流水线中通过
script
来插入一段 groovy 脚本
Post
post
部分将会在 pipeline 的最后执行,经常用于一些测试完毕后的清理和通知操作。文档中给出了一系列的情况,比较常用的是 always
,success
和 failure
。
比如说下面的脚本将会在成功和失败的时候更新 gitlab 的状态,在失败的时候发送通知邮件:
post {
failure {
updateGitlabCommitStatus name: 'build', state: 'failed'
emailext body: '$DEFAULT_CONTENT', recipientProviders: [culprits()], subject: '$DEFAULT_SUBJECT'
}
success {
updateGitlabCommitStatus name: 'build', state: 'success'
}
}
每个状态其实都相当于于一个 steps
,都能够执行一系列的操作,不同状态的执行顺序是事先规定好的,就是文档中列出的顺序。
Shared Libraries
同一个 Team 产出的不同项目往往会有着相似的流程,比如 golang 的大部分项目都会执行同样的命令。这就导致了人们经常需要在不同的项目间复制同样的流程,而 Shared Libraries 就解决了这个问题。通过在 Pipeline 中引入共享库,把常用的流程抽象出来变成一个的指令,简化了大量重复的操作。
在配置好 lib 之后,Jenkins 会在每个 Pipeline 启动前去检查 lib 是否更新并 pull 到本地,根据配置决定是否直接加载。
所有的 Shared Libraries 都要遵循相同的项目结构:
(root)
+- src # Groovy source files
| +- org
| +- foo
| +- Bar.groovy # for org.foo.Bar class
+- vars
| +- foo.groovy # for global 'foo' variable
| +- foo.txt # help for 'foo' variable
+- resources # resource files (external libraries only)
| +- org
| +- foo
| +- bar.json # static helper data for org.foo.Bar
目前我们的使用比较低级,所以只用到了 vars
来存储全局的变量。
vars 下的每一个 foo.groovy
文件都是一个独立的 namespace,在 Pipeline 中可以以 foo.XXX
的形式来导入。比如我们有 vars/log.groovy
:
def info(message) {
echo "INFO: ${message}"
} def warning(message) {
echo "WARNING: ${message}"
}
那么 Jenkinsfile 中就可以这样调用:
// Jenkinsfile
steps {
log.info 'Starting'
log.warning 'Nothing to do!'
}
大家可能已经注意到了,在 groovy
文件中,我们可以直接像在 steps
中一样调用已有的方法,比如 echo
和 sh
等。
我们也能在 groovy
文件中去引用 Java 的库并返回一个变量,比如:
#!/usr/bin/env groovy
import java.util.Random; def String name() {
def rand = new Random()
def t = rand.nextInt()
return String.valueOf(t)
}
这样就能够在 JenkinsFile
中去设置一个环境变量:
// Jenkinsfile
environment {
NAME = random.name()
}
除了定义方法之外,我们还能让这个文件本身就能被调用,只需要定义一个 call 方法:
#!/usr/bin/env groovy def call() {
sh "hello, world"
}
还能够定义一个新的 section,接受一个 Block:
def call(Closure body) {
node('windows') {
body()
}
}
这样可以让指定的 Body 在 windows 节点上调用:
// Jenkinsfile
windows {
bat "cmd /?"
}
常用技巧
发送邮件通知
主要使用 emailext
,需要在 Jenkins 的配置界面事先配置好,可用的环境变量和参数可以参考文档 Email-ext plugin
emailext body: '$DEFAULT_CONTENT', recipientProviders: [culprits(),developers()], subject: '$DEFAULT_SUBJECT'
结果同步到 gitlab
同样需要配置好 gitlab 插件,在 Pipeline 中指定 options
:
// Jenkisfile
options {
gitLabConnection('gitlab')
}
然后就可以在 post 中根据不同的状态来更新 gitlab 了:
// Jenkisfile
failure {
updateGitlabCommitStatus name: 'build', state: 'failed'
}
success {
updateGitlabCommitStatus name: 'build', state: 'success'
}
文档参考:Build status configuration
构建过程中可用的环境变量列表
Jenkins 会提供一个完整的列表,只需要访问 <your-jenkins-url>/env-vars.html/
即可,别忘了需要使用 "${WORKSPACE}"
在 checkout 前执行自定义操作
在 Multibranch Pipeline 的默认流程中会在 checkout 之前和之后执行 git clean -fdx
,如果在测试中以 root 权限创建了文件,那么 jenkins 会因为这个命令执行失败而报错。所以我们需要在 checkout 之前执行自定义的任务:
#!/usr/bin/env groovy
// var/pre.groovy
def call(Closure body) {
body()
checkout scm
}
在 Jenkinsfile 中配置以跳过默认的 checkout 行为:
// Jenkisfile
options {
skipDefaultCheckout true
}
在每个 stage 中执行自定义的任务即可:
// Jenkisfile
stage('Compile') {
agent any
steps {
pre {
sh 'pre compile'
}
sh 'real compile'
}
}
总结
Jenkins 作为使用最为广泛的 CI/CD 平台,网上流传着无数的脚本和攻略,在学习和开发的时候一定要从基本出发,了解内部原理,多看官方的文档,不要拿到一段代码就开始用,这样才能不会迷失在各式各样的脚本之中。
更重要的是要结合自己的业务需求,开发和定制属于自己的流程,不要被 Jenkins 的框架限制住。比如我们是否可以定义一个自己的 YAML 配置文件,然后根据 YAML 来生成 Pipeline,不需要业务自己写 Pipeline 脚本,规范使用,提前检查不合法的脚本,核心的模块共同升级,避免了一个流程小改动需要所有项目组同步更新。这是我现在正在做的事情,有机会再跟大家分享~
Jenkins Pipeline 参数详解的更多相关文章
- Jenkins pipeline 语法详解
原文地址http://www.cnblogs.com/fengjian2016/p/8227532.html pipeline 是一套运行于jenkins上的工作流框架,将原本独立运行于单个或者多个节 ...
- 利用 Java 操作 Jenkins API 实现对 Jenkins 的控制详解
本文转载自利用 Java 操作 Jenkins API 实现对 Jenkins 的控制详解 导语 由于最近工作需要利用 Jenkins 远程 API 操作 Jenkins 来完成一些列操作,就抽空研究 ...
- Nginx主配置参数详解,Nginx配置网站
1.Niginx主配置文件参数详解 a.上面博客说了在Linux中安装nginx.博文地址为:http://www.cnblogs.com/hanyinglong/p/5102141.html b.当 ...
- iptables参数详解
iptables参数详解 搬运工:尹正杰 注:此片文章来源于linux社区. Iptalbes 是用来设置.维护和检查Linux内核的IP包过滤规则的. 可以定义不同的表,每个表都包含几个内部的链,也 ...
- chattr的常用参数详解
chattr的常用参数详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在实际生产环境中,有的运维工程师不得不和开发和测试打交道,在我们公司最常见的就是部署接口.每天每个人部署的 ...
- mha配置参数详解
mha配置参数详解: 参数名字 是否必须 参数作用域 默认值 示例 hostname Yes Local Only - hostname=mysql_server1, hostname=192.168 ...
- $.ajax()方法所有参数详解;$.get(),$.post(),$.getJSON(),$.ajax()详解
[一]$.ajax()所有参数详解 url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. type: 要求为String类型的参数,请求方式(post或get)默认为get.注 ...
- linux PHP 编译安装参数详解
linux PHP 编译安装参数详解 ./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc -- ...
- 【转】jqGrid 各种参数 详解
[原文]http://www.cnblogs.com/younggun/archive/2012/08/27/2657922.htmljqGrid 各种参数 详解 JQGrid JQGrid是一个 ...
随机推荐
- python实现词云
一.安装使用命令[pip install wordcloud]安装词云 二.参数使用了OpenCV的数据格式进行读取,字体可以多试几种 def create_wordcloud_pic(): stop ...
- Zookeeper的安装与配置、使用
Dubbo的介绍 如果表现层和服务层是不同的工程,然而表现层又要调用服务层的服务,肯定不能像之前那样,表现层和服务层在一个项目时,只需把服务层的Java类注入到表现层所需要的类中即可,但现在,表现层和 ...
- Oracle 原生驱动带来的精度问题的分析与解决
问题 Oracle 官方提供了 dotnet core 驱动,但我们在使用中遇到了精度问题. 复现 以下代码运行数学运算 1/3,无论是 OracleCommand.ExecuteScalar() 还 ...
- OWIN详细介绍
1.OWIN.dll介绍 用反编译工具打开Owin.dll,你会发现类库中就只有一个IAppBuilder接口,所以说OWIN是针对.NET平台的开放Web接口. public interface I ...
- .Net捕获网站异常信息记录操作日志
第一步:在Global.asax文件下的Application_Error()中写入操作日志 /// <summary> /// 整个网站出现异常信息,都会执行此方法 /// </s ...
- ORM:对象关系映射
一.简单操作 定义:面向对象和关系型数据库的一种映射,通过操作对象的方式操作数据 对应关系: 类对应数据表 对象对应数据行(记录) 属性对应字段 导入:from app01 import models ...
- day10 作业
猜年龄升级版 ''' 1. 可以直接玩猜年龄游戏,不需要登录 2. 登录成功后玩猜年龄游戏 3. 猜年龄猜中后,可以选择两次奖品 4. 注册的用户名不能重复注册 ''' import random p ...
- mysql_innodb存储引擎的优化
采用innodb作为存储引擎时的优化 innodb_buffer_pool_size 如果用 Innodb,那么这是一个重要变量.相对于 MyISAM 来说,Innodb对于 buffer size ...
- 李宏毅-Network Compression课程笔记
一.方法总结 Network Pruning Knowledge Distillation Parameter Quantization Architecture Design Dynamic Com ...
- Linux 动态链接库路径 LD_LIBRARY_PATH
如果遇到一些 .so 缺失问题 把路径添加到这个变量里面就可以了,注意跟PATH的区别 export LD_LIBRARY_PATH= 注意使用 export 否则变量设置成功但是子进程不可见