-А как тебе новые версии поставлять?
-Можешь как все остальные на проекте, через SVN.
-То-есть ты сама билдить будешь?
-Да нет… Бинарники оттуда беру.
Оказывается, очень много программистов, даже имеющих в подписях слова вроде Senior или Superior никогда в жизни не стыкались с понятием CI, или слабо себе представляют что это такое. Не найдя отдельных публикаций на Хабре на эту тему, решил восполнить пробел, а заодно и по возможности заработать желанный инвайт.
Continuous Integration, зачем, почему и как?
Continuous Integration, или для краткости CI – это особый принцип разработки программного обеспечения, который может очень сильно упростить вам жизнь. Если на пальцах, то система CI – это некая программа, которая следит за вашим Source Control, и при появлении там изменений автоматически стягивает их, билдит, гоняет тесты (конечно, если их пишут) и возможно делает кое-что ещё. В случае же неудачи она дает об этом знать всем заинтересованным лицам, в первую очередь – последнему коммитеру.
Что нам это дает? Во первых – в любой момент времени мы имеем достоверную информацию о состоянии исходников в системе. Если последний билд был неудачным («упал»), значит брать свежую версию из сорц-контрола нельзя – он может даже не компилится, а если зелёненький, удачный – значит все отлично. Во-вторых – очень просто найти виновника «торжества» — скорее всего, это последний коммитер – он то и будет отвечать за «ремонт». Кстати, в подобной среде задачей высочайшего приоритета является исправление билда.
Если на проекте используется unit testing, их прогонка при каждом билде дает некоторую гарантию отсутствия регрессионных багов (когда в одном месте починили, а в другом отвалилось).
Также можно включить в билд различные метрики качества кода, как-то покрытие, статический анализ, поиск дублированного кода, и т.д., автоматизировать установку на тестовую машину и тому подобные полезные и не очень вещи.
Итак, как готовить?
Систем CI довольно много, на вскидку приходят на ум CruiseControl, CruiseControl.Net, Atlassian Bamboo, Hudson, Microsoft Team Foundation Server, и лично мой любимый – TeamCity, пусть и не OpenSource, но все-же бесплатный для небольших проектов.
Итак – пускай нам необходимо запустить под TeamCity CI для небольшого проекта на .Net (VS2008SP1), который хранится в SVN, и содержит тесты на nUnit. Как вы увидите, для того чтобы сделать такое на TeamCity, нам не придётся написать ни строчки кода/конфига.
Во первых – нам нужен сервер. Да, я знаю, это уже довольно много, но я больше уверен в позитивном результате если пойду к админам и скажу: дайте мне сервер, чем если пойду к админам и скажу: дайте мне, к примеру, решарпер. Итак, припустим что сервер у нас уже есть, можно виртуальный. Устанавливаем на него TeamCity просто кликая next-next-next – установки по дефолту вполне прилична. В дальнейшем большинство установок также можно не трогать – здесь я буду указывать только те, что нужно изменить. Ну и на будущее, скоро пригодится, поставьте также .Net Framework подходящей версии (3.5SP1 в нашем случае) и Windows SDK.
Итак, в TeamCity по завершении инсталляции создаем новый проект, который фактически просто группа для отдельных билд-конфигураций, и в нем новую конфигурацию, которую я, не мудрствуя лукаво назвал Build.
Ещё одна вещь, которую нуможно указать на этой странице – это путь к бинарникам, поле Artifacts, например вот так: ProjectName\bin\Release\*.*. В общем, артефакты – это те файлы, которые имеют смысл как результаты билда, это могут быть бинарники, логи, результаты анализа, что угодно. Тогда для каждого билда их можно будет аккуратненько скачать из веб-интерфейса.
Кстати… К сожалению стандартные visual studio установочные проекты vdproj не совместимы с msbuild-ом, который внутри делает за нас грязную работу. Поэтому если мы захотим получать в результате build-а готовый msi – придётся немного по-колдовать. Но об этом позже.
Жмём Next, и оказываемся на страничке посвящённой системе управления версиями. Во первых, нужно создать корень VCS. Поясню: к примеру вы используете один и тот же сорц-контрол для нескольких проектов, которые лежат в соседних папочках. Тогда нет смысла настраивать для каждого доступ отдельно – просто настраиваем доступ к корню, а в каждой конфигурации просто указываем какая именно часть исходников нам нужна. Итак, Create and attach new VCS root, далее – Type of VCS (у нас Subversion), ну и в зависимости от типа – дальнейшие настройки, для svn хватает соответственно: url, user name и password. Внизу страницы большая группа настроек labeling rules – это на случай если вы захотите делать теги успешных билдов, и кстати уже со старта настроена на стандартную структуру репозитория. Проверяем правильность введённых данных кнопкой Test Connection, сохраняем. Возвратившись на страницу выбора сорц-контрола для нашей конфигурации, на которой вверху появился только-что созданный корень, необходимо добавить Checkout rules. Именно они определяют, какая именно часть репозитория будет билдится. К примеру, если наш проект лежит по адресу https://svn.company.com/trunk/project то есть смысл установить корень на svn.company.com, а правило задать следующего вида:
+:trunk/project=>.
То-есть: взять то, что находится в SVN по такому-то адресу относительно корня, и вынуть в активную рабочую папку. Все остальные пути, как-то путь к файлу солюшена, пути к артефактам, будут задаваться относительно неё.
Все, можно переходить к самой интересной части: к выбору «раннера», то-есть процесса, который будет собственно исполнять билд. TeamCity из коробки поддерживает множество различных раннеров, в том числе и Ant, и Maven, и что для нас более интересно – NAnt, MSBuild и sln200*.
Для начала нам подойдет sln2008. Из параметров достаточно указать путь к файлу солюшена (как уже говорилось – относительно корня, заданного правилом). Далее у нас есть секция с настройками NUnit – здесь достаточно указать версию и путь(и) к dll-файлам с тестами. Все. По сохранении нас не бросит на следующую страницу – это потому, что конфигурация уже создана и пригодна к использованию. Конечно чтобы это все называть Continuous Integration, нам необходимо добавить условие запуска билда – в правой верхней части интерфейса ссылка под номером 4, Build Triggering. Здесь нужно поставить единственную птичку — Enable triggering when files are checked into VCS. Теперь можно переключатся на страницу Projects и жать кнопочку Run в строке Build. Если все сделано правильно (ну и если ваши исходники в порядке) – значок рядом со словом Build позеленеет, а внизу появится число успешно исполненных тестов.
Как развивать?
Да как хотите. Можно включить поиск продублированного кода или FxCop – соответствующие раннеры уже включены в TeamCity. Можно автоматизировать деплоймент – тут уже придётся сложнее.
Конечно, если ваш проект деплоется простым копированием, вы можете создать конфигурацию на основе простого command-line runner, добавить зависимость на артефакты из билда и наслаждаться.
Но что делать если у вас есть, к примеру, сервис или, хуже, база данных?
Виндовс-сервис перед деплойментом нужно остановить, перезаписать и стартануть, базу данных – пересоздать или обновить.
Здесь вам на помощь придёт NAnt или MSBuild. Я писал скрипты и на том и на другом, и мне сложно сказать что у меня есть особые предпочтения. Они довольно одинаковы, у каждого есть плюсы и недостатки. К примеру nant вызывает тот же msbuild для работы с проектами Visual Studio, msbuild по умолчанию ставится вместе с .net framework. Но с другой стороны у nant-а есть довольно большая библиотека дополнений nant-contrib. Вобщем – дело вкуса.
Итак, как добавить такой скрипт в наш проект? Просто добавляем в сорц-контрол, и ставим соответствующий раннер.
Типичный для меня скрипт билда проекта с сайтом, виндовс-сервисом и базой делает следующее: билдит проект, обновляет конфигурации в соответствии с шаблоном, ставит на сайт майнтенанс-мессадж, стопает на дев-сервере сервис, деплоит все на девелоперский сервер x-copy, обновляет базу скриптами из сорц-контрола (если нужно конечно), стартует сервис, убирает майнтенанс-мессадж. Позитив этого скрипта в том, что он без изменений пригоден к деплойменту в живую среду.
Вобщем, это уже тема для другого разговора, продолжу если вам этот пост понравится.
p.s. Я ещё обещал рассказать как билдить vdproj. Правильный ответ – с помощью Visual Studio. Да, она как не прискорбно должна быть установлена на билд-сервере. Сделать это можно к примеру вот-так.
p.p.s Большое спасибо JetBrains за ихний софт)
p.p.p.s. Ещё большее спасибо Мицголу за инвайт.