Github Webhook Resloution Service

Webhook

Webhook is a type of HTTP-based callback function that can be used for lightweight, event-driven communication between two Application Programming Interfaces (APIs). A client provides a server API with a unique URL and specifies the events it wants to be informed about. After setting up a webhook, the client no longer needs to poll the server; when the specified event occurs, the server will automatically send the relevant payload to the client’s Webhook URL.

Webhooks can be an important component of automation and are easy to implement (just a single HTTP request that can be embedded anywhere). Webhook message pushing is supported by domestic platforms such as Feishu, DingTalk, and WeChat Work.

The advantages are clear, but the downside is the lack of uniform parameters for HTTP requests, since it’s too simplistic without a standardized protocol. Different platforms use different terms, such as “msg” on one platform and “message” or “text” on another. Therefore, to fully utilize webhooks, it’s necessary to create your own Webhook parsing service, which thankfully isn’t complicated. This article will use Github Webhook as an example, parsing and pushing it to WeChat Work with Flask.

However, if you don’t have highly customized needs and only want to use Github Webhook without other platforms, you can use Dingling, which can forward Github Webhook to WeChat Work. Dingling only supports pushing messages in Markdown format (which cannot be viewed directly on WeChat), which is why I gave up on it.

CloudFlare Webhook

The message body of the CloudFlare Webhook is very simple, as follows:

1
{"text":"CloudFlare is simply the conscience of the industry!"}

Parsing it with Flask and forwarding the message to WeChat Work:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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)

Deploy the Flask process on a server and fill in the address on Cloudflare as shown in the figure below

image-20240229160731848

After saving and testing, you should be able to receive a brief test message in WeChat Work.

Github Webhook

If CloudFlare’s Webhook is a short message, then Github seems to want to pass you the entire website’s information, with dozens of parameters but not a single piece of natural language. Therefore, it’s necessary to parse according to your own needs. The logic of the following code is to first determine the event type, then extract the needed information to forward based on the event type. The content parsed below includes actions such as push, release, issue, pull, etc.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
@app.route('/github', methods=['POST'])
def github():
    githubEvent = request.headers['x-github-event']
    if githubEvent == 'push':
        repository = 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"{repository} Someone committed code\nBranch: {branch}\nAuthor: {author}\nCommit message: {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':
            repository = request.json['repository']['name']
            issue = request.json['issue']
            title = issue['title']
            body = issue['body']
            user = issue['user']['login']
            data = {
                "msgtype": "text",
                "text": {
                    "content": f"{repository} Someone submitted an issue\nTitle: {title}\nContent: {body}\nSubmitter: {user}"
                }
            }
            r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'], json=data)

        if action == 'closed':
            repository = request.json['repository']['name']
            issue = request.json['issue']
            title = issue['title']
            body = issue['body']
            user = issue['user']['login']
            data = {
                "msgtype": "text",
                "text": {
                    "content": f"{repository} Someone closed an issue\nTitle: {title}\nContent: {body}\nSubmitter: {user}"
                }
            }
            r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'], json=data)
        if action == 'reopened':
            repository = request.json['repository']['name']
            issue = request.json['issue']
            title = issue['title']
            body = issue['body']
            user = issue['user']['login']
            data = {
                "msgtype": "text",
                "text": {
                    "content": f"{repository} Someone reopened an issue\nTitle: {title}\nContent: {body}\nSubmitter: {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':
            repository = 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"{repository} Someone opened a pull request\nTitle: {title}\nContent: {body}\nSubmitter: {user}"
                }
            }
            r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'], json=data)
        if action == 'closed':
            repository = 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"{repository} Someone closed a pull request\nTitle: {title}\nContent: {body}\nSubmitter: {user}"
                }
            }
            r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'], json=data)
        if action == 'reopened':
            repository = 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"{repository} Someone reopened a pull request\nTitle: {title}\nContent: {body}\nSubmitter: {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':
            repository = 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"{repository} Someone published a release\nVersion: {tag_name}\nContent: {body}\nPublisher: {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':
            repository = request.json['repository']['name']
            branch = request.json['ref']
            user = request.json['sender']['login']
            data = {
                "msgtype": "text",
                "text": {
                    "content": f"{repository} Someone created a branch\nBranch: {branch}\nCreator: {user}"
                }
            }
            r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'],
                              json=data)
        if ref_type == 'tag':
            repository = request.json['repository']['name']
            tag = request.json['ref']
            user = request.json['sender']['login']
            data = {
                "msgtype": "text",
                "text": {
                    "content": f"{repository} Someone created a tag\nTag: {tag}\nCreator: {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':
            repository = request.json['repository']['name']
            branch = request.json['ref']
            user = request.json['sender']['login']
            data = {
                "msgtype": "text",
                "text": {
                    "content": f"{repository} Someone deleted a branch\nBranch: {branch}\nDeleter: {user}"
                }
            }
            r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'],
                              json=data)
        if ref_type == 'tag':
            repository = request.json['repository']['name']
            tag = request.json['ref']
            user = request.json['sender']['login']
            data = {
                "msgtype": "text",
                "text": {
                    "content": f"{repository} Someone deleted a tag\nTag: {tag}\nDeleter: {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':
            repository = 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"{repository} Someone has submitted a pull request review\nTitle: {title}\nContent: {body}\nSubmitter: {user}\nStatus: {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':
            repository = 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"{repository} Someone has submitted a pull request review comment\nTitle: {title}\nContent: {body}\nSubmitter: {user}\nComment: {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':
    #         repository = request.json['repository']['name']
    #         check_run = request.json['check_run']
    #         name = check_run['name']
    #         conclusion = check_run['conclusion']
    #         data = {
    #             "msgtype": "text",
    #             "text": {
    #                 "content": f"{repository} Somebody has submitted a check run\nName: {name}\nStatus: {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':
            repository = request.json['repository']['name']
            check_suite = request.json['check_suite']
            conclusion = check_suite['conclusion']
            data = {
                "msgtype": "text",
                "text": {
                    "content": f"{repository} Someone has submitted a check suite\nStatus: {conclusion}"
                }
            }
            r = requests.post(
                'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key='+config['API_KEY_2'],
                json=data)
        return 'success', 200

Server and Github configurations are done. You can view detailed push information in the logs.

image-20240229160811295

Reference Documentation

Github Official Documentation

Buy me a coffee~
Tim AlipayAlipay
Tim PayPalPayPal
Tim WeChat PayWeChat Pay
0%