从GitHub部署在PythonAnywhere上



每个人都可以这样做:


本地项目-> github


使用(收费)ssh访问权限,您可以执行以下操作:


本地项目-> PythonAnywhere


本文显示了如何(免费)执行此操作:


本地项目-> github-> PythonAnywhere


首先,我将列出您可能需要它的原因,然后继续介绍如何实现它。 如果您对第一部分不感兴趣,请随时跳过本文。




怎么了


PythonAnywhere是一项很棒的服务! 它是免费的,提供强大的功能,甚至提供数据库,因此您可以在几分钟内创建一个动态站点。 对于想要尝试现场体验的初学者以及需要托管API或某些个人项目的人来说,这是一个很好的选择。


但是该服务也有缺点。 如果要打开正在处理的代码怎么办? 您会同时在两个地方支持并进行更改吗? 一次在PythonAnywhere生产中,第二次在GitHub上供其他开发人员使用。 如果您接受Pull Request或想要集成CI,该怎么办? 不断重复所有动作非常不便。


GitHub是一个很好的服务,可以一起工作和查看源代码,它们的UI比在PythonAnywhere上更好,而且,我的意思是,直接在PythonAnywhere上编辑代码不是很愉快。 如果我们可以将两个世界的优点结合起来怎么办?


您将所有更新推送到GitHub上,PythonAnywhere应用程序将自动同步并重新启动。 您可以在任何设备上闪烁PR,使用票证,从任何设备查看代码,甚至无需登录,也无需在代码编辑器中打开文件-通常,GitHub可以做的所有事情。


我已经听到一个杂音:“好,好,被说服,但是如何实现呢?” 一句话不多!




怎么了


我们使用Github Webhooks来通知您应用程序更新,拉动并重新加载它。


作为示例,我将考虑我的SwagLyrics应用程序,该应用程序的后端位于PythonAnywhere上。 我使用的是Flask,因此对于另一个框架,该过程将有所不同。


首先,同步项目,使GitHub成为源。 如果尚未创建PythonAnywhere存储库,则可以对其进行初始化或直接从GitHub对其进行编码。


类似于:


git init git remote add origin https://github.com/yourusername/yourreponame.git 

现在转到GitHub->设置-> Webhooks->添加webhook


在那里,您将看到:



在“有效负载网址”字段中,添加your_domain / route_to_update


例如,我的存储库的webhook指向nbsp; https://aadibajpai.pythonanywhere.com/update_server


将“内容类型”从application / x-www-form-urlencoded更改为application / json (稍后再告诉您为什么需要这样做)。


我们不会触摸“秘密”字段。


确保选择了“推送事件”选项,然后单击“添加webhook”。


在Flask上打开您的应用程序,我们将配置一条路由,以在推送事件发生时从GitHub接收信息。 该路径应该是您在“有效载荷URL”字段中指定的路径。 我们没有明确指定master分支,因为 为了简单起见,它暗示它是存储库中唯一的一个。


最简单的设置如下所示:


 from flask import Flask, request import git 

 app = Flask(__name__) 

 @app.route('/update_server', methods=['POST']) def webhook(): if request.method == 'POST': repo = git.Repo('path/to/git_repo') origin = repo.remotes.origin 

  origin.pull() 

  return 'Updated PythonAnywhere successfully', 200 else: return 'Wrong event type', 400 

这是最简单的例子,一个完整的版本会更低。


现在,每当发生push事件时,应用程序都会通过pull进行更新。


如果一切顺利,则下一次提交后,您将看到以下内容:



在继续保护Webhook免受陌生人攻击之前,我将告诉您如何在拉动后重新启动应用程序,这样您就无需手动执行此操作。


Web应用程序自动重新加载


我们将使用git hooks。 这些只是事件后执行的shell命令。 拉动后没有事件挂钩,但是...


我们使用git pull仅仅是git fetchgit merge的事实,但是存在合并后事件的钩子。 如果拉取成功完成,将执行它。


在您的PythonAnywhere存储库中,转到.git / hooks /


现有的钩子已经存在,可以通过创建一个合并后的文件来添加自己的钩子


将以下代码写入其中:


 #!/bin/sh touch /path/to/username_pythonanywhere_com_wsgi.py 

使用您的wsgi的路径,该路径在更改(触摸)后将重新启动应用程序。


要使文件可执行,请打开控制台并运行


 chmod +x post-merge 

通过进行新的提交来确保重新启动有效。


现在让我们继续进行安全性。




Webhook保护


必须保护Webhook,以便其他人无法不断发送重新启动应用程序的请求。 我们将使用指南。


首先,在PythonAnywhere上以及在GitHub webhook设置的“ Secret”字段中添加一个秘密令牌作为环境变量。 在此将更详细地描述过程。


GitHub在Ruby中提供了其方法,但是我们使用Python,因此我们将使用以下比较功能:


 import hmac import hashlib def is_valid_signature(x_hub_signature, data, private_key): # x_hub_signature and data are from the webhook payload # private key is your webhook secret hash_algorithm, github_signature = x_hub_signature.split('=', 1) algorithm = hashlib.__dict__.get(hash_algorithm) encoded_key = bytes(private_key, 'latin-1') mac = hmac.new(encoded_key, msg=data, digestmod=algorithm) return hmac.compare_digest(mac.hexdigest(), github_signature) 

现在,通过在代码更新部分之前添加以下行来修改update_server控制器以检查签名是否有效:


 x_hub_signature = request.headers.get('X-Hub-Signature') if not is_valid_signature(x_hub_signature, request.data, w_secret): 

w_secret应该与您之前设置为环境变量的值匹配。


通常,添加日志记录和更多检查以确保GitHub Webhook或该事件包含数据是有意义的 ,因此,如果您愿意,您可以从我的存储库中复制相关代码 ,并在必要时进行更改,因为您已经知道了一切重要的


希望这些信息对您有所帮助。 我知道有很多事情,但是我希望您了解正在发生的事情。




我自己并没有提出所有建议,而是从各种渠道收集了最重要的建议,并创建了完整的解决方案。


以下链接对我有帮助,可以为您提供帮助:

感谢您的阅读!

Source: https://habr.com/ru/post/zh-CN457348/


All Articles