пятница, 5 февраля 2010 г.

Непрерывная Интеграция. Антипаттерны.


Непрерывная Интеграция. Антипаттерны.

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

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

1. Максимально быстрое извещение разработчиков о том, что их изменения что-то где-то поломали;
2. Авто-сбор статистики по различным метрикам;
3. Возможность автоматизировать обновление производственного сервера (в случае серверных приложений) или выкладывание новых инсталляционных файлов на сервер (в случае настольных приложений).

Теперь о тех условиях, без которых, как мне кажется, НИ не может иметь жизнь.

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

2. Автоматическая сборка системы.
Система должна "уметь" собираться без участия разработчика - никаких запросов "Вы уверены что хотите запустить модульные тесты?" или "Укажите путь к библиотеке ***:" не должно быть - иначе НИ скрипт/cервер не сможет собрать проект в фоновом режиме. Так же желательно, что бы сборка осуществлялась в один запуск, хотя это уже не обязательно - практически все современные НИ инструменты позволяют создавать композитные шаги для сборки.

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

4. Правильное производственное окружение на НИ сервере. 
Наверняка все сталкивались с ситуацией, когда у одного разработчика на его рабочей машине "все собирается", а у другого тот же самый код упорно не хочет собираться и ужасно ругается. После изнурительных разборов оказывается, что первый доставил себе какую-то библиотеку и забыл ее включить в репозиторий. Это правило не дает подобному случится (ну случится-то случится, но исправления будут происходить куда как быстрее). Если говорить коротко, то сборки продуктов должны проходить на системе, которая повторяет окружение основной производственной системы.

5. Быстрая сборка. 
Условие, которое гласит так: время собирания проекта не должен занимать времени более, чем теоретическое количество времени между коммитами в команде разработки. Причина - сама непрерывность сборки - т.е. основные сборки не должны становиться в очередь, а должны успевать собраться до следующего коммита изменений в репозиторий. В маленьких системах это не проблема, но если система большая, то процесс сборки разбивается на несколько частей - первая (занимающая менее 10 минут) - это основная компиляция и минимальный набор тестов, далее - уже более громоздкие тесты, которые можно убрать в бекграунд и поставить в очередь, и результаты неудачи по которым не будут критичными. Также здесь можно применить подход разделенной компиляции, где компиляция происходит по частям на разных серверах или персональных машинах.

6. Правила извещений и развертывания. 
Описанные логические правила "если - то", по которым будет писаться скрипт/рецепт/конфигурация запуска сборки. Т.е. что необходимо делать при успешном/не успешном результате того или иного шага сборки (и всей сборки в целом) и кого нужно уведомлять. Почему это на мой взгляд является правилом описывает один из антипаттернов ниже.

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

1. Молоток с тридцатью разными режимами работы.
Представьте что вы работаете в цеху, где собирают мебель из готовых компонентов. Задача работника цеха - забить гвоздь между двумя деталями. Вы просите молоток для забивания этого единственного гвоздя, а мега-продвинутый нач. цеха дает вам пятикилограммовый молоток с ручками и рычажками, который можно настроить на забивание чего угодно и где угодно (и в каких угодно условиях). Ваша реакция? Вот такая же будет реакция у человека, которому говорят что для непрерывных сборок проекта "Convert CSV 2 INI" поднят огромный CI сервер, чья проектная настройка включает в себя больше строк, чем строк в самом проекте. А ведь достаточно было написать python скрипт, который собирает и отправляет уведомления, и всем бы было хорошо. Помните, что цель должна оправдывать средства, и если есть способ "сделать это проще" при настройке НИ - делайте, не надо быть мега-продвинутым нач. цеха и закладываться на возможные условия работы при нулевой гравитации.

2. Редкая синхронизация кода.
Это когда разработка долгое время ведется вне ветки trunk. Это даже не антипаттерн CI, а антипаттерн в целом - чем более долгое время ветки не сливаются, тем более долгое время разработчики исправляют полученные конфликты и имеют много головной боли (и руководители вместе с ними). Решение очевидно - почаще сливайте ветки и не делайте "забытых" веток - за каждую ветку и за ее слияние должен кто-то отвечать.

3. Поврежденные сборки.
Чем больше неисправленных вовремя сборок, тем медленнее будет реакция на следующие поломки. Как я уже писал - первостепенная задача НИ - это максимально быстрое извещение о поломке. Если сборка не исправлена, значит все последующие тоже поломаны, а значит сама практика теряет свой смысл. Решение тоже исходит из названия - чините сборки в первую очередь с максимальным приоритетом - не откладывайте на завтра, потому как завтра ваш коллега зальет нормальные изменения и очень испугается, увидев поломку в своей ревизии.

4. Минимальная обратная связь.
Вот и добрались до того, о чем я писал выше. Стройте правильную схему уведомлений. Все участники должны получать ровно столько, сколько нужно. Этот антипаттерн обычно применяют когда "сверху" сказали настроить НИ, и тот, кто его настраивает не заинтересован в результате. Что-то там настроил, что-то там сделал, поставил одного себя в список на уведомления и забы(и)л. А разработчики даже и не подозревают, что сборки ломаются и что у них вообще есть настроенный сервер НИ. Вывод - сначала описываем условия и участников, потом настраиваем НИ.

5. Чрезмерная обратная связь.
Обратная сторона предыдущего антипаттерна. Когда информация льется рекой на всех - кто когда запустился, полные логи всех процессов, логи когда НИ ждал, и т.п. И в результате имеем переполнение буфера у разработчиков и полное игнорирывание уведомлений он НИ сервера. Лечится как и в предыдущем пункте.

6. Медленная система.
Если у вас серьезные проект, и время сборки уже существенно большое, то стоит пойти к начальству и попросить хорошее железо под ваш НИ сервер. Чем дольше выполняется сборка, тем дольше будут слатся уведомления, и тем медленнее будет реакция разработчиков.

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

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