Bereitstellung auf PythonAnywhere von GitHub



Jeder kann das:


lokales Projekt -> Github


Mit (kostenpflichtigem) SSH-Zugriff können Sie Folgendes tun:


lokales Projekt -> PythonAnywhere


Der Artikel zeigt, wie (kostenlos) dies zu tun ist:


lokales Projekt -> Github -> PythonAnywhere


Zuerst werde ich auflisten, warum Sie dies möglicherweise benötigen, und dann mit der Implementierung fortfahren. Sie können den Artikel gerne überspringen, wenn der erste Teil für Sie nicht interessant ist.




Warum?


PythonAnywhere ist ein großartiger Service! Es ist kostenlos, bietet eine gute Leistung und sogar eine Datenbank, sodass Sie in wenigen Minuten eine dynamische Site erstellen können. Dies ist eine großartige Option für Anfänger, die etwas live ausprobieren möchten, und für diejenigen, die eine API oder ein persönliches Projekt hosten müssen.


Der Service hat aber auch Nachteile. Was ist, wenn Sie den Code öffnen möchten, an dem Sie arbeiten? Werden Sie zwei Orte gleichzeitig unterstützen und Änderungen vornehmen? Einmal in der PythonAnywhere-Produktion und ein zweites Mal in GitHub für andere Entwickler. Was ist, wenn Sie Pull Request akzeptieren oder CI integrieren möchten? Das ständige Duplizieren aller Aktionen ist sehr unpraktisch.


GitHub ist ein großartiger Dienst für die Zusammenarbeit und das Anzeigen von Quellcode. Die Benutzeroberfläche ist besser als bei PythonAnywhere, und was ich dazu führe, ist es nicht sehr angenehm, den Code direkt bei PythonAnywhere zu bearbeiten. Was wäre, wenn wir das Beste aus zwei Welten kombinieren könnten?


Sie übertragen alle Updates auf GitHub und die PythonAnywhere-Anwendung wird automatisch synchronisiert und neu gestartet. Sie können PRs blinken lassen, Tickets verwenden, Ihren Code von jedem Gerät aus anzeigen, ohne sich anzumelden und ohne eine Datei im Code-Editor zu öffnen - im Allgemeinen tun Sie alles, was GitHub Ihnen ermöglicht.


Ich höre bereits ein Murmeln: "Gut, gut, überzeugt, aber wie kann dies erreicht werden?" Kein Wort mehr!




Wie?


Wir verwenden Github-Webhooks, um Sie über ein Anwendungsupdate zu informieren, es abzurufen und neu zu laden.


Als Beispiel werde ich meine SwagLyrics- Anwendung betrachten, deren Backend ich auf PythonAnywhere halte. Ich verwende Flask, daher wird der Prozess für ein anderes Framework anders sein.


Synchronisieren Sie zunächst das Projekt so, dass GitHub der Ursprung ist. Wenn Sie noch kein PythonAnywhere-Repository erstellt haben, können Sie es initialisieren oder direkt von GitHub aus codieren.


So etwas wie:


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

Gehen Sie nun zu GitHub -> Einstellungen -> Webhooks -> Webhook hinzufügen


Dort sehen Sie:



Fügen Sie im Feld "Payload URL" Ihre_Domäne / route_to_update hinzu


Der Webhook meines Repositorys zeigt beispielsweise auf nbsp. https://aadibajpai.pythonanywhere.com/update_server


Ändern Sie den "Inhaltstyp" von application / x-www-form-urlencoded in application / json (ich werde Ihnen später erklären , warum dies erforderlich ist).


Wir werden das geheime Feld noch nicht berühren.


Stellen Sie sicher, dass die Option "Push-Ereignis" ausgewählt ist, und klicken Sie auf "Webhook hinzufügen".


Öffnen Sie Ihre Anwendung auf Flask. Wir konfigurieren eine Route, um Informationen von GitHub zu erhalten, wenn ein Push-Ereignis auftritt. Der Pfad sollte der sein, den Sie im Feld "Payload URL" angegeben haben. Wir geben den Hauptzweig nicht explizit an, als Der Einfachheit halber wird es als das einzige im Repository verstanden.


Das einfachste Setup würde so aussehen:


 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 

Dies ist das trivialste Beispiel, eine vollständigere Version wird niedriger sein.


