原文地址:Jenkins 2.x-实践指
什么是触发条件
前文中,我们都是在推送代码后,再切换到 Jenkins 界面,手动触发构建的。显然,这不够 “自动化”.自动化是指 pipeline 按照一定的规则自动执行。而这些规则被称为 pipeline 触发条件。
对于 pipeline 触发条件,笔者从两个维度来区分:时间触发和事件触发。接下来我们从这两个维度分别介绍:
时间触发
时间触发是指定义一个时间,时间到了就触发 pipeline 执行。在 Jenkins pipeline 中使用 trigger 指令来定义时间触发。
trigger 指令智能被定义在 pipeline 模块下,Jenkins 内置支持 cron, pollSCM, upstream 三种方式。其他方式可以通过插件来实现。
定时执行:cron
定时执行就像 cronjob,一到时间点就执行。它的使用场景通常是执行一些周期性的 job,如每夜构建。
1 | pipeline { |
Jenkins trigger cron 语法采用的是 UNIX cron 语法(有些细微的区别)。一条 cron 包含 5个字段,使用空格或 Tab 分隔,格式为:MINUTE HOUR DOM MONTH DOW。每个字段的含义为:
- MINUTE:一个小时内的分钟,取值范围为 0~59;
- HOUR:一天内的小时,取值范围为 0~23;
- DOM:一个月的某一天,取值范围为 1~31;
- MONTH:月份,取值范围为 1~12;
- DOW:星期几,取值范围为 0~7,0 和 7 都代表星期天。
还可以使用以下几种特殊符号,一次性指定多个值。
- * :匹配所有的值
- M-N:匹配 M 到 N 之间的值
- M-N/X or */X:指定在 M 到 N 范围内,以 X 值为步长;
- A,B,…,Z:使用逗号枚举多个值。
在一些大型组织中,会同时存在大量的同一时刻执行的定时任务,比如 N 个半夜零点 (0 0 * * *
) 执行的任务。这样会产生负载不均衡。在 Jenkins trigger cron 语法中使用 “H” 字符来解决这一问题,H 代表 hash。对于没必要准确到零点0分执行的任务,cron 可以这样写:H 0 * * *
,代表在零点 0 分至零点 59 分之间任何一个时间点执行。
需要注意的是,H 应用在 DOM(一个月的某一天)字段时会有不准确的情况,因为 10 月有 31 天,而 2月却是 28 天。
Jenkins trigger cron 还设计了一些人性化的别名:@yearly,@annually,@monthly,@weekly,@daily,@midnight 和 @hourly。例如,@hourly 与 H * * * *
相同,代表一个小时内的任何时间;@midnight 实际上代表在半夜 12:00 到凌晨 2:59 之间的某个时间。其他的别名很少有应用场景。
轮询代码仓库:pollSCM
轮询代码仓库是指定期到代码仓库询问是否有变化,如果有变化就执行。有读者会问:那么多久轮询一次?笔者的答案是越频繁越好。因为构建的间隔时间越长,在一次构建内就可能会包含多次代码提交。当构建失败时,你无法马上知道是哪一次代码提交导致了构建失败。总之,越不频繁集成,得到的 “持续集成” 的好处就越少。笔者通常会在 jenkinsfile 中这样写:
1 | pipeline { |
事实上,如果代码有变化,最好的方式是代码仓库主动通知 Jenkins,而不是 Jenkins 频繁去代码仓库检查。那这种方式存在的意义是什么?
在一些特殊的情况下,比如外网的代码仓库无法调用内网的 Jenkins,或者反过来,则会采用这种方式。
事件触发
事件触发就是发生了某个事件就触发 pipeline 执行。这个事件可以是你能想到的任何事件。比如手动在界面上触发,其他 job 主动触发,HTTP API Webhook 触发等。
由上游任务触发:upstream
当 B 任务的执行依赖 A 任务的执行结果时,A 就被称为 B 的上游任务。在 Jenkins 2.22 及以上版本中,trigger 指令开始支持 upstream 类型的触发条件。upstream 的作用就是能让 B pipeline 自行决定依赖哪些上游任务。示例如下:
1 | // job1 和 job2 都是任务名 |
当 upstreamProjects 参数接收多个任务时,使用逗号(,)分隔。threshold 参数是指上游任务的执行结果是什么值时触发。hudson.model.Result 是一个枚举,包括以下值:
- ABORTED:任务呗手动中止
- FAILURE:构建失败
- SUCCESS:构建成功
- UNSTABLE:存在一些错误,但不至于构建失败;
- NOT_BUILT:在多个阶段构建时,前面阶段的问题导致后面阶段无法执行。
注意:需要手动触发一次任务,当 Jenkins 加载 pipeline 后,trigger 指令才会生效。
GitLab 通知触发
GitLab 通知触发是指当 GitLab 发现源代码有变化时,触发 Jenkins 执行构建。由 GitLab 主动通知进行构建的好处是显而易见的,这样很容易就解决了我们之前提到的轮询代码仓库时 “多久轮询一次” 的问题,实现每一次代码的变化都对应一次构建。
安装 GitLab 的过程就不赘述了。假设你已经安装好 GitLab,其配置过程并不复杂。通过以下几步就可以实现提交代码后,GitLab 触发 Jenkins 上相应的 pipeline 执行构建。
安装 Jenkins 插件
- GitLab 插件 https://plugins.jenkins.io/gitlab-plugin
- git 插件 https://plugins.jenkins.io/git
需要再次提醒的是,本书使用的 GitLab 版本是 10.5.4,使用的是 GitLab 插件,不是 GitLab Hook 插件(已废弃)。在安装插件时需要留意。
在 GitLab 上创建项目
我们在 jenkins-book 这个 group 组下创建一个名为 “hello-word-pipeline” 的项目,地址为:http://172.16.68.21:8091/jenkins-book/hello-word-pipeline.
在 Jenkins 上创建 pipeline 项目
注意是单分支的 pipeline 项目, 而不是多分支的 pipeline项目。使用的 git 地址就是上一步创建的 git@172.16.68.21:jenkins-book/hello-world-pipeline.git。Jenkins 将使用 SSH 方式拉取,所以需要提前将 SSH 的公钥放到 GitLab 上。
在 Jenkins 上配置 hello-world-pipeline
在项目的配置页中找到 “Build Triggers” 部分,勾选 “Build when a change is pushed to GitLab” 复选框,就可以看到如下图所示的配置: