Schritt 11: Den Code branchen

5.2 version
Maintained Unmaintained
5.0

Den Code branchen

Es gibt viele Möglichkeiten, den Workflow von Code-Änderungen in einem Projekt zu organisieren – Das direkte Arbeiten am Git Master-Branch und der direkte Einsatz im Produktivbetrieb ohne Tests ist aber nicht der beste Weg.

Beim Testen geht es nicht nur um Unit- oder Funktionale Tests, sondern auch um die Überprüfung des Anwendungsverhaltens mit echten Daten. Wenn Du oder Deine Stakeholder die Anwendung genau so benutzen können, wie sie für Endbenutzer*innen bereitgestellt wird, entsteht ein großer Vorteil, der Dir ermöglicht die Anwendung mit Vertrauen deployen zu können. Es ist besonders effizient, wenn nicht-technische Personen neue Funktionen validieren können.

Wir werden der Einfachheit halber (und zur Vermeidung von Wiederholungen) die nächsten Schritte auf dem Git Master-Branch fortführen, aber mal sehen, wie das besser funktionieren könnte.

Einen Git-Workflow einführen

Ein möglicher Workflow ist die Erstellung eines Branches pro neuem Feature oder Bugfix. Das ist einfach und effizient.

Branches erstellen

Der Workflow beginnt mit der Erstellung eines Git-Branches:

1
$ git branch -D sessions-in-db || true
1
$ git checkout -b sessions-in-db

Dieser Befehl erstellt einen sessions-in-db-Branch, basierend auf dem master-Branch. Es „spaltet“ den Code und die Infrastrukturkonfiguration vom master-Branch ab.

Sessions in der Datenbank speichern

Wie Du vielleicht schon am Namen des Branches erraten hast, wollen wir die Speicherung der Sessions vom Dateisystem auf (unsere PostgreSQL) Datenbank umstellen.

Die notwendigen Schritte, um dies zu verwirklichen, sind typisch:

  1. Erstelle einen Git-Branch;
  2. Aktualisiere bei Bedarf die Symfony-Konfiguration;
  3. Schreibe und/oder aktualisiere bei Bedarf etwas Code;
  4. Aktualisiere die PHP-Konfiguration falls nötig (zum Beispiel um die PostgreSQL PHP-Erweiterung hinzuzufügen);
  5. Aktualisiere die Infrastruktur auf Docker und SymfonyCloud falls nötig (füge den PostgreSQL-Dienst hinzu);
  6. Teste lokal;
  7. Teste remote;
  8. Führe den Branch mit dem Master-Branch zusammen;
  9. Deploye in die Produktivumgebung;
  10. Lösche den Branch.

Um Sessions in der Datenbank zu speichern, ändere die session.handler_id-Konfiguration so, dass sie auf den Datenbank-DSN weist:

patch_file
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
--- a/config/packages/framework.yaml
+++ b/config/packages/framework.yaml
@@ -7,7 +7,7 @@ framework:
     # Enables session support. Note that the session will ONLY be started if you read or write from it.
     # Remove or comment this section to explicitly disable session support.
     session:
-        handler_id: null
+        handler_id: '%env(DATABASE_URL)%'
         cookie_secure: auto
         cookie_samesite: lax

Um Sessions in der Datenbank zu speichern, müüsen wir die sessions-Tabelle anlegen. Mach das mit Doctrine Migrations:

1
$ symfony console make:migration

Bearbeite die Datei um die Tabellenerstellung in der up()-Methode hinzuzufügen:

