Etap 11: Zarządzanie gałęziami kodu

5.0 version
Maintained

Zarządzanie gałęziami kodu

Istnieje wiele sposobów zarządzania zmianami kodu w projekcie. Tym niemniej, praca bezpośrednio na gałęzi głównej (ang. master) oraz bezpośrednie wdrożenia na środowisko produkcyjne z pominięciem testów prawdopodobnie nie są najlepszym pomysłem.

W testowaniu nie chodzi tylko o testy jednostkowe czy funkcjonalne, ale również o sprawdzanie zachowania aplikacji z danymi produkcyjnymi. Jeśli Ty lub Twoi interesariusze mogą przeglądać aplikację dokładnie tak, jak zostanie ona wdrożona dla użytkowników końcowych, staje się to ogromną zaletą i pozwala na bezpieczne wdrażanie. Jest to szczególnie ważne, jeśli ludzie nietechniczni mogą zatwierdzać nowe funkcje.

Dla uproszczenia i uniknięcia powtarzania się, w kolejnych krokach będziemy kontynuować całą pracę na gałęzi głównej (ang. master) w repozytorium Git, ale zobaczmy, jak to może działać lepiej.

Organizacja pracy z użyciem systemu Git

Jednym z możliwych sposobów pracy jest utworzenie jednej gałęzi dla każdej nowej funkcji lub poprawki błędu. Jest to proste i skuteczne.

Opisywanie infrastruktury

Być może jeszcze nie zdajesz sobie z tego sprawy, ale posiadanie infrastruktury przechowywanej w plikach obok kodu bardzo pomaga. Docker i SymfonyCloud używają plików konfiguracyjnych do opisania infrastruktury projektu. Gdy nowa funkcja wymaga dodatkowej usługi, kod się zmienia, a zmiany infrastruktury są częścią tej samej łatki (ang. patch).

Tworzenie gałęzi

Praca rozpoczyna się wraz z utworzeniem gałęzi Git:

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

To polecenie tworzy gałąź sessions-in-redis z gałęzi master. To działanie „rozwidla” kod i konfiguację infrastruktury.

Przechowywanie sesji w Redis

Jak można się domyślić po nazwie gałęzi, chcemy przełączyć przechowywanie sesji z systemu plików na magazyn Redis.

Kroki niezbędne do urzeczywistnienia tej koncepcji są typowe:

  1. Stwórz gałąź Git;
  2. W razie potrzeby zaktualizuj konfigurację Symfony;
  3. Napisz i/lub zaktualizuj kod, jeśli zajdzie taka potrzeba;
  4. Zaktualizuj konfigurację PHP (dodaj rozszerzenie Redis w PHP);
  5. Zaktualizuj infrastrukturę w Dockerze i SymfonyCloud (dodaj usługę Redis);
  6. Przetestuj lokalnie;
  7. Przetestuj zdalnie;
  8. Połącz (ang. merge) bieżącą gałąź z gałęzią główną (ang. master);
  9. Wdróż (ang. deploy) na produkcję;
  10. Usuń gałąź.

Wszystkie zmiany potrzebne dla kroków od 2 do 5 mogą być wykonane w jednej łatce (ang. patch):

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]

Czyż nie jest to piękne ?

„Zrestartuj” Dockera w celu uruchomienia usługi Redis:

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

Pozwolę Ci to przetestować lokalnie, poprzez przeglądanie strony internetowej. Ponieważ nie ma żadnych zmian wizualnych i nie korzystamy jeszcze z sesji, wszystko powinno działać tak jak wcześniej.

Wdrażanie gałęzi

Przed wdrożeniem (ang. deploy) na produkcję powinniśmy przetestować gałąź na tej samej infrastrukturze, co infrastruktura produkcyjna. Powinniśmy również sprawdzić, czy wszystko działa dobrze dla środowiska prod Symfony (lokalna strona internetowa korzystała ze środowiska dev Symfony).

Po pierwsze, upewnij się, że dokonasz zmian na nowej gałęzi:

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

Teraz stwórzmy środowisko SymfonyCloud oparte na gałęzi Git :

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

