Как стать автором
Обновить

Тестовый контур как спасение при частых релизах

Время на прочтение6 мин
Количество просмотров7K

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

Немного о проекте

Сейчас проект представляет собой два приложения. Фактически, одно приложение  — это копия второго, но с незначительными различиями. Каждое приложение поделено на сервисы. Условно назовем их Frontend, Backend и X-API.

Что представляют из себя эти сервисы?

  • Frontend
    Уже наверное все привыкли, что frontend — это приложение на angular/react/vue или чем-нибудь подобном. В нашем случае это стандартное приложение на PHP + JQuery, в котором работают пользователи.

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

  • X-API
    Выделенная из монолитного backend часть бизнес-логики со своей базой данных.

Какие еще характеристики проекта следует выделить?

  • Устаревший стек: PHP 7.1, Zend 2, MySQL 5.6;

  • Объемная кодовая база: 400 тысяч строк кода на одно приложение, без учета шаблонов; 

  • Отсутствие автотестов; 

  • Сложная предметная область и несколько бизнес-доменов; 

  • Десятки интеграций API от различных поставщиков услуг;

  • Отсутствие моковых данных для API;

  • Плохо структурированный код с классами на пять тысяч строк кода;

  • Сотни предупреждений от PHPStorm.

Начало работы 

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

Проект страдал от 140 критических багов, из-за которых компания несла убытки. Их нужно было как можно быстрее исправить. Поэтому следующие два месяца мы устраняли дефекты и выпускали горящие релизы. В процессе постоянно всплывали новые проблемы, рефакторинг стал восприниматься не как рекомендация по улучшению, а как необходимая мера, чтобы спасти проект от технического банкротства. 

И тогда мы разработали дорожную карту по улучшению системы:

Основные моменты, которые можно выделить:

  • Миграция на Symfony

  • Обновление PHP

  • Обновление Mysql

  • Тестовый контур

  • Рефакторинг кода

  • Внедрение Unit-тестирования

  • Реализация Mock-API поставщиков

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

С какими проблемами мы столкнулись

Как должно было быть:

Есть ветка master для прода и ветка dev для тестового сервера. Разработчик делает задачу в ветке, созданной от master. Отправляет ветку на code-review. Ревьювер мержит в dev и отправляет на тестирование. В случае успеха задача идет в master. 

Как было на деле:

В какой-то момент в dev скопилась куча задач. Это релизы, которые еще рано выливать в master, а также задачи, которые не прошли тестирование. И тогда у нас пошел рассинхрон с веткой master и начались проблемы с тестированием.

В ветке от master код работает, но после слияния с dev работает не так, как хотелось бы. Пошли постоянные merge-конфликты, что съедает время и знатно портит настроение.

Помимо прочего, релизам нужны свои тестовые стенды. Для примера:

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

И вот представьте: внутренние тестировщики все проверили, подошла наша очередь, и разработчик что-то ломает во время исправления бага в совершенно другом месте. Все, test-failed, ждем еще месяц. Неприятно, поэтому нужно что-то делать.

Тестовый контур: требования

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

  • Одновременно может быть запущено множество стендов. У нас 9 разработчиков на проекте. В день может быть реализовано с десяток задач и нужна возможность их изолированного тестирования;

  • Создание стенда не должно вызывать сложностей и занимать много времени;

  • То же касается и удаления стенда. В противном случае есть вероятность, что старые стенды будут висеть и потреблять ресурсы;

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

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

Теперь мы понимаем, чего хотим, и можно приступать к реализации.

Тестовый контур: реализация

Проектирование

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

У нас есть два сервера: сервер управления и сервер тестирования.

На сервере тестирования запускаются стенды, происходит это в Docker и поверх работает Reverse-proxy.

На сервере управления развернут CI-сервер, registry, приложения для удобного управления этим всем и интеграции с Jira.

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

Инфраструктура как код

Решили автоматизировать процесс настройки серверов согласно современным DevOps практикам и инструментам. 

Ansible

Создали инфраструктурный репозиторий, в него сохранили все конфигурации с использованием Ansible. Например, если нужно настроить сервер, добавить пользователей, установить cron или docker — пишем ansible-роль. Деплой компонентов управления — еще одна ansible-роль, деплой приложения тоже. Это позволило разработчикам собирать тестовые стенды локально. 

Jenkins


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

1. Сборка базовых версий образов PHP, MySQL, Nginx. Базовая версия — это конкретная версия PHP и установленные на ней утилиты. В общем, все окружение кроме кода.

2. Снятие дампов БД и упаковка их в образы. Снятие дампов по крону происходит раз в неделю, и сама упаковка занимает около 30 минут. Но это делается один раз, а потом данные в виде готовых образов запускаются на тестовом сервере.

3. Основная задача — это сборка площадок. Сюда входит сборка образов и запуск их на тестовом сервере. 

4. Удаление площадок для освобождения ресурсов. Это остановка приложения, чистка стенда и удаление образов из Registry.

В итоге получается такая схема:

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

Кастомная панель управления 

Найти готовое решение с нормальным пользовательским интерфейсом не удалось, поэтому решили написать сами. Выбрали стек Django + Vue + Vuetify. Силами одного разработчика реализовали нужную функциональность всего за две недели:

Сама панель управления достаточно простая и состоит из нескольких моделей:

  • Настройки. Например, ключ доступа к Jenkins или к GitLab. Грубо говоря, key-value хранилище данных.

  • Конфигурация стендов. Это три сущности: проект, сервис и площадка.

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

В проекте есть сервисы. У них тоже есть обязательные поля, например, символьный код и репозиторий, и дополнительные поля, которые можно добавлять в любом количестве.

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

  • Интеграции с Jira, Jenkins, Docker-registry, Gitlab и Traefik.

Traefik

Отдельного внимания здесь заслуживает Traefik. По нашему мнению, это лучший в мире reverse-proxy для Docker. Другие инструменты мы особо не проверяли, но когда изучили, как это делается в Nginx, то пришли в ужас и решили применять Traefik.

Чем он так хорош? Тем, что он может заставить приложение открываться по определенной ссылке. Например, эти 4 строчки делают доступным контейнер по нужному нам URL-адресу стейджа: 

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

Traefik помог и в этой ситуации. Добавили мини-приложение — обработчик 404-й ошибки. Теперь, когда тестировщик заходит на площадку, он может сам запустить создание площадки по кнопке:

Registry + Portainer

Все наши образы хранятся в Docker-registry. В текущей ситуации он пригодился, так как Elastic и Logstash больше нельзя скачать без VPN. Но они теперь есть в нашем Registry.

Из минусов — тут не очень удобно реализовано удаление образа по тэгу. Метода удаления по тэгу попросту нет. Чтобы удалить, нужно сначала запросить хэш манифеста по тегу, удалить манифест по полученному хэшу и запустить сборщик мусора внутри registry. Только тогда registry почистит место. Неудобно, но терпимо.

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

Итоги

Мы избавились от боли при merge в dev-ветку. Теперь мы больше не теряем на этом время. Можем получить столько тестовых стендов, сколько нужно, причем делается это быстро. Площадка разворачивается в среднем за 4 минуты.

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

Получили средство для обкатки новых инструментов. Приложение на PHP 7.4 запускается в пару кликов.

Теги:
Хабы:
Всего голосов 12: ↑11 и ↓1+10
Комментарии6

Публикации

Истории

Работа

Ближайшие события