Workflows
TL;dr: Or, you could just use Gitlab or Github..
Für die Entwicklung einer Webanwendung mit Flask kann es nützlich sein, dass Änderungen am Code schnell auf einen Server übertragen und dort direkt ausgespielt werden können. Zwei Fälle sind für mich hier relevant: Die Zusammenarbeit am Code mit Leuten, die selber keine Flask-Entwicklungsumgebung einrichten, aber Änderungen beisteuern und ausprobieren wollen, und das Reflektieren von einfachen Änderungen bei der iterativen Entwicklung im Kontakt mit Nutzer*innen.
Flask bietet einen integrierten Entwicklungsserver, mit dem eine
Anwendung lokal gestartet werden kann. Wird der Server im Debug-Modus
gestartet werden Änderungen direkt in den ausgespielten Seiten
angezeigt. Das heißt der Entwicklungsserver erkennt, dass eine Änderung
gemacht wurde, und führt die notwendigen Reloads durch. Der Server im
wird im Debug-Modus gestartet mit
flask --app my_app --debug run
(ab Flask-Version
2.2.x). Jetzt können alle Änderungen am Code, die Änderungen in der
Ausgabe hervorbringen, direkt im Browser beobachtet und geprüft werden.
Ich verwende das zum Beispiel für die Anpassung von Templates für
ausgegebene Seiten.
Dieser Entwicklungs-Workflow funktioniert wenn alleine entwickelt wird. Was machen wir wenn wir kollaborativ entwickeln? Mit der Versionierungslösung Git können Änderungen vom lokalen Rechner in ein Git-Repository und vom Repository wieder auf lokale Rechner übertragen werden. Wenn also zwei Leute an einer Anwendung arbeiten, spielen beide ihre Änderungen ins Repository und holen sich die Änderungen der jeweils anderen Person auch aus diesem Repository. Beide entwickeln also lokal mit einem eigenen lokalen Entwicklungsserver, der Code wird über das Repository geteilt.
Aber was tun wenn Leute an der Anwendungsentwicklung beteiligt sind,
die die Anwendung nicht lokal laufen lassen wollen oder können, weil sie
vielleicht CSS beitragen, aber normalerweise nicht mit Python arbeiten?
Dann fehlt der lokale Entwicklungsserver und wir brauchen einen
entfernten Entwicklungsserver, auf dem die Anwendung installiert ist,
läuft, und von außen erreichbar ist. Änderungen am Code müssen so
übertragen werden können, dass sie nachvollziehbar sind, also rückgängig
gemacht werden können, und direkt vom Server reflektiert werden. Wir
arbeiten in diesem Szenario schon mit Git. Der Code für die Anwendung
liegt in einem Git-Repository auf dem Server, das für alle
Beiträger*innen erreichbar ist. Um Änderungen auf den Server zu
übertragen reicht es also, sie wie bei der normalen Arbeit mit Git mit
dem Befehl git push
zu übertragen. Die Beiträger*innen
werden dadurch entlastet: Es reicht, wenn Änderungen ins zentrale
Repository übertragen werden. Von dort werden sie automatisiert auf den
Server gespiegelt und direkt in der laufenden Anwendung reflektiert.
Server einrichten
Der Server wird so eingerichtet, dass
- Änderungen via git direkt auf den Server übertragen werden können
- der Server für die Webanwendung im Reload-Modus läuft, also Änderungen an der Anwendung direkt reflektiert werden
Für Punkt a) wird ein Git-Repository benötigt, das für alle Beteiligten zugänglich ist. Auf dem Server wird dann ein Skript eingerichtet, das regelmäßig die Änderungen aus dem Repository auf den Server holt. Das Repo kann auf dem Server liegen oder anderswo. Es muss lediglich sichergestellt werden dass die Änderungen automatisiert übertragen werden kann. Mein Setup:
- Ein leeres Git-Repo auf dem Server einrichten, auf dem auch die
Anwendung läuft. Ordner anlegen, dann im Ordner das Repo einrichten mit
git init --bare
. - Dieses Repo auf meinem lokalen git repo als remote repository setzen
mit
git remote add origin ssh://[username]@example.org:[path_to_git]
- Inhalte übertragen mit
git push origin main
- Auf dem Server das Repo in einem eigenen Anwendungsverzeichnis
klonen mit
git clone [path_to_git]
. Das ist notwendig, weil das neu angelegte git-repo aus dem ersten Schritt kein Arbeitsverzeichnis ist, sondern eine etwas andere Struktur hat. Dort liegen keine Ordner und Dateien, die bearbeitet werden können. - Das regelmäßige Update des geklonten Repos automatisieren.
Für Punkt b) nutze ich den Anwendungsserver Gunicorn. Gunicorn bietet eine
Reloadfunktion, die einfach mit der Option --reload
aktiviert wird. Die Flask-Anwendung wird mit Gunicorn ausgeführt und ist
dann über die angezeigte Adresse erreichbar. Der Gunicorn-Befehl muss so
ausgeführt werden, dass er unabhängig von der aktiven SSH-Session läuft,
zum Beispiel mit einem Terminal-Multiplexer wie screen oder tmux.
Im Ergebnis können alle Beteiligten ihre Änderungen am Code auf dem Server testen. Zu beachten ist, dass die Bereitstellung der Anwendung im Netz ein Sicherheitsrisiko darstellt, das durch entsprechende Zugangsbeschränkungen möglichst gering gehalten werden sollte.