GithubWebhook解析服务
Webhook
Webhook是一种基于HTTP的回调函数,可在两个应用编程接口(API)之间实现轻量级的事件驱动通信。客户端向服务器API提供唯一URL,并指定它想要知道的事件。设置webhook后,客户端不再需要轮询服务器;发生指定的事件时,服务器会自动将相关的有效负载发送到客户端的Webhook URL。
Webhook可以是实现自动化的重要一环,而且实现简单(仅一次http请求,可以嵌到任何地方),国内飞书、钉钉和企业微信等都支持Webhook推送消息。
以上是好处,那么坏处就是http请求的参数不统一,就是因为它太简单了,没有协议规范,一个平台一个样,比如在某平台上消息叫做”msg”,在其它平台可能就是”message”或”text”。因而想要真正发挥Webhook的作用,需要搭建一个自己的Webhook解析处理服务,好在这并不复杂。本文将以Github Webhook为例,基于Flask进行解析并推送到企业微信。
然而,如果您没有高度自定义的需求,且仅想使用Github Webhook而不使用其它平台的,可以使用Dingling,它可以将GIthub Webhook转发到企业微信。DIngling只支能推送Markdown格式的消息(不能在微信中直接查看)是我放弃它的原因。
CloudFlare Webhook
CloudFlare Webhook 的消息体非常简单,如下:
{"text":"CloudFlare简直是业界良心!"}
使用Flask解析,并将消息转发到企业微信:
from flask import Flask, request, jsonify,abort
import requests
from config import config
app = Flask(__name__)
@app.route('/cloudflare', methods=['POST'])
def cloudflare():
if request.method == 'POST':
print(request.json)
text = request.json['text']
data = {
"msgtype": "text",
"text": {
"content": text
}
}
r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_3'], json=data)
print(r.json())
return 'success', 200
else:
abort(400)
if __name__ == '__main__':
app.run(port=5700,host='0.0.0.0',debug=True)
将Flask进程部署到服务器上,并在Cloudflare上填写地址,如下图
保存并测试之后,应该就能在企业微信中收到一条简短的测试消息了。
Github Webhook
如果说CloudFlare的Webhook是一条简短的消息,那么Github恨不得把整个网站的信息全都传给你,参数有几十个,但是没有一句是自然语言,因而需要根据自己的需求解析。下段代码的逻辑是先判断事件类型,再根据事件类型提取需要的信息转发出去。下面解析的内容包括push,release,issue,pull等行为。
@app.route('/github', methods=['POST'])
def github():
githubEvent = request.headers['x-github-event']
if githubEvent == 'push':
respority = request.json['repository']['name']
branch = request.json['ref'].split('/')[-1]
commits = request.json['commits']
for commit in commits:
author = commit['author']['name']
message = commit['message']
data = {
"msgtype": "text",
"text": {
"content": f"{respority} 有人提交了代码\n分支:{branch}\n作者:{author}\n提交信息:{message}"
}
}
r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'], json=data)
return 'success', 200
if githubEvent == 'issues':
action = request.json['action']
if action == 'opened':
respority = request.json['repository']['name']
issue = request.json['issue']
title = issue['title']
body = issue['body']
user = issue['user']['login']
data = {
"msgtype": "text",
"text": {
"content": f"{respority} 有人提交了 issue\n标题:{title}\n内容:{body}\n提交者:{user}"
}
}
r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'], json=data)
if action == 'closed':
respority = request.json['repository']['name']
issue = request.json['issue']
title = issue['title']
body = issue['body']
user = issue['user']['login']
data = {
"msgtype": "text",
"text": {
"content": f"{respority} 有人关闭了 issue\n标题:{title}\n内容:{body}\n提交者:{user}"
}
}
r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'], json=data)
if action == 'reopened':
respority = request.json['repository']['name']
issue = request.json['issue']
title = issue['title']
body = issue['body']
user = issue['user']['login']
data = {
"msgtype": "text",
"text": {
"content": f"{respority} 有人重新打开了 issue\n标题:{title}\n内容:{body}\n提交者:{user}"
}
}
r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'], json=data)
return 'success', 200
if githubEvent == 'pull_request':
action = request.json['action']
if action == 'opened':
respority = request.json['repository']['name']
pull_request = request.json['pull_request']
title = pull_request['title']
body = pull_request['body']
user = pull_request['user']['login']
data = {
"msgtype": "text",
"text": {
"content": f"{respority} 有人提交了 pull request\n标题:{title}\n内容:{body}\n提交者:{user}"
}
}
r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'], json=data)
if action == 'closed':
respority = request.json['repository']['name']
pull_request = request.json['pull_request']
title = pull_request['title']
body = pull_request['body']
user = pull_request['user']['login']
data = {
"msgtype": "text",
"text": {
"content": f"{respority} 有人关闭了 pull request\n标题:{title}\n内容:{body}\n提交者:{user}"
}
}
r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'], json=data)
if action == 'reopened':
respority = request.json['repository']['name']
pull_request = request.json['pull_request']
title = pull_request['title']
body = pull_request['body']
user = pull_request['user']['login']
data = {
"msgtype": "text",
"text": {
"content": f"{respority} 有人重新打开了 pull request\n标题:{title}\n内容:{body}\n提交者:{user}"
}
}
r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'], json=data)
return 'success', 200
if githubEvent == 'release':
action = request.json['action']
if action == 'published':
respority = request.json['repository']['name']
release = request.json['release']
tag_name = release['tag_name']
body = release['body']
user = release['author']['login']
data = {
"msgtype": "text",
"text": {
"content": f"{respority} 有人发布了 release\n版本:{tag_name}\n内容:{body}\n发布者:{user}"
}
}
r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'], json=data)
return 'success', 200
if githubEvent == 'ping':
data = {
"msgtype": "text",
"text": {
"content": "github webhook test"
}
}
r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'], json=data)
return 'success', 200
if githubEvent == 'create':
ref_type = request.json['ref_type']
if ref_type == 'branch':
respority = request.json['repository']['name']
branch = request.json['ref']
user = request.json['sender']['login']
data = {
"msgtype": "text",
"text": {
"content": f"{respority} 有人创建了分支\n分支:{branch}\n创建者:{user}"
}
}
r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'],
json=data)
if ref_type == 'tag':
respority = request.json['repository']['name']
tag = request.json['ref']
user = request.json['sender']['login']
data = {
"msgtype": "text",
"text": {
"content": f"{respority} 有人创建了 tag\ntag:{tag}\n创建者:{user}"
}
}
r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'],
json=data)
return 'success', 200
if githubEvent == 'delete':
ref_type = request.json['ref_type']
if ref_type == 'branch':
respority = request.json['repository']['name']
branch = request.json['ref']
user = request.json['sender']['login']
data = {
"msgtype": "text",
"text": {
"content": f"{respority} 有人删除了分支\n分支:{branch}\n删除者:{user}"
}
}
r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'],
json=data)
if ref_type == 'tag':
respority = request.json['repository']['name']
tag = request.json['ref']
user = request.json['sender']['login']
data = {
"msgtype": "text",
"text": {
"content": f"{respority} 有人删除了 tag\ntag:{tag}\n删除者:{user}"
}
}
r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'],
json=data)
return 'success', 200
if githubEvent == 'pull_request_review':
action = request.json['action']
if action == 'submitted':
respority = request.json['repository']['name']
pull_request = request.json['pull_request']
title = pull_request['title']
body = pull_request['body']
user = pull_request['user']['login']
review = request.json['review']
state = review['state']
data = {
"msgtype": "text",
"text": {
"content": f"{respority} 有人提交了 pull request review\n标题:{title}\n内容:{body}\n提交者:{user}\n状态:{state}"
}
}
r = requests.post(
'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'],
json=data)
return 'success', 200
if githubEvent == 'pull_request_review_comment':
action = request.json['action']
if action == 'created':
respority = request.json['repository']['name']
pull_request = request.json['pull_request']
title = pull_request['title']
body = pull_request['body']
user = pull_request['user']['login']
comment = request.json['comment']
comment_body = comment['body']
data = {
"msgtype": "text",
"text": {
"content": f"{respority} 有人提交了 pull request review comment\n标题:{title}\n内容:{body}\n提交者:{user}\n内容:{comment_body}"
}
}
r = requests.post(
'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'],
json=data)
return 'success', 200
# if githubEvent == 'check_run':
# action = request.json['action']
# if action == 'created':
# respority = request.json['repository']['name']
# check_run = request.json['check_run']
# name = check_run['name']
# conclusion = check_run['conclusion']
# data = {
# "msgtype": "text",
# "text": {
# "content": f"{respority} 有人提交了 check run\n名称:{name}\n状态:{conclusion}"
# }
# }
# r = requests.post(
# 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'],
# json=data)
# return 'success', 200
if githubEvent == 'check_suite':
action = request.json['action']
if action == 'completed':
respority = request.json['repository']['name']
check_suite = request.json['check_suite']
conclusion = check_suite['conclusion']
data = {
"msgtype": "text",
"text": {
"content": f"{respority} 有人提交了 check suite\n状态:{conclusion}"
}
}
r = requests.post(
'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'],
json=data)
return 'success', 200
配置好服务端和Github,可在历史记录中查看详细的推送信息。