
Smoke-тесты сайта после deploy: практический набор
Создаём быстрые HTTP-проверки после публикации: статус, редиректы, ключевые страницы, ресурсы, заголовки и маркер версии с автоматическим отказом.
Содержание
Smoke-тестом называют короткую проверку основных функций сразу после публикации. Она отвечает на простой вопрос: новый релиз вообще открывается и отдаёт ожидаемые страницы? Такой тест не заменяет полный набор проверок, но быстро обнаруживает пропущенный файл, ответ 502, неверный каталог Nginx и публикацию не того коммита.
Какие проверки нужны после публикации
Составьте список из 5–10 критичных HTTP-проверок. Используйте curl --fail --silent --show-error --location, ограничьте время, проверьте ожидаемый код, содержимое и безопасный version marker. Запускайте тест сначала на новом каталоге или локальном адресе, затем после переключения — по публичному HTTPS. Любой обязательный сбой должен остановить публикацию или привести к понятному rollback.
Выберите маленький, но полезный набор
Для статической базы знаний подойдут:
- главная страница;
- архив статей;
- одна конкретная статья;
- страница поиска или JSON-индекс;
robots.txtи sitemap;- CSS или изображение из текущего релиза;
- 404 для несуществующего URL;
- HTTP→HTTPS редирект;
- маркер ожидаемой версии.
Для приложения добавьте health endpoint и один read-only пользовательский сценарий. Не создавайте в smoke-тесте реальные заказы, письма и данные без контролируемой очистки.
Проверки должны быть идемпотентными: повторный запуск не меняет состояние и не требует ручной уборки. Не включайте тяжёлое сканирование всех страниц в критический путь deploy. Полный link checker и производительные тесты можно выполнять отдельно, а smoke оставлять быстрым, чтобы команда не привыкла обходить его из-за долгого ожидания.
Почему одного кода 200 мало
Прокси может вернуть красивую страницу ошибки с кодом 200. Главная может быть старой из кеша. Неверная маршрутизация иногда отдаёт один и тот же HTML для любого пути. Поэтому проверяйте три уровня:
- HTTP-код и редирект.
- Ожидаемый тип или фрагмент содержимого.
- Версию релиза или другой уникальный признак.
Маркер не должен содержать секреты, внутренний путь и полный состав окружения. Достаточно короткого commit hash или release ID.
Напишите короткий сценарий на curl
Сохраните следующий код в файле scripts/smoke.sh и передайте адрес сайта первым аргументом. Сценарий проверит главную страницу и наличие строки Sitemap: в robots.txt; при первой ошибке он завершится с ненулевым кодом:
#!/usr/bin/env bash
set -euo pipefail
BASE_URL="${1:?Передайте адрес сайта}"
curl --fail --silent --show-error --location \
--connect-timeout 5 --max-time 15 \
--output /dev/null "$BASE_URL/"
curl --fail --silent --show-error --location \
--connect-timeout 5 --max-time 15 \
"$BASE_URL/robots.txt" | grep -q 'Sitemap:'
--fail делает 4xx/5xx ошибкой команды, --show-error сохраняет сообщение, --location следует ожидаемым редиректам. Таймаут не позволяет deploy зависнуть навсегда. Не используйте -k: отключение проверки сертификата скрывает важную production-ошибку.
Если pipeline анализирует вывод, избегайте печати полного ответа страницы с персональными данными.
Проверяйте точный код там, где это важно
Для 404 получите только код ответа несуществующей страницы и сравните его с ожидаемым значением. Эти строки добавляются после объявления BASE_URL в том же сценарии:
status="$(curl --silent --show-error --output /dev/null \
--write-out '%{http_code}' "$BASE_URL/definitely-missing-page/")"
test "$status" = "404"
Для редиректа HTTP→HTTPS не включайте --location, иначе увидите конечный 200 вместо первого ответа:
status="$(curl --silent --show-error --output /dev/null \
--write-out '%{http_code}' "http://example.org/")"
test "$status" = "301" -o "$status" = "308"
Домены и ожидаемый код задайте под свою конфигурацию. Временный 302 может быть правильным для отдельного сценария, но не должен приниматься автоматически для постоянного канонического редиректа.
Проверяйте содержимое без хрупких совпадений
Лучше добавить стабильный идентификатор релиза в готовый HTML или отдельный общедоступный файл. Следующий фрагмент ожидает переменную EXPECTED_RELEASE и требует полного совпадения одной строки:
EXPECTED_RELEASE="${EXPECTED_RELEASE:?Нет release ID}"
curl --fail --silent --show-error "$BASE_URL/version.txt" \
| grep -Fxq "$EXPECTED_RELEASE"
Не проверяйте длинный маркетинговый заголовок: редактор изменит текст и сломает deploy при исправном сайте. Стабильным может быть ID шаблона, JSON-поле или точный version marker.
Для статического ресурса получите URL из текущего HTML либо проверяйте файл с постоянным назначением, например favicon. Если asset имеет хеш в имени, старый жёстко записанный URL перестанет существовать в нормальном новом релизе.
Проверьте релиз до и после переключения
При атомарной публикации сначала проверяйте новый каталог до смены ссылки current, по которой Nginx находит активный релиз. Его можно временно обслужить на локальном адресе, отдельном порту или тестовом виртуальном хосте. Затем переключите ссылку и повторите небольшой набор по публичному домену.
Pre-switch ловит неполный артефакт без влияния на посетителей. Public smoke включает Nginx, TLS, DNS/CDN и фактическую текущую ссылку. Оба уровня нужны: один не заменяет другой.
Добавьте проверку заголовков
headers="$(curl --fail --silent --show-error --head "$BASE_URL/")"
printf '%s\n' "$headers" | grep -qi '^content-type: text/html'
printf '%s\n' "$headers" | grep -qi '^cache-control:'
Для security headers проверяйте только те значения, которые проект действительно принял. Бездумный список заголовков может сломать внешние ресурсы или создать ложное ощущение защиты.
Для кеширования отдельно проверьте HTML и хешированный asset: у них должны быть разные сроки жизни.
Сохраняйте диагностичный результат
Каждая ошибка должна отвечать на вопрос «что именно не прошло». Оборачивайте проверки в функции с понятными именами, печатайте URL, ожидаемый результат и полученный код, но не тело защищённого ответа. Сценарий возвращает ненулевой exit code при обязательном сбое.
Храните лог вместе с release ID и временем UTC. Это связывает ошибку с конкретной публикацией и помогает отличить проблему deploy от последующего инцидента.
Определите действие при ошибке
Безопасная логика:
- Создать новый релиз.
- Выполнить pre-switch smoke.
- Переключить
current. - Выполнить public smoke.
- При сбое вернуть предыдущую ссылку.
- Снова проверить публичный сайт.
- Сохранить неудачный релиз и журнал для разбора.
Автоматический rollback опасен при несовместимой миграции базы. Если данные менялись, deploy должен заранее определить совместимость, а не пытаться вернуть код вслепую.
Избегайте ложноположительных тестов
- Не принимайте любой 2xx вместо ожидаемого кода.
- Не отключайте TLS verification.
- Не проверяйте только localhost после переключения.
- Не используйте DNS-кеш без понимания.
- Не следуйте редиректу, когда тестируете сам редирект.
- Не ищите текст, который присутствует и на странице ошибки.
- Не позволяйте необязательному внешнему виджету останавливать основной релиз.
Один и тот же набор проверок должен запускаться после локальной сборки и ручной публикации. Когда сценарий стабилен, его включают в атомарный deploy, а непрерывную доступность контролирует мониторинг.
Источники
Самопроверка
Проверьте, что материал усвоен
Ответьте на все вопросы. Результат сохранится только в этом браузере и будет учтён в статистике прочитанных материалов.
Разбираем коротко
Частые вопросы
Чем smoke-тест отличается от мониторинга доступности?
Smoke-тест запускается для конкретного релиза и быстро проверяет его критичные функции. Мониторинг повторяется постоянно и сообщает о проблемах, которые возникают уже во время эксплуатации.
Достаточно ли проверять HTTP-код главной страницы?
Нет. Старый релиз и страница ошибки proxy тоже могут вернуть 200. Проверяйте несколько маршрутов, ожидаемый контент или version marker, ресурсы, редиректы и важные заголовки.
Должен ли неуспешный smoke-тест запускать rollback автоматически?
Только если проверка надёжна и откат безопасен для данных. Для начала лучше остановить переключение либо явно пометить релиз как неуспешный, сохранив журналы для диагностики.


