Branching van de code

Version: current
  • Maintained versions
  • Unmaintained versions

Branching van de code

Er zijn vele manieren om de workflow van codewijzigingen in een project te organiseren. Maar direct werken in de Git master-branch en direct in productie nemen zonder testen is waarschijnlijk niet de beste.

Testen gaat niet alleen over unit- of functionele testen, het gaat ook over het controleren hoe de applicatie zich gedraagt met productiegegevens. Als jij of jouw stakeholders de applicatie kunnen testen in dezelfde staat als aan de eindgebruikers opgeleverd zal worden, dan is dat een groot voordeel. Het maakt dat je met vertrouwen kan deployen. Het voordeel komt in het bijzonder tot zijn recht wanneer niet-technische mensen nieuwe features kunnen gaan valideren.

Om het eenvoudig te houden zullen we in de volgende stappen al ons werk in de Git master branch blijven doen. Maar laten we eens kijken hoe het eventueel ook beter kan.

Het eigen maken van een Git Workflow

Een mogelijke workflow is het creëren van een branch per nieuwe functie of bugfix. Dit is eenvoudig en efficiënt.

Branches maken

De workflow begint met het aanmaken van een Git branch:

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

Dit commando maakt een sessions-in-db branch aan vanuit de master branch. Het maakt een afsplitsing van de code en de infrastructuurconfiguratie.

Sessies opslaan in de database

Zoals je misschien - op basis van de branchnaam - geraden hebt, willen we de session-storage overschakelen van het filesystem naar een database (in dit geval onze PostgreSQL database).

De stappen die nodig zijn om het te realiseren zijn logisch:

  1. Maak een Git branch aan;
  2. Werk de Symfony-configuratie bij indien nodig;
  3. Schrijf en/of update wat code indien nodig;
  4. Werk de PHP-configuratie bij indien nodig (voeg bijvoorbeeld de PostgreSQL PHP-extensie toe);
  5. Update de infrastructuur op Docker en SymfonyCloud indien nodig (voeg bijvoorbeeld de PostgreSQL-service toe);
  6. Lokaal testen;
  7. Remote testen;
  8. Merge de branch met de master branch;
  9. Deployen naar productie;
  10. Verwijder de branch.

Verander de session.handler_id configuratie en verwijs naar de database DSN om sessies in de database op te slaan:

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

We moeten een sessions tabel toevoegen om de gegevens in de database op te slaan. Dit doen we middels een Doctrine migratie:

1
$ symfony console make:migration

Wijzig het bestand en voeg de code toe om de database tabel te creëren in de up() methode:

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

Migreer de database:

1
$ symfony console doctrine:migrations:migrate

Test lokaal door naar de website te surfen. Omdat er geen visuele veranderingen zijn en omdat we nog geen sessies gebruiken, zou alles nog steeds moeten werken zoals voorheen.

Note

We hebben stappen 3 t/m 5 hier niet nodig omdat we de database hergebruiken als session-storage. Het hoofdstuk over Redis laat zien hoe eenvoudig het is om nieuwe services toe te voegen, te testen en te deployen in zowel Docker als SymfonyCloud.

Omdat de nieuwe tabel niet "gemanaged" is door Docker, zullen we in de Docker migratie aan moeten geven dat deze niet verwijderd moet worden in de volgende database migratie:

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 je wijzigingen in de nieuwe branch:

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

Deployen van een branch

Voordat we de branch in productie nemen, moeten we deze testen op dezelfde infrastructuur als in productie. We moeten ook valideren dat alles goed werkt voor de prod Symfony-omgeving (de lokale website gebruikt de dev Symfony-omgeving).

Laten we nu een SymfonyCloud-omgeving maken op basis van de Git branch:

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

Dit commando creëert vervolgens een nieuwe omgeving:

  • De branch erft de code en infrastructuur van de huidige Git branch (sessions-in-db);
  • De gegevens komen uit de master- (aka-productie) omgeving door het maken van een consistente snapshot van alle service-gegevens, inclusief bestanden (bijvoorbeeld door de gebruiker geüploade bestanden) en databases;
  • Er wordt een nieuw dedicated cluster gecreëerd om de code, de gegevens en de infrastructuur te deployen.

Aangezien de deployment dezelfde stappen volgt als de deployment naar productie, zullen ook databasemigraties worden uitgevoerd. Dit is een goede manier om te valideren dat de migraties werken met de productiedataset.

De niet-master omgevingen lijken erg op de master omgeving, op enkele kleine verschillen na: e-mails worden bijvoorbeeld standaard niet verstuurd.

Zodra de deployment is voltooid, open je de nieuwe branch in een browser:

1
$ symfony open:remote

Merk op dat alle SymfonyCloud commando's werken op de huidige Git branch. Dit commando opent de gedeployede URL voor de sessions-in-db branch; de URL ziet er dan als volgt uit https://sessions-in-db-xxx.eu.s5y.io/.

Test de website op deze nieuwe omgeving, je zou alle gegevens moeten zien die je in de master-omgeving hebt aangemaakt.

Als je meer conferenties aan de master omgeving toevoegt, dan zullen ze niet in de sessions-in-db omgeving verschijnen en vice versa. De omgevingen zijn onafhankelijk en geïsoleerd.

Als de code op master evolueert, kun je altijd de Git branch rebasen en de bijgewerkte versie deployen, waardoor de conflicten voor zowel de code als de infrastructuur worden opgelost.

Je kan zelfs de gegevens van de master terug naar de sessions-in-db omgeving synchroniseren:

1
$ symfony env:sync

Het debuggen van productie-deployment vóór de ingebruikname

Standaard gebruiken alle SymfonyCloud-omgevingen dezelfde instellingen als de master / prod omgeving (ook wel de Symfony prod omgeving genoemd). Dit stelt je in staat om de toepassing in reële omstandigheden te testen. Het geeft je het gevoel dat je direct op productieservers ontwikkelt en test, maar zonder de risico's die daarmee gepaard gaan. Dit doet me denken aan de goede oude tijd toen we deployments via FTP verzorgden.

In het geval van een probleem, kan je misschien overstappen naar de Symfony dev omgeving:

1
$ symfony env:debug

Als je klaar bent, ga dan terug naar de productie-instellingen:

1
$ symfony env:debug --off

Warning

Schakel nooit de dev omgeving of de Symfony Profiler in op de master branch; het maakt de applicatie traag en zorgt voor een hoop serieuze kwetsbaarheden.

Testen van de productie-deployments voor de ingebruikname

Toegang hebben tot de nieuwe versie van de website met productiegegevens biedt veel mogelijkheden: van visuele regressietests tot performance tests. Blackfire is de perfecte tool voor de klus.

Raadpleeg de stap over "Prestaties" om meer te weten te komen over hoe je Blackfire kan gebruiken om jouw code te testen voordat je deze deployt.

Mergen naar productie

Als je tevreden bent met de wijzigingen in de branch, merge dan de code en de infrastructuur naar de Git master branch:

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

En deploy:

1
$ symfony deploy

Bij de deployment worden enkel de code en wijzigingen in de infrastructuur naar SymfonyCloud gepusht; de data wordt op geen enkele wijze beïnvloed.

Opruimen

Ruim tot slot op door de Git branch en de SymfonyCloud omgeving te verwijderen:

1
2
$ git branch -d sessions-in-db
$ symfony env:delete --env=sessions-in-db --no-interaction
This work, including the code samples, is licensed under a Creative Commons BY-NC-SA 4.0 license.