前言
在之前的CI/CD流程中,我在配置Jenkins Job的“构建触发器”时,采用的都是Gitlab的轮询策略,每10分钟轮询一次Gitlab代码仓库,若有新代码提交,则触发构建、执行代码扫描、运行自动化测试等一系列动作。此种方式的好处是可以灵活定义轮询的时间间隔,比如每10分钟、每1小时、每天8点、每周五轮训一次等,不足之处就是不够及时,而webhook钩子刚好可以弥补这种不足:即在Gitlab仓库配置完webhook,Gitlab仓库检测到如代码提交或其他自定义事件时,即可立即触发Jenkins构建。本篇为webhook的配置过程记录、趟坑大全、解决方案、常见报错问题的通用排查思路,以及一些个人思考总结。
一、配置步骤
1.在Jenkins端安装Gitlab触发器插件
安装如图所示插件,安装完成后重启Jenkins生效
2.在Jenkins job中配置触发器
构建触发器中选择“Build when a change is pushed to Gitlab......”,并记住webhook URL。
3.Gitlab中配置webhook
Gitlab指定代码仓库-设置-Webhooks,将构建触发器中的webhook url复制到Webhooks地址栏中
4.测试webhook
新建完成后,Project Hooks中会显示新创建的webhook,可以点击右侧下拉框中的“测试”,发送请求测试与Jenkins之间的连通性。若返回200,则说明连通性正常,若返回400、401、500等则说明配置有问题。当然如果配置过程这么顺利的话,也就不会有这篇文章的存在。既然是趟坑大全,必然会有一个又一个坑在等着我。
二、趟坑大全
坑一:“ Urlis blocked: Requests to the local network are not allowed”
将Jenkins构建触发器中提示的URL,配置到gitlab待测试项目的仓库下的webhooks中,保存时提示 “ Urlis blocked: Requests to the local network are not allowed”
【原因】
官方解释:https://docs.gitlab.com/ee/security/webhooks.html,大致意思就是Gitlab 10.6 版本以后为了安全,默认不允许向本地网络发送webhook请求,可以修改默认值
【解决办法】
以管理员身份在设置-网络-外发请求中勾选“允许Webhook和服务对本地网络的请求”
坑二:忘记Gitlab管理员密码
第一次搭建完Gitlab时,管理员密码是保存在Gitlab配置目录的一个文件下,密码是一堆字符串,根本记不住,而且第一次登录后,该文件会自动删除。好在Gitlab服务是我搭建的,可以通过一些途径重置管理员密码:
gitlab-rails console # 进入gitlab-rails控制台
user = User.where(id:1).first # 查询第一个用户的信息,看是不是root用户
user.password='root123456' # 将密码设为123456
user.save # 保存设置
如下图所示:
坑三:gitlab管理员勾选“允许Webhook和服务对本地网络的请求”保存时报错500
也就是按照坑一的解决方法操作时,Gitlab会报错500
这个问题排查了很久,在一些软件测试群里或是搜索引擎上也没找到类似问题的解决方案,毕竟Gitlab 500是一种很常见的报错,可能由很多种原因导致。但此时Gitlab是正常工作的,因而可以排除网络上常见的一些原因。后来通过gitlab-ctl tail查看日志发现了报错的具体信息:
【原因】
通过在网上搜索报错信息得知,报错是因为gitlab更新到高版本(13.8.8后),”管理员设置不可注册的操作报错“,原来是我的Gitlab版本太高了...
【解决办法】
进入gitlab命令行,依次执行如下命令,进行更新设置:
gitlab-rails c # 进入gitlab命令行
# 依次执行如下命令:
settings = ApplicationSetting.last
settings.update_column(:runners_registration_token_encrypted, nil)
settings.update_column(:encrypted_ci_jwt_signing_key, nil)
settings.save!
如下图所示:
此时,再用管理员保存Gitlab网络配置时,即可保存成功:
坑四:gitlab添加Webhook后,测试发送请求,提示401
我以为Gitlab管理员密码也找回了,网络配置也设置完了,应该可以正常发送请求到Jenkins了,没想到刚测试发送请求,就提示“Hook executed successfully but returned HTTP 401”
【原因】
Jenkins访问安全问题,Jenkins和Gitlab之间没有建立信任关系。
【解决办法】
需要在Jenkins用户-设置-API TOKEN中增加一个token,并在gitlab的webhook中配置时,如“http://admin:11f3dd13297766a1546d455e73933eb4cc@192.168.1.122:8088/jenkins/project/TEST-RS-OTMS”
坑五:gitlab添加Webhook后,测试发送请求,提示403
解决坑四、在Jenkins添加完token、重新配置webhook URL后,再次发送请求,提示“Hook executed successfully but returned HTTP 403.....“,我就是不气馁,再次搜索解决方案。
【原因】
Jenkins访问权限问题
【解决办法】
需要在Jenkins系统设置中取消勾选“Enable authentication for '/project' end-point”
坑六:gitlab添加Webhook后,测试发送请求,提示500
搞完坑五的配置,测试发送请求,提示“Hook executed successfully but returned HTTP 500”。NND,我还是不气馁,再次搜索解决方案,还真被我找到了一个遇到和我一模一样问题的人。
【解决办法】
原来URL中的project要改为job(猜测可能是高版本Jenkins才有的问题,毕竟很多教程上,人家都是用的project)
坑七:gitlab测试发送请求,返回200,但是提交代码未触发Jenkins构建
以为返回200就大功告成了,没想到仅仅是返回了200,Jenkins Job那边没有丝毫动静,也就是webhook没有触发Jenkins的执行,肯定哪里还有隐藏的坑,再次搜索解决方案......
【解决办法】
URL最后要加个build,完整的形式:http://用户名:API token @IP+端口/jenkins/job/项目名称/build
坑八:Jenkins被webhook多次无规律触发构建
在解决完坑七后,再次测试发送请求,这次终于可以成功触发Jenkins构建了。但随之而来又遇到了匪夷所思的问题,Jenkins无端端地被多次触发构建(企业微信收到了多封邮件)。
【问题排查】:
① 初步分析:起初我以为是不是团队中有其他人提交代码所致,但看了Gitlab代码提交记录,只有我一个人提交代码。
② 再次分析:可能是我同时配置了Gitlab轮询策略导致,但重新检查了一遍Jenkins Job的配置,只有Webhook一种构建触发器,且根据邮件上的构建时间来看,几次的构建时间间隔没有任何规律,此原因也可以排除。
③ 继续分析:没过多会,”作用域“一词在我脑海中不断闪现:会不会是我创建的webhook位置创建错了,因为第一次在项目下创建时,遇到了坑一、二、三的各种报错,没有创建成功,后来在Gitlab的全局设置-Webhooks下创建成功了。此次可能和创建位置有关,也就是Gitlab的任意代码仓库有代码提交,都会触发Jenkins进行构建。为了验证这种猜想,我特意问了前端的开发同事,因为只有他们的代码是提交到Gitlab,后端是提交到SVN。果然当天下午有多位前端同事提交代码,且提交时间基本与我收到邮件通知的时间相吻合。
④ 终极验证:为了彻底验证猜想,我请某位同事再次提交了代码,果然随后Jenkins立马就被触发构建,我也收到了邮件通知。问题终于找到了!
【解决办法】
将webhook配置在gitlab的待测试项目的代码仓库下。
三、测试Webhook
提交代码,验证webhook:
Jenkins已经成功触发了构建:
四、总结与思考
以上就是案例”利用Gitlab的webhook钩子触发Jenkins自动执行构建“的配置全过程、各种常见不常见的问题报错、解决方案,以及遇到疑难问题的排查思路,也同样适用于其他环境搭建/软件工具使用/代码运行过程中的疑难问题,那就是:
我看过网上的很多教程,他们配置过程都很顺利,三言两语就搞定了。在遇到一些疑难问题后,我也咨询过一些同行,他们都没遇到过我这么多的问题,我甚至开始怀疑自己,简直是趟坑达人。不过,这也不完全是坏处,事物总有两面性,以下是一些思考总结: