很多人都有自己的GitHub项目,可能需要自动通知钉钉仓库中的事件。虽然可以在钉钉群中加入专用的GitHub机器人,但是支持的事件类型非常有限,基本只有推送相关的事件。如果你想支持更多的赛事,不如自己造一个机器人。于是,实现了一个GitHubtoDingTask项目。该项目通过阿里云的函数计算服务部署,无需任何货币成本即可部署该通知服务。实现思路的核??心是在钉钉群中添加一个自定义机器人,实现一段WebHook逻辑,根据接收到的GitHub事件类型向自定义机器人发送不同的消息。这个webhook逻辑需要有公网地址才能调用。各大云服务的函数计算服务每个月都会提供一定数量的免费调用,是存放webhook逻辑的首选。实现原理在钉钉上添加自定义机器人在钉钉群中添加自定义机器人,在机器人的安全设置中选择“添加签名”,记下密钥后点击“完成”,在完成中记下机器人的webhook地址界面。通知逻辑GitHub的WebHook事件的事件体是一个Json字典,因此可以构造一个DingTalkNotifier类来接收事件体payload,并提供notify()方法根据事件内容通知钉钉群具体消息。得知钉钉群有现成的开源PythonSDK——DingtalkChatbot,可以使用,免去了我们阅读钉钉定制机器人的技术文档来打包实现的麻烦。WebHook通知的核心代码如下:importloggingimportconffromdingtalkchatbot.chatbotimportDingtalkChatbotclassDingTalkNotifier(object):def__init__(self,payload:dict):self.payload=payloadself.action=self.payload.get('action')self.action_prep='to'ifself.actionin('created','opened','submitted',None)else'of'self.sender=sender=payload.get('sender')or{}self.sender_full_name=sender.get('login')self.sender_page=sender.get('html_url')self._md_sender=f'[{self.sender_full_name}]({self.sender_page})'self.repo=repo=payload.get('repository')或{}self.repo_full_name=repo.get('full_name')self.repo_page=repo.get('html_url')self.repo_language=repo.get('language')self.repo_star_count=repo.get('stargazers_count')self._md_repo=f'[{self.repo_full_name}]({self.repo_page})'self.bot=DingtalkChatbot(conf.webhook,conf.secret)defnotify(self):logging.info(f'Preparingnotification:{self.payload}')if'pull_request'inself.payload:self._notify_pull_request()elif'head_commit'inself.payload:self._notify_push()elif'issue'inself.payload:self._notify_issue()elif'starred_at'inself.payload:self._notify_star()elif'forkee'inself.payload:self._notify_fork()elif'discussion'inself.payload:self._notify_discussion()def_notify_pull_request(self):pr=self.payload['pull_request']pr_page=pr['html_url']pr_number=pr['number']pr_title=pr['title']pr_body=pr['body']or''review=self.payload.get('review')comment=self.payload.get('comment')如果评论:pr_review_page=review['html_url']review_body=review['body']或''self.bot.send_markdown(title='PullRequestReview',text=f'{self._md_sender}有{self.action}一个pullrequestreview{self.action_prep}{self._md_repo}\n\n'f'[#{pr_number}{pr_title}]({pr_review_page})\n\n'f'>{review_body}')elifcomment:comment_page=comment['html_url']comment_body=comment['body']or''self.bot.send_markdown(title='IssueComment',text=f'{self._md_sender}有{self.action}拉取请求审查评论'f'{self.action_prep}{self._md_repo}\n\n'f'[#{pr_number}{pr_title}]({comment_page})\n\n'f'>{comment_body}')else:self.bot.send_markdown(title='PullRequest',text=f'{self._md_sender}有{self.action}拉取请求{self.action_prep}{self._md_repo}\n\n'f'[#{pr_number}{pr_title}]({pr_page})\n\n'f'>{pr_body}')上面代码中:DingTalkNotifier的构造函数接收payload变量,即GitHubWebHook在事件体构造函数中,初步分析了事件体中的公共发送者和存储库数据,以便在稍后发送消息时组合所需的内容。另外,使用DingtalkChatbot(conf.webhook,conf.secret)传入钉钉机器人的WebHook地址和秘钥,初始化钉钉机器人类发送钉钉消息。notify()方法用于发送钉钉消息。在这个方法中,根据self.payload的不同特点,决定调用不同的消息发送方法。例如,当事件体中包含pull_requestkey时,调用self._notify_pull_request()发送PullRequest消息。_notify_pull_request()方法是具体的消息通知实现。该方法从事件体中获取需要的信息,进一步判断事件体的类型,然后使用self.bot.send_markdown()向钉钉群发送MarkDown格式的消息。部署通知服务编写的通知逻辑,需要将逻辑部署到服务端,并提供一个可调用的URL,供GitHubWebHook调用。为了方便和免费,这里选择了阿里云的函数计算服务(FC)进行部署。FC的好处是每月有100万次免费调用,提供HTTP触发器,也就是说提供了可以调用的URL,不需要申请域名。FC有一个专门的部署工具叫ServerlessDevs。安装配置该工具后,将项目中notification/conf.py中的webhook和secret变量值替换为钉钉机器人的WebHook和secretkey,然后执行如下命令进行部署:sgithub-notificationdeploy部署完成后,访问FC控制??台,获取公网访问地址,作为GitHub仓库的WebHook,就可以愉快的接收到GitHub仓库的通知了。当GitHub仓库发生事件时,钉钉群机器人会推送相关消息,效果如下:
