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

Проверки перед выкладкой - синтаксис, стандарт, тесты, миграции

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

Механика

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

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

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

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

Сборка фронтенда - это тоже проверка, ничем не хуже прогона тестов. Бандл должен собираться из чистого клона репозитория; сборка, которая получается только на машине одного разработчика, однажды не соберётся вовсе.

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

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

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

Шаги

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

Код

Проверяем синтаксис изменённых файлов:

Окно терминала
git diff --name-only origin/main...HEAD -- '*.php' | xargs -r -n1 php -l
# проверка занимает секунды и ловит самую обидную ошибку - опечатку в скобках
# на каждой отправке изменений её гоняют целиком, без всяких условий

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

Держим в проверке только свой код:

Окно терминала
vendor/bin/phpcs --standard=PSR12 --extensions=php \
local/php_interface local/modules local/templates
# каталог платформы и чужие решения в проверку не берут никогда
# правила фиксируют файлом настроек в репозитории, а не ключами в команде

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

Поднимаем копию базы для тестов:

Окно терминала
mysql -e "DROP DATABASE IF EXISTS bitrix_ci; CREATE DATABASE bitrix_ci"
gunzip < backup/nightly.sql.gz | mysql bitrix_ci
# копия ночной резервной копии: свежая структура и обезличенные данные
mysql bitrix_ci -e "UPDATE b_user SET EMAIL = CONCAT('u', ID, '@example.org')"

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

Запускаем тесты своей логики:

Окно терминала
BITRIX_DB=bitrix_ci vendor/bin/phpunit --testsuite local
# набор тестов ограничен своим кодом: ядро платформы не тестируют
# подъём ядра занимает секунды на каждый запуск: тесты гоняют набором

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

Собираем фронтенд из чистого клона:

Окно терминала
npm ci # именно ci: ставит ровно то, что записано в блокировке
npx bitrix build
# сборка, которая получается только у одного разработчика, однажды не соберётся
test -s local/js/vendor/catalog/dist/catalog.bundle.js # результат обязан появиться

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

Прогоняем миграции на копии:

Окно терминала
php local/tools/migrate.php up
# журнал применённых миграций на копии свой: прогон идёт с нуля
# упавшая здесь миграция не доедет до боевого сайта
# после прогона копию базы удаляют: она нужна ровно на одну проверку

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

Собираем всё в один скрипт с кодом возврата:

#!/bin/sh
set -e # первая же неуспешная проверка останавливает остальные
sh ci/syntax.sh
sh ci/style.sh
sh ci/migrate.sh
sh ci/test.sh
echo "проверки пройдены"
# скрипт выкладки запускают только после нулевого кода возврата этого файла
# тот же файл запускают локально перед отправкой изменений в общую ветку

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

Ограничения

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

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

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

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

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

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

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

Проверка красная неделями, и все привыкли.

Результат проверки ничего не блокирует и не влияет на выкладку. Скрипт выкладки запускают только после успешного завершения проверок.

Проверка стандарта кода идёт часами.

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

После тестов на боевом сайте появились тестовые заказы.

Тесты запускались на боевой базе. Под них поднимают копию из ночной резервной копии и работают только с ней.

Бандл собирается у одного разработчика и больше нигде.

Сборка зависит от локального состояния каталога пакетов. Проверка собирает фронтенд из чистого клона с установкой по блокировке версий.

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

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

Проверка проходит, а сайт после выкладки не работает.

Проверки покрывают код, но не денежные сценарии целиком. Корзину, оформление и вход проходят руками перед крупными релизами.

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

С чего начать, если проверок нет вовсе?

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

Где взять базу для тестов?

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

Нужно ли проверять код платформы?

Нет: он не ваш, его правила оформления другие, и замечания по нему бесполезны. В проверку берут каталог проекта, а если платформу всё-таки правили, это отдельная находка для разбора.

Что делать, если проверка идёт слишком долго?

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

Заменяют ли тесты ручную проверку перед релизом?

Нет. Они закрывают повторяющиеся ошибки в своём коде, но проход по корзине, оформлению и оплате руками перед крупной выкладкой остаётся обязательным.

Смежное

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