如何在Python中接收Github Webhooks

40 投票
5 回答
52425 浏览
提问于 2025-04-17 13:44

Github提供了一种功能,当你的代码库有活动时,可以把信息发送到你指定的URL,这个功能叫做Post-receive hooks。我想写一个的Python命令行程序(也就是没有图形界面或网页应用),这个程序会在我的电脑上(以后可能会放在NAS上)持续监听这些来自Github的POST请求。一旦收到Github发来的POST请求,它就会处理里面的JSON信息。处理这些JSON数据对我来说没问题。

这些POST请求可能只会来自Github提供的少数几个IP地址;我打算/希望能指定一个端口,让请求发送到我的电脑上。

问题是,我对网络技术了解得不够,搜索时看到的选项太多了……我该用Django、Requests、sockets、Flask,还是微框架呢?我对大多数术语的意思都不太清楚,而且听起来很多都太复杂,解决不了我的问题——我感到有点不知所措,不知道从哪里开始。

我找到的大多数关于POST/GET的教程似乎都是在讲如何发送或直接请求网站的数据,而不是持续监听数据。

我觉得这个问题其实并不难,一旦我知道该怎么做,就能用几行代码解决。有没有人能给我一些指引、教程、例子或者示例代码呢?

5 个回答

2

我会推荐使用:

https://github.com/carlos-jenkins/python-github-webhooks

你可以配置一个网络服务器来使用它,或者如果你只是想在没有网络服务器的情况下运行一个进程,你可以启动内置的服务器:

python webhooks.py

这样你就可以完成你所需要的所有功能。不过,这需要你在你的代码库和钩子里做一些设置。

抱歉来得有点晚,还顺便做了个自我宣传。

45

首先,网络是基于请求和响应的。也就是说,有人会请求你的链接,而你需要做出相应的回应。你的服务器应用会一直在一个端口上监听这个请求,你不需要为此担心。

下面是一个在 Flask(我喜欢的微框架)中的类似版本:

from flask import Flask, request
import json

app = Flask(__name__)

@app.route('/',methods=['POST'])
def foo():
   data = json.loads(request.data)
   print "New commit by: {}".format(data['commits'][0]['author']['name'])
   return "OK"

if __name__ == '__main__':
   app.run()

这里有一个示例运行,使用的是来自 github 的例子:

运行服务器(上面的代码保存在 sample.py 文件中):

burhan@lenux:~$ python sample.py 
 * Running on http://127.0.0.1:5000/

这是对服务器的请求,基本上就是github会做的事情:

burhan@lenux:~$ http POST http://127.0.0.1:5000 < sample.json
HTTP/1.0 200 OK
Content-Length: 2
Content-Type: text/html; charset=utf-8
Date: Sun, 27 Jan 2013 19:07:56 GMT
Server: Werkzeug/0.8.3 Python/2.7.3

OK # <-- this is the response the client gets

这是服务器的输出:

New commit by: Chris Wanstrath
127.0.0.1 - - [27/Jan/2013 22:07:56] "POST / HTTP/1.1" 200 -
26

这里有一个简单的 web.py 示例,用来接收通过 POST 发送的数据,并对这些数据进行处理(在这个例子中,就是把它打印到标准输出):

import web

urls = ('/.*', 'hooks')

app = web.application(urls, globals())

class hooks:
    def POST(self):
        data = web.data()
        print
        print 'DATA RECEIVED:'
        print data
        print
        return 'OK'

if __name__ == '__main__':
    app.run()

我使用 hurl.it 向它发送了一些数据(在此之前,我在路由器上转发了 8080 端口),然后看到了以下输出:

$ python hooks.py 
http://0.0.0.0:8080/

DATA RECEIVED: 
test=thisisatest&test2=25

50.19.170.198:33407 - - [27/Jan/2013 10:18:37] "HTTP/1.1 POST /hooks" - 200 OK

你可以把打印的部分换成你自己的 JSON 数据处理代码。

要指定端口号,可以在运行脚本时加一个额外的参数:

$ python hooks.py 1234 

撰写回答