Через тернии к сборке

в 7:31, , рубрики: bash, Hudson, redmine, smoke, Блог компании RTL-Service, разработка программного обеспечения, тестирование, Тестирование IT-систем

Привет, дорогие читатели. Я – разработчик в компании “RTL Service”, в которой мои обязанности по разработке продукта пересекаются с обязанностями DevOps. Конкретнее – я создаю и поддерживаю инфраструктуру сборки и первичного тестирования наших продуктов еще до их попадания в отдел тестирования.

В данной статье будет рассказано о том, какой путь у нас проходит код от пуша в хранилище системы контроля версий до формирования установочного deb пакета и размещения в наш репозиторий пакетов.
В качестве сервера CI (непрерывной интеграции) у нас используется Hudson, можете кидать в меня тапками, но мы руководствуемся принципом «Работает — не трогай».
В дальнейшем есть планы попробовать TeamCity либо Jenkins.

Общая информация о задачах и группах на нашем CI сервере.

Все задачи по сборкам у нас разбиты на 5 больших групп:
● Firmware (сборка прошивок устройств, они выходят за рамки этой статьи, но первый и второй шаг сборки у них происходит так же как у остальных объектов сборки)
● Server (сборки основного сервера)
● Appserver (сборки сервера приложений)
● Webclient (сборки веб интерфейса)
● Tests (запуск полного функционального тестирования и т.п)

Шаг 1: Коммит в систему контроля версий.
Тут все довольно тривиально. При помощи хуков со стороны сервера контроля версий посылается GET запрос на CI сервер, результатом которого будет запуск параметризованной сборки (что это и для чего – будет рассказано ниже).
Пример post-commit хука:

while read orev nrev ref
do
case "$ref" in
refs/heads/i*)
issue_branch="${ref##refs/heads/}"
curl -X GET "http://адрес_ci_сервера/…./buildWithParameters?ISSUE_BRANCH=$issue_branch"
;;
esac
done

Шаг 2: Запуск параметризованной сборки.
Как ясно из названия, — это сборка, которая может иметь различные параметры. В нашем случае обычно хватает пары-тройки, например, — имя ветки и название продукта. Такой подход позволяет не плодить задачи, которые различаются между собой не критичными моментами.
На этом этапе происходит первичная сборка, например, для java проекта это будет работа с gradle в самом примитивном варианте, выглядящая как «gradle clean build».
Это позволит выявить случайные недочёты в коде многомодульного проекта и прогнать юнит тесты.

Шаг 3: Запуск smoke тестирования.
Этот шаг выполняется в рамках параметризованной сборки. Smoke тесты проходят в рамках slave машины, на которой запущена задача по сборке. Этот подход позволяет выполнять сборку и начальное тестирование различного ПО (например, сервера приложений и веб-клиента) параллельно, что уменьшает время ожидания новой версии отделом тестирования. В то же время разработчики раньше получают информацию о возникших проблемах.
Вполне очевидно, что в рамках этих тестов проверяется, что после сборки кода (нового или исправленного) устанавливаемое приложение стартует и выполняет основные функции. В нашей компании, в зависимости от проекта, они написаны на разных фреймворках (например, cucumber).
Тут нам и понадобятся параметры сборки, которые мы передали, т.к. для разных продуктов, как и в случае с приемочным тестированием, сценарии smoke тестирования могут очень сильно разниться.

Шаг 4: Запуск приемочного тестирования.
На этом этапе выполняется приемочное тестирование продукта с различными сценариями. Расписывать это не вижу смысла, т.к. на эту тему есть статьи на хабре и соответствующих ресурсах.

Шаг 5: Сборка deb пакета.
Поскольку наша система рассчитана на дистрибутив Debian, то самым очевидным и удобным средством будет родной для него формат распространения бинарных пакетов deb.
Про структуру пакета на хабре имеются статьи, с которыми можно ознакомиться. Я же расскажу про некоторые ухищрения, которые применяются у нас.
Перво-наперво нужно получить ревизию проекта для версионности и возможности обновлять пакет прямо из репозитория через apt-get update и apt-get install.
Для этого мы используем стандартную функцию гита «git describe», при желании можно получить номер сборки в соответствии тегу, добавив параметр --tags. Обычно под новую минорную версию мы заводим свой тег.
Распарсив это по регулярному выражению, получаем нечто вроде «1075-g7fb7c67», что и будет номером нашей ревизии. Вкупе с названием и версией продукта мы получаем полное название нашего пакета, в нашем случае получается нечто вроде «rtls-webclient-mines-1.0-dev_1.0-dev.1075-g7fb7c67_all.deb».

Собственно, для самой сборки у нас используется bash скрипт.
Суть в том, что он создает сборочную директорию и кладёт туда шаблоны для создания пакета. Дальше, в зависимости от наименования продукта, кладёт необходимые модули и обрабатывает шаблон файла config в папке DEBIAN, через команду sed прописывает свежую информацию о пакете, имея сведения полученные выше (на примере с ревизией это выглядит так: «sed -e «s/%REVISION%/$REV/» -i $PACKAGE/DEBIAN/control»).
После подготовки сборочной директории при помощи fakeroot создаётся сам deb пакет командой «dpkg-deb --build $TMP_DIR ${NAME}_${VERS}.${REV}_all.deb», где TMP_DIR — сборочная директория, NAME — имя продукта. VERS – версия, а REV – вытащенная ревизия.
Дальше при помощи wput полученный пакет кладется в репозиторий, а пакет для отправки – в отдел тестирования.

Шаг 6: Работа с баг трекером.
В качестве баг трекера у нас используется redmine, и для него написан соответствующий скрипт, который определяет наличие номера тикета в коммите, и при наличии такового, тикет комментируется служебным пользователем в названии пакета, в котором применено исправление найденной ошибки. Это позволяет отделу тестирования практически сразу проверять исправления.

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

Пример удачной сборки

image

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

image

Автор: RTL-Service

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js