… или использование TeamCity для сборки *.deb-пакетов и не только. Написать статью меня побудило знакомство с модулем tcDebRepository. Я наивно полагал, что "вот сейчас я его подключу, и всё волшебным образом заработает". Как водится, не заработало, и в конце концов был накоплен некий опыт, который захотелось систематизировать. Статья ни в коей мере не является введением в основы TeamCity и предполагает, что читатель уже знаком и собственно с TeamCity, и с инфраструктурой Debian GNU/Linux. Если вы уже представляете, что такое continuous integration, но ещё ни разу не держали в руках TeamCity — вам, наверное, сюда. О сборке пакетов в Debian можно почитать в Debian New Maintainers' Guide. Для игр (на случай, если кто-то захочет воспроизвести результаты) использовался сервер TeamCity 10 и 3 агента под управлением Debian 8.0 (Jessie). 3 агента — это лимит в случае TeamCity Professional. Всё ниженаписанное, думаю, без проблем переносится на любой другой дистрибутив на основе Debian GNU/Linux, напр., Astra Linux. Достаточно произвольным образом я выбрал для экспериментов 4 пакета: С учётом ограничения лицензии типа Professional на количество конфигураций сборки можно было "набрать" до 20 пакетов. TeamCity загружается с официального сайта. Кроме собственно TeamCity, на каждую из агентских машин нам потребуется установить пакет build-essential, равно как и необходимые для сборки зависимости для всех четырёх пакетов (из категорий  build-depends и  build-depends-indep). Это позволит минимизировать (но совсем не обязательно устранить) проблемы с зависимостями при сборке. Пакеты, помимо прочих особенностей, делятся на "родные" (native) и внешние (non-native) (подробнее). "Родные" пакеты (autotools-dev, debhelper, dpkg) обычно разрабатываются в рамках проекта Debian, и исходный код уже содержит необходимую для сборки метаинформацию (каталог debian/ в корне дерева исходного кода). Отличие внешних пакетов (bash) в том, что исходный код никоим образом не завязан на Debian, и инженерам сопровождения (в русскоязычной документации это называется "разработчик Debian", в англоязычной — просто "maintainer") приходится поддерживать параллельное дерево исходного кода с метаинформацией и патчами (это то самое содержимое каталога debian/). Бинарные пакеты, которые мы будем собирать — это, в терминологии TeamCity, "артефакты". Соответственно, нужно указать, что мы ожидаем иметь в сухом остатке по окончании очередной сборки, указав artifact paths: Для "родных" пакетов артефакты pkgname.orig.tar.{gz,bz2,xz} и pkgname.debian.tar.{gz,bz2,xz} не создаются. Чаще всего как раз с этим шагом нет ничего сложного: просто идём в настройки конфигурации сборки (build configuration) и добавляем новый корень системы контроля версий (VCS root). Для "родных" пакетов эту операцию нужно выполнить однократно, для внешних — как правило, дважды (но возможны исключения, когда и разработчики (вне проекта Debian), и инженеры сопровождения используют одну и ту же DVCS (Git, Bazaar), и изменения в коде постоянно "кочуют" из одного репозитория в другой, в то же время не вызывая merge-конфликтов для метаинформации и патчей). Единственная особенность состоит в том, что артефакты в нашем случае будут собираться вне дерева исходного кода (на один каталог выше), так что нам нужно настроить checkout rules таким образом, чтобы, скажем, исходный код пакета dpkg выгружался не в текущий рабочий каталог, а в одноимённый пакету подкаталог, т. е. dpkg/. Это достигается добавлением в checkout rules одной строчки: и в конечном счёте выглядит так:  Теперь можно добавить VCS-триггер и к настройке контроля версий уже не возвращаться: "Но ведь для сборки bash требуется интеграция с Bazaar, а штатная поставка TeamCity не поддерживает эту систему!" — скажет внимательный читатель, и будет прав. Кроме того, TeamCity, увы, не позволит нам добавить и Git URL вида bzr::http://bazaar.launchpad.net/~doko/+junk/pkg-bash-debian — у JGit слишком много ограничений. Существует внешний модуль для поддержки Bazaar, но у него есть по меньшей мере два серьёзных недостатка:   Поскольку сервер TeamCity у меня работал на Windows, я отказался от весёлого приключения в виде установки Bazaar на стороне сервера, а вместо этого в случае пакета bash просто добавил ещё один шаг сборки (Bazaar-интеграцию для бедных), используя Command Line Runner и следующий сценарий оболочки: Такой подход не позволит нам "видеть" изменения в одном дереве исходного кода (из двух) и автоматически запускать сборку при их (изменений) появлении, но для первого опыта вполне достаточен. N.B.! Поскольку Command Line Runner не умеет подсвечивать синтаксис кода сценария, для пользователей браузеров Mozilla Firefox и SeaMonkey я бы рекомендовал расширение It's All Text!, позволяющее редактировать содержимое текстовых полей во внешнем редакторе. Можно подключить Vim или Emacs и насладиться подсветкой синтаксиса, автодополнением, шахматами и поэтессами. Для сборки нам достаточно использовать уже знакомый нам Command Line Runner, вызывающий dpkg-buildpackage. Ключи -uc и -us означают, что мы не хотим создавать цифровых подписей для наших пакетов. Если всё-таки хотим — придётся загрузить соответствующую пару GnuPG-ключей на каждый из агентов. Также обратите внимание, что dpkg-buildpackage должен исполняться не в текущем рабочем каталоге, а в одноимённом пакету подкаталоге (куда будет выгружено дерево исходного кода). Если настройка контроля версий выполнена, поле "Working directory" можно заполнить в один щелчок мыши, не вводя имя каталога вручную:  Как ни странно, но качество кода (или, точнее, стиль разработки) может являться серьёзной проблемой на пути внедрения continuous integration. Опытным путём выяснилось, что, в случае bash, версии в двух деревьях кода рассинхронизированы: последние коммиты в основном дереве соответствуют версии 4.4, хотя файл debian/changelog уже без малого два года назад остановился на версии 4.3, и код одной версии с метаинформацией другой версии вместе не собираются. Хорошо, значит, мне нужна ветка bash-4.3 в основном дереве.  Резюме: При запуске первой же сборки мы увидим, что dpkg-buildpackage завершил работу с кодом возврата 3:  В результате просмотра протокола сборки выяснится, что какие-то зависимости всё-таки отсутствуют:  Но вот мы установили всё, что требовалось (на всех агентах), а dpkg-buildpackage завершается с тем же кодом. В чём же дело? Здесь есть несколько нюансов. Если мы всё-таки хотим себя обмануть и таки собрать наш пакет, достаточно будет запустить dpkg-buildpackage в изменённом окружении: О других способах самообмана можно почитать здесь. После того, как все круги ада пройдены, мы увидим, что очередная сборка завершилась созданием артефактов:  Если вы не хотите, чтобы с каждым инкрементом версии пакета количество артефактов единичной сборки увеличивалось (в конечном счёте предлагая широкий ассортимент из dpkg_1.18.16_i386.deb, dpkg_1.18.17_i386.deb и dpkg_1.18.18_i386.deb), содержимое рабочего каталога стоит выборочно очищать перед каждой сборкой. Это можно было бы выполнить вручную, непосредственно перед dpkg-buildpackage вызвав rm -rf c пресловутыми artifact paths в качестве аргументов, но есть способ лучше — штатный модуль TeamCity с ласковым названием "Швабра". Вот так выглядят его настройки (ключевое здесь — "Before next build start"): А вот таким образом будет выглядеть соответствующий фрагмент протокола сборки, если модуль Swabra правильно настроен: Теперь самое время настроить наш Debian-репозиторий. Это достигается добавлением артефакт-фильтров в настройках модуля tcDebRepository. Некоторое неудобство состоит в том, что для каждой конфигурации (читай: программного пакета) приходится добавлять новый фильтр, фактически идентичный предыдущему:  Уже существующие артефакты не будут проиндексированы, поэтому после окончательной настройки Debian-репозитория в каждой конфигурации должна пройти как минимум одна сборка. После этого наступает предвкушение: При добавлении репозитория в /etc/apt/sources.list можно наблюдать все те же пакеты уже со стороны клиента: N.B.! Если вы собираете под несколько архитектур (i386, x32, amd64, arm), стоит либо иметь несколько отдельных конфигураций сборки, соответствующих одному пакету и различающихся требованиями к агентам, либо, в дополнение к VCS Trigger, добавить Schedule Trigger с флагом "Trigger build on all enabled and compatible agents": Через какое-то время вы увидите, что проект dpkg активно развивается, а вот остальные участники, похоже, курят бамбук.