patch_file
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
--- a/migrations/Version00000000000000.php
+++ b/migrations/Version00000000000000.php
@@ -21,6 +21,14 @@ final class Version00000000000000 extends AbstractMigration
     {
         // this up() migration is auto-generated, please modify it to your needs

+        $this->addSql('
+            CREATE TABLE sessions (
+                sess_id VARCHAR(128) NOT NULL PRIMARY KEY,
+                sess_data BYTEA NOT NULL,
+                sess_lifetime INTEGER NOT NULL,
+                sess_time INTEGER NOT NULL
+            )
+        ');
     }

     public function down(Schema $schema): void

Führe die Datenbankmigration aus:

1
$ symfony console doctrine:migrations:migrate

Teste lokal, indem Du Dir die Website anschaust. Da es keine visuellen Veränderungen gibt und wir noch keine Sessions verwenden, sollte alles wie bisher funktionieren.

Bemerkung

Wir brauchen Schritt 3 bis 5 hier nicht, weil wir die Datenbank erneut für die Session-Speicherung gebrauchen, aber das Kapitel wie man Redis gebraucht zeigt uns unkompliziert wie man einen neuen Dienst für Docker und SymfonyCloud hinzufügt, testet und bereitstellt.

Da die neue Tabelle nicht durch Doctrine „verwaltet“ wird, müssen wir Doctrine so konfigurieren, dass die Tabelle nicht bei der nächsten Datenbankmigration entfernt wird:

patch_file
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
--- a/config/packages/doctrine.yaml
+++ b/config/packages/doctrine.yaml
@@ -5,6 +5,8 @@ doctrine:
         # IMPORTANT: You MUST configure your server version,
         # either here or in the DATABASE_URL env var (see .env file)
         #server_version: '13'
+
+        schema_filter: ~^(?!session)~
     orm:
         auto_generate_proxy_classes: true
         naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware

Commit Deine Änderungen zu dem neuen Branch:

1
2
$ git add .
$ git commit -m'Configure database sessions'

Einen Branch deployen

Bevor wir zum Produktivsystem deployen, sollten wir den Branch auf der gleichen Infrastruktur wie die Production-Environment testen. Wir sollten auch sicherstellen, dass für die Symfony prod-Environment alles gut funktioniert (die lokale Website hat die Symfony dev-Environment verwendet).

Lasst uns nun eine SymfonyCloud-Environment erstellen, die auf dem Git-Branch basiert:

1
$ symfony env:delete sessions-in-db --no-interaction
1
$ symfony env:create

Dieser Befehl erstellt eine neue Environment:

  • Der Branch erbt den Code und die Infrastruktur vom aktuellen Git-Branch (sessions-in-db);
  • Die Daten stammen von der Master-Environment (auch bekannt als Production oder Produktivumgebung), und zwar durch eine Momentaufnahme aller Servicedaten, einschließlich Dateien (z. B. von Benutzer*innen hochgeladene Dateien) und Datenbanken;
  • Ein neuer dedizierter Cluster wird erstellt, um den Code, die Daten und die Infrastruktur zu deployen.

Da das Deployment den gleichen Schritten folgt wie das Deployment in die Produktivumgebung, werden auch Datenbankmigrationen durchgeführt. Dies ist gleichzeitig eine gute Möglichkeit um sicherzugehen, dass die Migrationen mit echten Daten funktionieren.

Die Nicht-master-Environments sind der``master``-Environment sehr ähnlich, bis auf einige kleine Unterschiede: So werden beispielsweise E-Mails standardmäßig nicht gesendet.

Wenn das Deployment abgeschlossen ist, öffne den neuen Branch in einem Browser:

1
$ symfony open:remote

Beachte, dass alle SymfonyCloud-Befehle mit dem aktuellen Git-Branch arbeiten. Somit wird der Befehl die URL für den sessions-in-db-Branch aufrufen. Die URL sieht dann so https://sessions-in-db-xxx.eu.s5y.io/ aus.

Teste die Website auf dieser neuen Environment. Du solltest jetzt alle Daten sehen, die Du in der Master-Environment angelegt hast.

Wenn Du weitere Konferenzen in die master-Environment hinzufügst, werden diese nicht in der sessions-in-db-Environment angezeigt und umgekehrt. Die Environments sind unabhängig und isoliert.

Wenn sich der Code auf Master weiterentwickelt, kannst Du diese Änderungen jederzeit mittels rebase in den aktuellen Branch integrieren und die aktualisierte Version deployen, wodurch die Konflikte sowohl für den Code als auch für die Infrastruktur gelöst werden.

Du kannst sogar die Daten von Master zurück in die sessions-in-db-Environment synchronisieren:

1
$ symfony env:sync

Fehler von Deployments in die Produktivumgebung vermeiden

Standardmäßig verwenden alle SymfonyCloud-Environments die Einstellungen der master/prod-Environment (auch bekannt als die prod-Symfony-Environment). Auf diese Weise kannst Du die Anwendung unter realen Bedingungen testen. Dies gibt Dir das Gefühl, direkt auf Produktivsystemen zu entwickeln und zu testen, aber ohne den damit verbundenen Risiken. Das erinnert mich an die guten alten Zeiten, als wir Deployments noch über FTP gemacht haben.

Wenn ein Problem auftritt, möchtest Du vielleicht auf die dev-Symfony-Environment wechseln:

1
$ symfony env:debug

Wenn Du fertig bist, gehe zurück zu den Produktiveinstellungen:

1
$ symfony env:debug --off

Warnung

Aktiviere niemals die dev-Environment oder den Symfony Profiler im master-Branch; dies würde Deine Anwendung wirklich langsam machen und viele ernsthafte Sicherheitsschwachstellen öffnen.

Produktivinstallationen vor dem Deployment testen

Der Zugriff auf die zukünftige Version der Website mit echten Daten eröffnet viele Möglichkeiten: vom visuellen Regressionstest bis zum Performance-Test. Blackfire ist das perfekte Werkzeug für diese Aufgabe.

Lies den Schritt über „Performance“, um mehr darüber zu erfahren, wie Du Blackfire verwenden kannst, um Deinen Code vor dem Deployment zu testen.

In die Produktivumgebung mergen

Wenn Du mit den Änderungen im Branch zufrieden bist, führe den Code und die Infrastruktur wieder in den Git Master-Branch zurück:

1
2
$ git checkout master
$ git merge sessions-in-db

Und deploye:

1
$ symfony deploy

Beim Deployment werden nur die Code- und Infrastrukturänderungen in die SymfonyCloud übertragen; die Daten werden in keiner Weise beeinträchtigt.

Aufräumen

Entferne zum Abschluss den Git-Branch und die SymfonyCloud-Environment:

1
2
$ git branch -d sessions-in-db
$ symfony env:delete --env=sessions-in-db --no-interaction

  • « Previous Schritt 10: Die Benutzeroberfläche erstellen
  • Next » Schritt 12: Mit Events arbeiten

This work, including the code samples, is licensed under a Creative Commons BY-NC-SA 4.0 license.