Quantcast
Channel: CodeSection,代码区,Python开发技术文章_教程 - CodeSec
Viewing all articles
Browse latest Browse all 9596

用 Django 来响应 Github Webhook

$
0
0

由瞳人

发布于 June 20, 2016, 4:44 p.m.

16 个评论

Django Github

利用 Django 来响应 Github 的 webhook 请求.

由于本 vps 上的 gitlab 开销大,所以我把所有项目移到 github 上。因此原先针对 gitlab 的 webhook 代码 就需要更新了。

关于 github webhook 的介绍,可以看后文的参考链接,这里就简单叙述一下解决方案。

当你向你 github 中的 repo 添加一个新的 webhook 时,github 会给你发一个 ping 事件的 post 请求, 这时你就可以在数据库中登记这个webhook。

你可以在 github 上设置触发该 webhook 的事件类型,我这里就设置了 push 事件。

为了安全起见,github 可以设置一个密钥,然后你可以在响应代码中进行验证。

同样的,与之前 gitlab 的 webhook 代码 中一样,我们现在数据库中添加一些需要验证的信息,包括 repository 的名字,ssh clone 地址即 'git@github.com:user/repo.git',secret,repository 的 id 等,但在初始化时我们先把 repo_id 填成 -1 ,这个值稍后由代码更新。

代码

models.py

# coding=utf-8 from django.db import models from django.utils.translation import ugettext as _ class Github_Webhook(models.Model): ''' Model for webhook of github ''' repo_name = models.CharField( verbose_name = _(u'repository name'), help_text = _(u' '), max_length = 255 ) repo_ssh_url = models.CharField( verbose_name = _(u'repository ssh_url'), help_text = _(u' '), max_length = 255 ) repo_id = models.IntegerField( verbose_name = _(u'repository id value'), help_text = _(u'Your repository id in github'), default = 0 ) secret = models.CharField( verbose_name = _(u'repository secret'), help_text = _(u' '), max_length = 255 ) def __unicode__(self): return u'%s' % (self.repo_name,)

views.py :

@csrf_exempt def github_webhook(request): if request.method == 'POST' and request.body: http_x_github_event = request.META.get('HTTP_X_GITHUB_EVENT', '') http_x_hub_signature = request.META.get('HTTP_X_HUB_SIGNATURE', '') json_data = json.loads(request.body) repo_data = json_data.get('repository', '') sender_data = json_data.get('sender', '') if repo_data and sender_data and http_x_hub_signature: user_id = sender_data.get('id', '') user_name = sender_data.get('login', '') repo_name = repo_data.get('name', '') repo_id = repo_data.get('id', '') repo_ssh_url = repo_data.get('ssh_url', '') sha_name, signature = http_x_hub_signature.split('=') if sha_name != 'sha1': return HttpResponseForbidden('HeHe!') webhook = Github_Webhook.objects.filter( repo_name=repo_name, repo_ssh_url=repo_ssh_url ).first() if webhook: # HMAC requires the key to be bytes, but data is string mac = hmac.new(str(webhook.secret), msg=request.body, digestmod=sha1) # python prior to 2.7.7 does not have hmac.compare_digest if hexversion >= 0x020707F0: if not hmac.compare_digest(str(mac.hexdigest()), str(signature)): return HttpResponseForbidden('HeHe!') else: # What compare_digest provides is protection against timing # attacks; we can live without this protection for a web-based # application if not str(mac.hexdigest()) == str(signature): return HttpResponseForbidden('HeHe!') if webhook.repo_id == -1 and http_x_github_event == 'ping': # Save this webhook webhook.repo_id = int(repo_id) webhook.save() content = u'Save github webhook: [%s] by user %s, %s' % ( webhook, user_id, user_name) write_log(content) return HttpResponse('Webhook saved!') if webhook.repo_id == int(repo_id) and http_x_github_event == 'push': # Do your webhook job # such as restarting a docker container. content = u'Restart github webhook: [%s] by user %s, %s' % ( webhook, user_id, user_name) write_log(content) return HttpResponse('Restarted!') return HttpResponseForbidden('HeHe!') 参考链接

我的博客 用 Django 来响应 Gitlab Webhook

carlos-jenkins/python-github-webhooks

Github webhook 官方介绍

Github Event Types & Payloads 官方介绍

哎呦, 不错哦!


用 Django 来响应 Github Webhook
用 Django 来响应 Github Webhook

用手机 支付宝钱包 / 微信 , 扫一扫即可~谢谢您的鼓励


Viewing all articles
Browse latest Browse all 9596

Trending Articles