公司团队是使用gitlab
来管理源代码的,一直以来当提交了一个PR
后,需要手动在内部IM
群里贴出PR
链接和摘要,然后@
目标同事来帮忙review代码,之后就不时地手动刷新页面查看是否有足够的人review
完了。这种方式比较原始费时,仔细想想其实大部分流程是可以自动化的。
一些做的好的IM
可以实现自定义机器人,例如飞书(lark),如果机器人可以知道有人发了PR
,同时又知道具体有哪些人需要review PR
,那么就可以自动在IM
群里把这个PR
的信息发出来,同时@
对方。然后当机器人知道PR
通过了后就可以给PR
作者私聊发通知,就可以开开心心合并代码了。整理下具体流程:
1 | 提交PR -> 群里发通知+@对方 -> PR通过 -> 私聊发送通知 -> 合并PR |
全程只有第一步和最后一个需要PR
作者操作,中间的步骤都可以由机器人完成。
如何知道有人发了PR
这里的标题有一点误导,我们真正想知道的不是有没有人提交PR,而是那些需要被人review
的PR
。我们可以约定只有在PR
的评论里@了同事,才认为这个PR
需要review
. 恰好gitlab
提供了一种webhook
机制,可以在发生了特定的事件时请求指定的api
。 webhook
的设置路径是项目仓库 -> Settings -> Integrations
,如图:
其中的URL
是自定义的,我们可以将它指向我们的一个后端api
,gitlab
会往这个api
发送一个POST
请求,携带事件的详细信息。Trigger
我们设置为Comments
,表示每次有人在PR
里发表了评论都会触发api
。
在设置了webhook
后,点击它的Edit
按钮,可以看到在什么时候触发了webhook
:
还可以看到每次触发时传递的参数:
里面的信息非常丰富,每次评论的内容也在其中,还可以根据已有的信息再次调用gitlab openapi
来获取更多信息。
以上,每次有人在PR
里发表评论了,我们的后端api
都会收到一个请求,接下来的问题是如何判断评论里是否含有有效的@
.
提取@对象
首先评论的具体内容是放在了请求参数的object_attributes.note
属性中,它是一个字符串例如@xiaoming @zhangsan 来看看我的PR啊~
。什么是有效的@目标呢? 就是@的对象确实是同事的名字,而不是随便写的,例如@123
就不是有效的@。 我们把这件事拆分一下,首先无脑提取所有的@对象,可以用以下代码:
1 | const atReg = /@[^\s]+/g |
它会返回形如['xiaoming', 'zhangsan']
的数组,接下来就是判断每个元素是否有效的目标。这里可能不同公司的业务不一样,我的思路是判断目标是否为gitlab
里的注册用户,可以用gitlab
的users api
,可以查询用户名匹配指定字符串的所有用户。我们利用这个api
看返回的数组是否为空,不为空取第一个。则整个过滤逻辑如下:
1 | // 过滤@列表,只留下真实存在的gitlab用户, privateToken为gitlab openapi需要的鉴权token |
调用gitlab openapi
需要鉴权的private_token
,获取步骤: 进入gitlab
-> 右上角个人头像 -> Settings
-> Access Tokens
,然后就可以增加一个token
了,注意token
的scopes
全选.
以上,这样我们就拿到了所有有效的@
目标,接下来就是如何在IM
群里利用机器人@
他们。
机器人自动@目标
这个基本就是调用各IM
工具的open api
了,举一个飞书
的例子:
1 | const atText = atList.map( at => `<at user_id="${ at.userId }">@${ at.name }</at>` ); |
只需提供@目标的userId
和name
即可,可以同时@多人。同时需要额外再提供群的id,这样机器人才知道该把消息往哪里发送。
置于怎么申请IM
机器人,这个也是不同IM
不一样,这里不赘述。
以上,我们就能做到当在PR
里@了一些目标同事后,机器人自动在群里@同事了。
通知merge PR
接下来要解决的问题是当有足够多的人觉得PR是ok的,实时通知PR作者来merge
PR
。这里涉及到2个问题:
- 怎么判断一个PR是ok的
- 怎么判断有足够多的人觉得PR是ok的
第一个问题可以约定一个暗号:当在PR中评论了LGTM(Look Good To Me)
即认为PR是ok的,当然也可以用其他暗号。
第二个问题的核心是: 判断一个PR的所有评论中是否有足够的指定字符串。首先需要获取所有评论,这个依然可以通过gitlab
openapi
来获取,然后就依次对每条评论的内容做字符串匹配即可。核心代码示范:
1 | // 此PR所有的评论 |
1 | // 筛选出非PR作者写的note, discussion 与 note是一对多的关系 |
以上我们就可以及时给PR作者发送merge通知了。
merge PR
最后一件锦上添花的事情,当收到merge
通知后,当然可以手动打开PR连接然后点击merge
按钮,不过这样显得不够极致,能不能让作者直接在IM
工具内点击某个按钮或链接,然后由机器人自动帮助其合并呢?这样就更方便好用了!
当然这么做的前提是IM
工具支持富文本类型消息,或者可交互的消息,只要最终可以往指定链接发送GET
或POST
请求即可。
gitlab
提供了直接merge PR
的openapi
,不过其只支持PUT
类型请求,同时需要携带PR
的关键信息。如果IM
工具不支持在消息内再发送PUT
类型请求,那么只能做一次中转:先发送一个普通的get
/post
请求到我们自己的某个后端api
,然后在这个api
内再发送最后的PUT
请求。核心代码示范如下:
1 | // 发送支持交互的消息 |
然后在后端api
发送PUT
请求:
1 | // 合并PR |
以上我们就做到了PR
的全程自动化! 整个机器人的代码其实就是一个node
服务,找个服务器部署起来即可。
完整的源码可以参照github
.