Skip to content

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.

Tworzenie gałęzi

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

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

To polecenie stworzy gałąź sessions-in-db z gałęzi master. To działanie "rozwidla" kod i konfiguację infrastruktury.

Przechowywanie sesji w bazie danych

Jak można się domyślić po nazwie gałęzi, chcemy przełączyć przechowywanie sesji z systemu plików na bazę danych (stworzoną przez nas w PostgreSQL).

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. Update the PHP configuration if needed (like adding the PostgreSQL PHP extension);
  5. Zaktualizuj infrastrukturę w Dockerze i Platform.sh jeżeli jest potrzeba (dodaj usługę PostgreSQL);
  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łąź.

Żeby przechowywać sesje w bazie danych, zmień konfigurację session.handler_id tak, żeby wskazywała na DSN bazy:

1
2
3
4
5
6
7
8
9
10
11
--- 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
         storage_factory_id: session.storage.factory.native

Żeby przechowywać sesje w bazie danych, musimy utworzyć tabele sessions. Zrób to wykorzystując migracje Doctrine:

1
$ symfony console make:migration

Zmodyfikuj plik tak, aby w metodzie up() dodać tworzenie tabeli:

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

Wykonaj migrację bazy danych:

1
$ symfony console doctrine:migrations:migrate

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

Note

Nie potrzebujemy tutaj kroków od 3 do 5, ponieważ ponownie używamy bazy danych jako magazynu sesji, ale rozdział o korzystaniu z Redisa pokazuje, jak proste jest dodawanie, testowanie i wdrażanie nowej usługi zarówno w Dockerze, jak i Platform.sh.

Ponieważ nowa tabela nie jest „zarządzana” przez Doctrine, musimy skonfigurować Doctrine tak, aby nie usuwał jej podczas następnej migracji bazy danych:

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

Zatwierdź (ang. commit) swoje zmiany do nowej gałęzi (ang. branch):

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

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

Teraz stwórzmy środowisko Platform.sh oparte na gałęzi Git :

1
$ symfony cloud:env:delete sessions-in-db
1
$ symfony cloud:deploy

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

  • Gałąź dziedziczy kod i infrastrukturę po obecnej gałęzi Git (sessions-in-db);
  • 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 cloud:url -1

Zauważ, że wszystkie polecenia Platform.sh działają na bieżącej gałęzi Git. Spowoduje to otwarcie adresu URL dla gałęzi sessions-in-db - adres URL będzie wyglądał tak: https://sessions-in-db-xxx.eu-5.platformsh.site/.

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-db 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-db:

1
$ symfony cloud:env:sync

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

Domyślnie wszystkie środowiska Platform.sh 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 cloud:env:debug

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

1
$ symfony cloud:env:debug --off

Warning

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

I wdróż:

1
$ symfony cloud:deploy

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

Sprzątanie

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

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