Polecenie to tworzy nowe środowisko w następujący sposób:

  • Gałąź dziedziczy kod i infrastrukturę po obecnej gałęzi Git (sessions-in-redis);
  • Dane pochodzą ze środowiska głównego (zwanego też produkcyjnym) poprzez wykonanie spójnego obrazu danych z wszystkich usług, w tym plików (np. plików przesłanych przez użytkownika) i baz danych;
  • Tworzony jest nowy dedykowany klaster do wdrożenia kodu, danych i infrastruktury.

Ponieważ wdrożenie odbywa się zgodnie z tymi samymi krokami co wdrożenie na produkcję, migracje do baz danych również będą wykonywane. Jest to świetny sposób na sprawdzenie, czy migracje działają z danymi produkcyjnymi.

Środowiska inne niż master są bardzo do niego podobne, z wyjątkiem kilku małych różnic: na przykład, wiadomości e-mail nie są domyślnie wysyłane.

Po zakończeniu wdrożenia otwórz nową gałąź w przeglądarce:

1
$ symfony open:remote

Zauważ, że wszystkie polecenia SymfonyCloud działają na bieżącej gałęzi Git. Spowoduje to otwarcie adresu URL dla gałęzi sessions-in-redis - adres URL będzie wyglądał tak: https://sessions-in-redis-xxx.eu.s5y.io/.

Przetestuj stronę internetową na tym nowym środowisku, powinny być widoczne wszystkie dane, które zostały stworzone w środowisku głównym (ang. master).

Jeśli dodasz więcej konferencji w środowisku produkcyjnym ( gałąź master), nie pojawią się one w środowisku sessions-in-redis i vice versa. Środowiska są niezależne i odizolowane.

Jeśli zmieni się kod w gałęzi głównej Git, zawsze można zrestartować gałąź i wdrożyć zaktualizowaną wersję, rozwiązując konflikty zarówno dla kodu, jak i infrastruktury.

Można nawet zsynchronizować dane z gałęzi głównej (ang. master) z powrotem do środowiska sessions-in-redis:

1
$ symfony env:sync

Debugowanie wdrożeń produkcyjnych przed właściwym wdrożeniem

Domyślnie wszystkie środowiska SymfonyCloud używają tych samych ustawień, co środowisko master / prod (znane również jako środowisko prod Symfony). Pozwala to na przetestowanie aplikacji w rzeczywistych warunkach. Daje to poczucie rozwoju i testowania bezpośrednio na serwerach produkcyjnych, ale bez związanego z tym ryzyka. Przypomina mi to dawne dobre czasy, kiedy wdrożenia robiliśmy przez FTP.

W przypadku wystąpienia problemu, możesz chcieć przełączyć się na środowisko dev Symfony:

1
$ symfony env:debug

Po zakończeniu należy powrócić do ustawień produkcyjnych:

1
$ symfony env:debug --off

Ostrzeżenie

Nigdy nie ustawiaj środowiska dev i nigdy nie włączaj Symfony Profiler na gałęzi master; spowoduje to, że Twoja aplikacja będzie naprawdę powolna i otworzy wiele poważnych luk w zabezpieczeniach.

Testowanie wdrażania produkcji przed właściwym wdrożeniem

Dostęp do nowej wersji strony internetowej z danymi produkcyjnymi otwiera wiele możliwości: od testów regresji wizualnej po testy wydajnościowe. Blackfire jest idealnym narzędziem do tego zadania.

Przejdź do etapu poświęconego wydajności, aby dowiedzieć się więcej o tym, jak można użyć Blackfire do przetestowania kodu przed wdrożeniem.

Scalanie z produkcją

Gdy jesteś zadowolony ze zmian w gałęzi, scal kod i infrastrukturę z powrotem do gałęzi głównej (ang. master) Git:

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

I wdróż:

1
$ symfony deploy

Podczas wdrażania, tylko kod i zmiany w infrastrukturze są przekazywane do SymfonyCloud; dane nie są w żaden sposób naruszone.

Sprzątanie

W końcu posprzątaj, usuwając gałąź Git i środowisko SymfonyCloud:

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

  • « Previous Etap 10: Tworzenie interfejsu użytkownika
  • Next » Etap 12: Nasłuchiwanie zdarzeń

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