Stap 11: Branching van de code

5.0 version
Maintained

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.

Jouw infrastructuur beschrijven

Je besefte het misschien nog niet, maar jouw infrastructuur kunnen bewaren in bestanden naast jouw code, is zeer handig. Docker en SymfonyCloud gebruiken configuratiebestanden om de projectinfrastructuur te beschrijven. Wanneer een nieuwe feature een extra service nodig heeft, dan veranderen zowel de code en de infrastructuurbestanden, in dezelfde patch.

Branches maken

De workflow begint met het aanmaken van een Git branch:

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

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

Sessies opslaan in Redis

Zoals je misschien - op basis van de branchnaam - geraden hebt, willen we de session-storage overschakelen van het filesystem naar Redis.

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 (voeg de Redis PHP-extensie toe);
  5. Update de infrastructuur op Docker en SymfonyCloud (voeg de Redis-service toe);
  6. Lokaal testen;
  7. Remote testen;
  8. Merge de branch met de master branch;
  9. Deployen naar productie;
  10. Verwijder de branch.

Alle wijzigingen die nodig zijn voor stap 2 tot 5 kunnen in één patch gedaan worden:

patch_file
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
--- a/.symfony.cloud.yaml
+++ b/.symfony.cloud.yaml
@@ -15,8 +15,13 @@ runtime:
 build:
     flavor: none

+variables:
+    php-ext:
+        redis: 5.3.1
+
 relationships:
     database: "db:postgresql"
+    redis: "rediscache:redis"

 web:
     locations:
--- a/.symfony/services.yaml
+++ b/.symfony/services.yaml
@@ -2,3 +2,6 @@ db:
     type: postgresql:11
     disk: 1024
     size: S
+
+rediscache:
+    type: redis:5.0
--- 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(REDIS_URL)%'
         cookie_secure: auto
         cookie_samesite: lax

--- a/docker-compose.yaml
+++ b/docker-compose.yaml
@@ -8,3 +8,7 @@ services:
             POSTGRES_PASSWORD: main
             POSTGRES_DB: main
         ports: [5432]
+
+    redis:
+        image: redis:5-alpine
+        ports: [6379]

Is dit niet prachtig?

“Herstart” Docker om de Redis-service te starten:

1
2
$ docker-compose stop
$ docker-compose up -d

Ik laat je lokaal testen 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.

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).

Zorg er eerst voor dat je jouw wijzigingen commit in de nieuwe branch:

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

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

1
$ symfony env:delete sessions-in-redis --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-redis);
  • 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 deployede URL voor de sessions-in-redis branch; de URL ziet er dan als volgt uit https://sessions-in-redis-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-redis 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-redis 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

Waarschuwing

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-redis

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-redis
$ symfony env:delete --env=sessions-in-redis --no-interaction

  • « Previous Stap 10: De gebruikersinterface bouwen
  • Next » Stap 12: Luisteren naar events

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