使用 Github 和 Python 进行持续部署

[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]

Related Posts