Skip to content

Работа с ветками

Существует множество способов организации работы с кодом в проекте. Однако фиксировать изменения непосредственно в master-ветке Git и напрямую развёртывать код в продакшен без тестирования, пожалуй, не лучший вариант.

Тестирование — это не только модульные или функциональные тесты, но и проверка поведения приложения с использованием реальных данных. Если вы или ваши заинтересованные стороны можете просмотреть приложение в том самом виде, в котором оно предстанет перед конечными пользователями, это становится огромным преимуществом и позволяет вам развёртывать приложения с уверенностью. Особенно полезно, когда нетехнические специалисты могут проверять новую функциональность.

Для упрощения и чтобы избежать повторения на следующих шагах мы продолжим работу в master-ветке Git, однако давайте посмотрим, как это можно организовать получше.

Организация рабочего процесса с помощью Git

Создание отдельной ветки на каждую новую функциональность или исправление бага — один из простых и эффективных вариантов организации рабочего процесса.

Создание веток

Рабочий процесс начинается с создания ветки в Git:

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

Команда из примера создаёт ветку sessions-in-db из ветки master. Это действие создаёт ответвление кода и конфигурации инфраструктуры.

Хранение сессий в базе данных

Вероятно, вы уже поняли из названия ветки, что для хранения сессий вместо файловой системы мы будем использовать хранилище базы данных (PostgreSQL в нашем случае).

Необходимые шаги для реализации этого вполне типичны:

  1. Создайте новую ветку в Git;
  2. Обновите конфигурацию Symfony, если потребуется;
  3. При необходимости напишите и/или обновите код;
  4. Update the PHP configuration if needed (like adding the PostgreSQL PHP extension);
  5. При необходимости обновите инфраструктуру Docker и Platform.sh (добавив сервис PostgreSQL);
  6. Протестируйте локально;
  7. Протестируйте удалённо;
  8. Выполните слияние ветки с основной веткой;
  9. Разверните в продакшене;
  10. Удалите ветку.

Чтобы хранить сессии в базе данных, измените конфигурационную опцию session.handler_id на DSN базы данных:

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

Для хранения сессий в базе данных нам нужно создать таблицу sessions. Создадим её с помощью миграции Doctrine:

1
$ symfony console make:migration

Отредактируйте файл, чтобы добавить создание таблицы в методе up():

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

Примените миграцию к базе данных:

1
$ symfony console doctrine:migrations:migrate

Протестируйте сайт на своём компьютере, просматривая различные страницы. Поскольку мы не вносили никаких визуальных изменений и пока не используем сессии, всё должно работать как и раньше.

Note

Пропустите шаги 3–5, поскольку мы повторно используем базу данных в качестве хранилища сессий. В главе про Redis наглядно показано, насколько просто добавить, протестировать и развернуть новый сервис как в Docker, так и в Platform.sh.

Поскольку новая таблица не "управляется" Doctrine, нам следует настроить Doctrine так, чтобы таблица не удалялась при следующей миграции базы данных:

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

Зафиксируйте изменения в новой ветке:

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

Развёртывание ветки

Перед развёртыванием в продакшене, мы должны протестировать ветку в окружении ему идентичному. Нам необходимо убедиться, что всё работает корректно в Symfony-окружении prod (локальный сайт использует окружение dev).

Теперь давайте создадим Platform.sh-окружение на основе Git-ветки:

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

Данная команда создаёт новое окружение в следующем порядке:

  • Ветка наследует код и инфраструктуру от текущей Git ветки (sessions-in-db);
  • Данные поступают из основного окружения (т.е. продакшена) путём создания последовательных слепков всех служебных данных, включая файлы (например, загруженные пользователями) и базы данных;
  • Создаётся новый выделенный кластер для развёртывания кода, данных и инфраструктуры.

Поскольку развёртывание проходит те же этапы, что и развёртывание в продакшене, миграции базы данных также будут выполнены. Это отличный способ проверить, что миграции работают с данными в продакшене.

Окружения, отличные от master, на самом деле очень на него похожи, но есть небольшие отличия. Например, отправка электронных писем отключена по умолчанию.

После завершения развёртывания откройте новую ветку в браузере:

1
$ symfony cloud:url -1

Обратите внимание, что все команды Platform.sh выполняются в пределах текущей Git-ветки. Выполненная выше команда откроет URL-адрес для только что развёрнутой ветки sessions-in-db. Адрес будет выглядеть примерно так: https://sessions-in-db-xxx.eu-5.platformsh.site/.

Протестируйте сайт в новом окружении: вы увидите те же данные, что и в основном окружении.

Если добавить новые конференции в основное окружение (master), они не появятся в окружении sessions-in-db и наоборот, так как окружения являются независимыми и полностью изолированными друг от друга.

Если код изменится в основной ветке, вы всегда можете выполнить перебазирование Git-ветки и развернуть обновлённую версию, разрешив конфликты в коде и инфраструктуре.

В том числе вы можете синхронизировать данные с основного окружения в окружение sessions-in-db:

1
$ symfony cloud:env:sync

Предварительная отладка развёртывания в продакшене

По умолчанию все Platform.sh-окружения используют те же настройки, что и окружение master/prod (то же, что и окружение prod в Symfony). Это позволяет протестировать приложение в реальных условиях (как и в продакшене). Таким образом создаётся ощущение разработки и тестирования непосредственно на продакшен-серверах, но без связанных с этим рисков. Мне напоминает это старые добрые времена, когда мы развёртывали проекты через FTP.

При возникновении проблемы вы можете переключиться на Symfony-окружение dev:

1
$ symfony cloud:env:debug

Как только закончите, переключитесь обратно к продакшен-настройкам:

1
$ symfony cloud:env:debug --off

Warning

Никогда не активируйте окружение dev и никогда не используйте профилировщик Symfony, находясь в ветке master, это приведёт к тому, что ваше приложение станет очень медленным и откроет множество серьёзных дыр безопасности.

Предварительное тестирование развёртывания в продакшене

Возможность предварительного просмотра будущей версии сайта с продакшен-данными открывает широкие возможности: от визуального регрессионного тестирования до тестирования производительности. Blackfire — идеальный инструмент для такого рода задач.

Перейдите к шагу Производительность, чтобы узнать больше про использование Blackfire для тестирования кода перед развёртыванием.

Развёртывание в продакшене

Если вы полностью удовлетворены изменениями в ветке с новой функциональностью, выполните слияние кода и инфраструктуры в master-ветку в Git:

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

И разверните:

1
$ symfony cloud:deploy

При развёртывании в Platform.sh отправляются только изменения в коде и инфраструктуре; данные останутся такими же, как и были до развёртывания.

Очистка

В завершение выполните очистку, удалив Git-ветку и 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