Перейти к содержимому

Три контура проекта - разработка, тест, бой и порядок переноса

Разбираем схему из трёх контуров: что живёт на разработке, тесте и бою, куда движутся код и данные, в каком порядке идёт выкладка и как готовят откат.

Механика

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

Код движется в одну сторону: от разработки через тест к бою. Обратного движения кода не бывает: правка, сделанная сразу на боевом сайте, теряется при следующей выкладке и ломает доверие к процессу.

Данные движутся в обратную сторону: с боя на тест и разработку. Копию обезличивают и отрезают от внешнего мира, иначе стенд шлёт письма настоящим покупателям и трогает боевой обмен.

Структура базы едет вместе с кодом, а не переносится копированием. Изменения оформляют скриптами миграций, которые лежат в репозитории рядом с кодом и применяются на каждом контуре по очереди.

Миграция обязана быть повторяемой без вреда для данных проекта. Она смотрит текущее состояние, применяет изменение только при необходимости и запоминает, что уже выполнена: без этого повторный запуск ломает данные.

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

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

Откат готовят до выкладки, а не после падения боевого сайта. Резервная копия файлов и базы, снятая непосредственно перед работами, - это разница между десятью минутами и бессонной ночью.

Шаги

  1. Развести три контура и договориться, что живёт и меняется на каждом из них.
  2. Держать в репозитории код, миграции структуры и конфигурацию самого окружения.
  3. Переносить данные только с боя на тест, обязательно обезличивая копию.
  4. Выкладывать строго по порядку: тест целиком, проверка, затем боевой сайт.
  5. Снимать резервную копию перед каждой выкладкой и проверять её восстановление.

Код

Проверяем, на каком контуре выполняется код:

// /bitrix/.settings_extra.php каждого контура: свои значения поверх общих
return ['vendor_env' => ['value' => ['stage' => 'test'], 'readonly' => true]];
// на бою здесь prod, на стенде разработчика - dev, и код смотрит именно сюда

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

Пишем идемпотентную миграцию структуры:

$version = (int)\Bitrix\Main\Config\Option::get('vendor.shop', 'db_version', '0');
if ($version < 3) {
$connection = \Bitrix\Main\Application::getConnection();
if (!$connection->isTableExists('vendor_contract')) {
$connection->queryExecute('CREATE TABLE vendor_contract (ID int NOT NULL AUTO_INCREMENT PRIMARY KEY)');
}
\Bitrix\Main\Config\Option::set('vendor.shop', 'db_version', '3'); // отметка о применении
}

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

Применяем миграции при выкладке:

Окно терминала
php /home/site/www/local/tools/migrate.php # применение всех новых миграций
# запуск ставят в порядок выкладки сразу после переноса файлов
php /home/site/www/local/tools/migrate.php --dry-run # проверка без изменений
# на бою сначала прогоняют проверку, потом само применение

Ведём журнал применённых миграций:

$applied = \Bitrix\Main\Config\Option::get('vendor.shop', 'migrations', '');
foreach (glob(__DIR__ . '/migrations/*.php') as $file) {
$name = basename($file);
if (str_contains($applied, $name)) { continue; } // эта миграция уже прошла
require $file;
\Bitrix\Main\Config\Option::set('vendor.shop', 'migrations', $applied .= $name . ';');
}

Журнал применённых миграций избавляет от вопроса «а этот скрипт уже гоняли». Список хранят в настройках модуля, и он одинаково работает на всех трёх контурах без ручного учёта в голове.

Отрезаем стенд от внешнего мира:

if (\Bitrix\Main\Config\Configuration::getValue('vendor_env')['stage'] !== 'prod') {
\Bitrix\Main\EventManager::getInstance()->addEventHandler('main', 'OnBeforeMailSend',
static fn() => false); // письма со стенда наружу не уходят
}

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

Сверяем окружения контуров между собой:

Окно терминала
for host in test prod; do
ssh $host 'php -v | head -1; php -m | md5sum; mysql -e "SELECT VERSION()"'
done
# расхождение версий или набора расширений объясняет «на тесте работало»

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

Снимаем копию перед выкладкой:

Окно терминала
mysqldump --single-transaction site_db | gzip > /backup/pre-deploy-$(date +%F-%H%M).sql.gz
tar czf /backup/pre-deploy-files.tar.gz /home/site/www/local /home/site/www/bitrix/.settings.php
# копия снимается непосредственно перед работами, а не вчера ночью

Свежесть копии важнее её полноты. Ночная копия не спасёт от потери заказов за рабочий день, а копия, снятая за минуту до выкладки, возвращает сайт в предсказуемое состояние.

Ограничения

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

Обратного переноса данных с теста на бой не бывает без потерь. Заказы, созданные на тесте, на бой не переносят: их номера, оплаты и остатки не сойдутся с настоящими.

Миграции не покрывают контент проекта и его настройки. Тексты страниц, настройки инфоблоков и права обычно переносят руками или отдельными сценариями, и это самая частая причина расхождений между контурами.

Три контура требуют дисциплины от всей команды проекта, а не от одного человека. Один «быстрый фикс» прямо на боевом сайте рушит схему: следующая выкладка затирает его, а автор правки уже не помнит, что именно менял.

Схема из трёх контуров живёт на договорённостях, а не на технике. Инструкция по разворачиванию контура, порядок релиза и правила доступа стоят дороже любого скрипта: без них процесс держится на памяти одного человека.

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

Типичные проблемы

Правка исчезла после очередной выкладки.

Её сделали прямо на боевом сайте мимо общего репозитория. Код меняют только на разработке, а на бой он приезжает выкладкой.

На тесте всё работало, на бою сломалось.

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

Миграция сломала данные при повторном запуске.

В ней нет проверки текущего состояния и отметки о применении. Миграцию пишут повторяемой и запоминают её версию в настройках.

Со стенда ушли письма настоящим покупателям.

Копия боевой базы не обезличена, а отправка писем не отключена. Внешние связи отрезают сразу после подъёма копии на стенде.

Откат занял несколько часов.

Резервная копия оказалась старой или её никто не проверял. Копию снимают прямо перед работами и регулярно проверяют её восстановлением.

Частые вопросы

Обязательно ли держать три контура?

Для небольшого сайта хватает разработки и боя. Как только релиз стоит денег или простоя, отдельный тестовый контур окупается первой же ошибкой.

Как переносить настройки инфоблоков между контурами?

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

Что делать со срочной правкой на бою?

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

Нужно ли обновлять платформу на тесте раньше боя?

Да, и это главный смысл тестового контура. Обновление сначала проходит там вместе с проверкой ключевых сценариев магазина.

Как проверить, что копия восстановится?

Развернуть её на стенде и открыть основные страницы сайта. Непроверенная копия - это надежда, а не резервная копия.

Смежное

Первоисточник