Wenn jetzt ein Push-Ereignis auftritt, aktualisiert sich die Anwendung selbst durch Ziehen.


Wenn alles reibungslos gelaufen ist, sehen Sie Folgendes nach dem nächsten Commit:



Bevor wir mit dem Schutz des Webhooks vor Fremden fortfahren, werde ich Ihnen erklären, wie Sie die Anwendung nach dem Ziehen neu starten, damit Sie dies nicht manuell tun müssen.


Automatisches Neuladen der Webanwendung


Wir werden Git Hooks verwenden. Dies sind nur Shell-Befehle, die nach Ereignissen ausgeführt werden. Es gibt keinen Haken für die Veranstaltung nach dem Ziehen, aber ...


Wir verwenden die Tatsache, dass Git Pull nichts anderes als Git FetchGit Merge ist , sondern ein Hook für das Ereignis nach dem Zusammenführen vorhanden ist. Es wird ausgeführt, wenn der Pull erfolgreich abgeschlossen wurde.


Wechseln Sie in Ihrem PythonAnywhere-Repository zu .git / hooks /


Es sind bereits mehrere Hooks vorhanden. Fügen Sie Ihre eigenen hinzu, indem Sie eine Post-Merge- Datei erstellen


Schreiben Sie den folgenden Code hinein:


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

Verwenden Sie den Pfad zu Ihrem wsgi, der bei Änderung (Berühren) die Anwendung neu startet.


Um die Datei ausführbar zu machen, öffnen Sie die Konsole und führen Sie sie aus


 chmod +x post-merge 

Stellen Sie sicher, dass der Neustart funktioniert, indem Sie ein neues Commit durchführen.


Fahren wir nun mit der Sicherung eines Webhooks fort.




Webhook-Schutz


Der Schutz eines Webhooks ist erforderlich, damit keine anderen Personen ständig Anforderungen zum Neustart der Anwendung senden können. Wir werden diesen Leitfaden verwenden.


Fügen Sie zunächst ein geheimes Token in PythonAnywhere als Umgebungsvariable sowie im Feld "Secret" in den GitHub-Webhook-Einstellungen hinzu. Hier wird der Prozess genauer beschrieben.


GitHub gibt seine Methoden in Ruby an, aber wir verwenden Python, daher verwenden wir diese Vergleichsfunktion:


 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) 

Ändern Sie nun den Controller update_server, um zu überprüfen, ob die Signatur gültig ist, indem Sie diese Zeilen vor dem Code-Update-Teil hinzufügen:


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

w_secret sollte mit dem Wert übereinstimmen, den Sie etwas früher als Umgebungsvariable festgelegt haben.


Im Allgemeinen ist es sinnvoll, die Protokollierung und einige weitere Überprüfungen hinzuzufügen, um sicherzustellen, dass der GitHub-Webhook oder das Ereignis Daten enthält. Wenn Sie möchten, können Sie den entsprechenden Code aus meinem Repository kopieren und gegebenenfalls ändern, da Sie bereits alles wissen das wichtige


Hoffe die Informationen waren hilfreich. Ich weiß, dass es viele Dinge gibt, aber ich wollte, dass Sie verstehen, was passiert ist.




Ich habe mir nicht alles selbst ausgedacht, sondern das Wichtigste aus verschiedenen Quellen zusammengetragen und eine Komplettlösung erstellt.


Hier sind die Links, die mir geholfen haben und Ihnen helfen können:
  1. https://stackoverflow.com/a/54268132/9044659 (Grundeinstellung)
  2. https://developer.github.com/webhooks/ (GitHub-Webhook-Dokumentation)
  3. https://github.com/CCExtractor/sample-platform/blob/master/mod_deploy/controllers.py (eine sehr detaillierte Implementierung mit einer Reihe von Überprüfungen, wenn Sie Zeit damit verbringen möchten)
  4. https://github.com/SwagLyrics/swaglyrics-issue-maker/blob/35d23d0ba416e742e381da931d592ce6f58fc13f/issue_maker.py#L268 (meine Controller-Implementierung für PythonAnywhere)
  5. https://github.com/SwagLyrics/SwagLyrics-For-Spotify (Repository, in dem ich dies in der Praxis verwende)

Danke fürs Lesen!

Source: https://habr.com/ru/post/de457348/


All Articles