[ad_1]
开发人员可以使用 Github 的 webhook 创建许多有用的服务。 从在 Jenkins 实例上触发 CI 作业到在云中配置机器,可能性几乎是无限的。 本教程展示了如何使用 Python 和 Flask 框架来构建一个简单的持续部署服务。
此示例中的持续部署服务是一个简单的 Flask 应用程序,带有一个 REST 端点,它将接收 Github 的 webhook 请求。 在验证每个请求以检查它是否来自正确的 Github 存储库后,该服务会将更改拉取到存储库的本地副本。 这样,每次将新的提交推送到远程 Github 存储库时,本地存储库都会自动更新。
烧瓶网络服务
使用 Flask 构建小型 Web 服务很容易。 下面看一下项目结构。
├── app │ ├── __init__.py │ └── webhooks.py ├── requirements.txt └── wsgi.py
首先,创建应用程序。 应用程序代码位于 app 目录下。
两个文件(__init__.py 和 webhooks.py)组成了 Flask 应用程序。 前者具有创建 Flask 应用程序并向其添加配置所需的代码。 后者具有端点逻辑。 这是应用程序从 Github 请求中接收数据的地方。
这是 app/__init__.py 的内容:
import os from flask import Flask from .webhooks import webhook def create_app(): """ Create, configure and return the Flask application """ app = Flask(__name__) app.config['GITHUB_SECRET'] = os.environ.get('GITHUB_SECRET') app.config['REPO_PATH'] = os.environ.get('REPO_PATH') app.register_blueprint(webhook) return(app)
该函数创建两个配置变量:
- GITHUB_SECRET 持有一个秘密密码,用于验证 Github 请求。
- REPO_PATH 保存要自动更新的存储库的路径。
此代码使用 烧瓶蓝图 组织应用程序端点。 使用蓝图允许对 API 进行逻辑分组,使应用程序更易于维护。 这通常被认为是一种良好的做法。
这是 app/webhooks.py 的内容:
import hmac from flask import request, Blueprint, jsonify, current_app from git import Repo webhook = Blueprint('webhook', __name__, url_prefix='') @webhook.route('/github', methods=['POST']) def handle_github_hook(): """ Entry point for github webhook """ signature = request.headers.get('X-Hub-Signature') sha, signature = signature.split('=') secret = str.encode(current_app.config.get('GITHUB_SECRET')) hashhex = hmac.new(secret, request.data, digestmod='sha1').hexdigest() if hmac.compare_digest(hashhex, signature): repo = Repo(current_app.config.get('REPO_PATH')) origin = repo.remotes.origin origin.pull('--rebase') commit = request.json['after'][0:6] print('Repository updated with commit {}'.format(commit)) return jsonify({}), 200
首先,代码创建一个新的蓝图 webhook。 然后它使用 Flask 路由向蓝图添加一个新端点。 此路由将由 /github URL 端点上的任何 POST 请求调用。
验证请求
当服务在此端点上收到请求时,它必须首先验证请求来自 Github 和正确的存储库。 Github 在请求头 X-Hub-Signature 中给出签名。 此签名是使用秘密 (GITHUB_SECRET) 生成的,即 HMAC 请求正文的十六进制摘要,然后使用 sha1 哈希函数进行哈希处理。
为了验证请求,服务需要在本地计算签名并将其与请求标头中收到的签名进行比较。 这是由 hmac.compare_digest 函数完成的。
自定义钩子逻辑
验证请求后,现在可以处理它。 本教程使用 GitPython 与 git 存储库交互的模块。 在 GitPython 模块中,Repo 对象用于访问名为 origin 的远程存储库。 该服务从原始存储库本地提取最新更改,还使用 –rebase 选项来避免合并问题。
调试打印语句显示从请求正文接收到的短提交哈希。 此示例显示如何使用请求正文。 有关正文中可用数据的更多详细信息,请查看 github的文档.
最后,服务返回一个空的 JSON 字符串和一个 200 状态码。 这告诉 Github 的 webhook 服务器收到了请求。
部署服务
要运行该服务,此示例使用 独角兽 网络服务器。 首先安装服务依赖项。 在受支持的 Fedora 服务器,将此命令与 sudo:
sudo dnf install python3-gunicorn python3-flask python3-GitPython
现在编辑 gunicorn 用来运行服务的 wsgi.py 文件:
from app import create_app application = create_app()
要部署此服务,请克隆此 git 存储库 或通过以下命令使用您自己的 git 存储库:
git clone https://github.com/cverna/github_hook_deployment.git /opt/
下一步是配置服务所需的环境变量。 运行这些命令:
export GITHUB_SECRET=asecretpassphraseusebygithubwebhook export REPO_PATH=/opt/github_hook_deployment/
本教程使用 webhook 服务 Github 存储库,但如果您愿意,可以使用不同的存储库。 最后,使用以下命令启动网络服务器:
cd /opt/github_hook_deployment/ gunicorn --bind 0.0.0.0 wsgi:application --reload
这些选项将 Web 服务器绑定到 0.0.0.0 ip 地址,这意味着它将接受来自任何主机的请求。 –reload 选项可确保 Web 服务器在代码更改时重新启动。 这就是持续部署魔法发生的地方。 收到的每个 Github 请求都会拉取存储库中的最新更改,gunicorn 会检测到这些更改并自动重新启动应用程序。
笔记: 为了接收来自 github 的请求,Web 服务必须部署在具有公共 IP 地址的服务器上。 一个简单的方法是使用您最喜欢的云提供商,例如 DigitalOcean、AWS、Linode 等。
配置 Github
本教程的最后一部分配置 Github 以将 webhook 请求发送到 web 服务。 这是持续部署的关键。
从您的 Github 存储库设置中,选择 Webhook 菜单并单击 Add Webhook。 Enter 以下信息:
- 有效载荷网址: 服务的 URL,例如 https://public_ip_address:8000/github
- 内容类型: 选择应用程序/json
- 秘密: 这 GITHUB_SECRET 前面定义的环境变量
然后单击添加 Webhook 按钮。
每次在此存储库上发生推送事件时,Github 都会向服务发送请求。
结论
本教程向您展示了如何编写基于 Flask 的 Web 服务,该服务接收来自 Github Webhook 的请求并进行持续部署。 您现在应该能够使用本教程作为起始基础来构建您自己的有用服务。
[ad_2]