Работа с ветками
Существует множество способов организации работы с кодом в проекте. Однако фиксировать изменения непосредственно в master-ветке Git и напрямую развёртывать код в продакшен без тестирования, пожалуй, не лучший вариант.
Тестирование — это не только модульные или функциональные тесты, но и проверка поведения приложения с использованием реальных данных. Если вы или ваши заинтересованные стороны можете просмотреть приложение в том самом виде, в котором оно предстанет перед конечными пользователями, это становится огромным преимуществом и позволяет вам развёртывать приложения с уверенностью. Особенно полезно, когда нетехнические специалисты могут проверять новую функциональность.
Для упрощения и чтобы избежать повторения на следующих шагах мы продолжим работу в master-ветке Git, однако давайте посмотрим, как это можно организовать получше.
Организация рабочего процесса с помощью Git
Создание отдельной ветки на каждую новую функциональность или исправление бага — один из простых и эффективных вариантов организации рабочего процесса.
Создание веток
Рабочий процесс начинается с создания ветки в Git:
1
$ git checkout -b sessions-in-db
Команда из примера создаёт ветку sessions-in-db
из ветки master
. Это действие создаёт ответвление кода и конфигурации инфраструктуры.
Хранение сессий в базе данных
Вероятно, вы уже поняли из названия ветки, что для хранения сессий вместо файловой системы мы будем использовать хранилище базы данных (PostgreSQL в нашем случае).
Необходимые шаги для реализации этого вполне типичны:
- Создайте новую ветку в Git;
- Обновите конфигурацию Symfony, если потребуется;
- При необходимости напишите и/или обновите код;
- Update the PHP configuration if needed (like adding the PostgreSQL PHP extension);
- При необходимости обновите инфраструктуру Docker и Platform.sh (добавив сервис PostgreSQL);
- Протестируйте локально;
- Протестируйте удалённо;
- Выполните слияние ветки с основной веткой;
- Разверните в продакшене;
- Удалите ветку.
Чтобы хранить сессии в базе данных, измените конфигурационную опцию 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: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