Jenkins 多分支项目过滤及 when 的高级用法

用户头像
jerry.mei
关注
发布于: 2020 年 07 月 27 日
Jenkins 多分支项目过滤及 when 的高级用法

需求



前段时间在研究 Jenkins 的自动化构建时,写了一篇文章:使用 Generic Webhook Trigger 触发 Jenkins 多分支流水线自动化构建



Generic Webhook Trigger 的使用过程中,有一个问题一直困扰着我,就是多分支流水线每次触发构建时所有的分支都会去构建一遍。之前也没怎么去关心,因为在 Jenkinsfile 里我用 when 做了条件匹配。这周发现分支越来越多,而且团队合并代码变频繁之后,虽然那些分支只是做了一下pull代码的操作,但是各种排队加起来的时间也会导致整个构建的时间越来越长,而且会产生各种不必要的构建日志等等。



之前的思路一直是 Generic Webhook Trigger 里是不是有一个配置可以做到只触发特定的分支,google 了一些文章发现无果。而且类似的触发器插件都是只能做到根据过滤条件去触发这个Job。所以后来换了个思路去思考这个问题。



首先想到的是,既然是一个多分支的流水线,那么对于这种流水线本身是不是可以去过滤一些特定的分支呢?比如我们项目里只需要构建 sprintmaster 分支,平时的 feature 分支还有其它的等等都是不需要构建的。然后就按这种想法去 google 了一下,还真的找到了答案。



Jenkins Multibranch Config: How to Filter branches based on variable string?



多分支流水线过滤



进入流水线的配置界面,在 Branch Sources 里找到了Behaviours 选项,可以添加很多行为,这里面有两个我们需要的:



  • Filter by name(with regular expression)

  • Fliter by name(with wildcards)



使用正则表达式或通配符来过滤





点击 ? 图标会有一些说明,比如正则表达式的语法使用的是Java的。这也是我想吐槽的一点,同样一个正则表达式,在不同的地方写法各不相同,折腾死人。





保存之后,流水线里就只保留了过滤之后的分支





这一步可以把开发时的各种分支都过滤掉,只保留需要构建的分支。但是还有另一个问题,我们Jenkinsfilebuild 阶段,会去做一些前端的代码打包工作,比较耗时。这个阶段配置的是 mastersprint 分支都会去执行。



但我们开发的时候,当代码合并到 sprint 分支后,我只想触发 sprint 分支去执行 build 阶段的命令。master 只需要手动去触发。这就需要用到 whentriggeredBy 属性



when 的 triggeredBy 属性



我们现在需要完成的目标是,当使用 Generic Webhook Trigger 触发构建的,master 分支各个 stage 都不执行。



官网的说明就这些。对于 Generic Webhook Trigger 来说,这些都没用。





然后试了下 when { triggeredBy 'GenericTrigger'} 也不行,generic-webhook-trigger-plugin有人专门提了一个 Issues 去问这个问题,但是被关闭了,也没有解决办法。



后面就去搜怎么在Jenkins中获取构建的原因,居然还找到了很多这方面的资料。可以通过currentBuild.getRawBuild().getCauses()去获取。但是出于安全考虑,Jenkins脚本中直接使用系统的方法是被禁止的,需要手动去添加一下。参考了Jenkins CI Pipeline Scripts not permitted to use method groovy.lang.GroovyObject这个问题的回答搞定了这个问题。



最后写了一个测试的脚本,如下:



stage('TEST'){
steps{
script{
env.buildCauses = currentBuild.getRawBuild().getCauses()
}
echo "Causes by: ${env.buildCauses}"
}
}

打印的结果如下:





本来想根据返回的这个结果去自己写匹配语句,但感觉很麻烦干脆就试一下 when { triggeredBy 'GenericCause'} 。天哪,居然可以了,简直不敢相信。



最终的 Jenkinsfile 脚本如下:



stage('Build'){
//构建条件:如果是feature分支,任何条件下都构建;如果是master分支,取消自动化构建
when{
anyOf{
expression { BRANCH_NAME ==~ /features\/sprint\d*/ }
allOf{
branch 'master'
not {
triggeredBy 'GenericCause'
}
}
}
}
steps{
sh '''
'''
}
}



这次虽然解决了这个棘手的问题,但是并没有非常开心。其实这些问题,文档写明白一点就不用去折腾这么久了。对于开源产品来说,一个清晰的文档真的很重要。



发布于: 2020 年 07 月 27 日 阅读数: 137
用户头像

jerry.mei

关注

Coding is ARTS 2019.01.03 加入

全栈工程师,技术作者,关注大前端、web全链路研发等领域 个人网站:http://www.jerrymei.cn

评论

发布
暂无评论
Jenkins 多分支项目过滤及 when 的高级用法