- PVSM.RU - https://www.pvsm.ru -
… или использование TeamCity для сборки *.deb
-пакетов и не только.
Написать статью меня побудило знакомство с модулем tcDebRepository [1]. Я наивно полагал, что "вот сейчас я его подключу, и всё волшебным образом заработает". Как водится, не заработало, и в конце концов был накоплен некий опыт, который захотелось систематизировать.
Статья ни в коей мере не является введением в основы TeamCity и предполагает, что читатель уже знаком и собственно с TeamCity, и с инфраструктурой Debian GNU/Linux. Если вы уже представляете, что такое continuous integration, но ещё ни разу не держали в руках TeamCity — вам, наверное, сюда [2]. О сборке пакетов в Debian можно почитать в Debian New Maintainers' Guide [3].
Для игр (на случай, если кто-то захочет воспроизвести результаты) использовался сервер TeamCity 10 и 3 агента п/упр Debian 8.0 (Jessie). 3 агента — это лимит в случае TeamCity Professional [4]. Всё ниженаписанное, думаю, без проблем переносится на любой другой дистрибутив на основе Debian GNU/Linux, напр., Astra Linux [5].
Достаточно произвольным образом я выбрал для экспериментов 4 пакета:
С учётом ограничения лицензии типа Professional на количество конфигураций сборки можно было "набрать" до 20 пакетов.
TeamCity загружается [15] с официального сайта. Кроме собственно TeamCity, на каждую из агентских машин нам потребуется установить пакет build-essential [16], равно как и необходимые для сборки зависимости для всех четырёх пакетов (из категорий build-depends
и build-depends-indep
). Это позволит минимизировать (но совсем не обязательно устранить) проблемы с зависимостями при сборке.
Пакеты, помимо прочих особенностей, делятся на "родные" (native) и внешние (non-native) (подробнее [17]). "Родные" пакеты (autotools-dev
, debhelper
, dpkg
) обычно разрабатываются в рамках проекта Debian, и исходный код уже содержит необходимую для сборки метаинформацию (каталог debian/
в корне дерева исходного кода).
Отличие внешних пакетов (bash
) в том, что исходный код никоим образом не завязан на Debian, и инженерам сопровождения (в русскоязычной документации это называется "разработчик Debian", в англоязычной — просто "maintainer") приходится поддерживать параллельное дерево исходного кода с метаинформацией и патчами (это то самое содержимое каталога debian/
).
Бинарные пакеты, которые мы будем собирать — это, в терминологии TeamCity, "артефакты". Соответственно, нужно указать, что мы ожидаем иметь в сухом остатке по окончании очередной сборки, указав artifact paths [18]:
Для "родных" пакетов артефакты 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/
. Это достигается добавлением одной строчки:
+:.=>dpkg
и в конечном счёте выглядит так:
Теперь можно добавить VCS-триггер и к настройке контроля версий уже не возвращаться:
"Но ведь для сборки bash
требуется интеграция с Bazaar, а штатная поставка TeamCity не поддерживает эту систему!" — скажет внимательный читатель, и будет прав. Кроме того, TeamCity, увы, не позволит нам добавить и Git URL вида bzr::http://bazaar.launchpad.net/~doko/+junk/pkg-bash-debian
— у JGit слишком много ограничений.
Существует внешний модуль [19] для поддержки Bazaar, но у него есть по меньшей мере два серьёзных недостатка:
Поскольку сервер TeamCity у меня работал на Windows, я отказался от весёлого приключения в виде установки Bazaar на стороне сервера, а вместо этого в случае пакета bash
просто добавил ещё один шаг сборки (Bazaar-интеграцию для бедных), используя Command Line Runner [21] и следующий сценарий оболочки:
#!/bin/bash
#
# vim:ft=sh:
#
export LANG=C
export LC_ALL=C
set -e
rm -rf bash/debian
bzr branch http://bazaar.launchpad.net/~doko/+junk/pkg-bash-debian bash/debian
major_minor=$(head -n1 bash/debian/changelog | awk '{print $2}' | tr -d '[()]' | cut -d- -f1)
echo "Package version from debian/changelog: ${major_minor}"
tar_archive=bash_${major_minor}.orig.tar
rm -f ${tar_archive} ${tar_archive}.bz2
# +:.=>bash checkout rule should be set for the main VCS root in TeamCity
tar cf ${tar_archive} bash
tar --delete -f ${tar_archive} bash/debian
# Required by dpkg-buildpackage
bzip2 -9 ${tar_archive}
Такой подход не позволит нам "видеть" изменения в одном дереве исходного кода (из двух) и автоматически запускать сборку при их (изменений) появлении, но для первого опыта вполне достаточен.
N.B.! Поскольку Command Line Runner не умеет подсвечивать синтаксис кода сценария, для пользователей браузеров Mozilla Firefox и SeaMonkey я бы рекомендовал расширение It's All Text! [22], позволяющее редактировать содержимое текстовых полей во внешнем редакторе. Можно подключить 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
в основном дереве.
bash-4.3-testing
с тэгами bash-4.3-rc2
и (ниже, не видно) bash-4.3-rc1
— и потом она внезапно обрывается. Если верить истории версий, то релиз bash
4.3 так и не состоялся.master
появляется коммит с тэгом bash-4.3
, которому не предшествует ни одна операция типа merge или cherry-pick.git push
на savannah.gnu.org [23] происходит через равные промежутки времени, причём через git merge --squash -s ours
(у каждого коммита невероятно длинный и трудно читаемый diff
).Bash-4.3 patch XY
" (всего 46 патчей для версии 4.3) кладутся в master
(на bash-4.3-testing
их нет), а через 3 недели на ветке master
появляется метка bash-4.4-beta2
. Это означает, что последнее стабильное состояние "bash
4.3 плюс патчи" взять, увы, неоткуда. Слава богу, TeamCity позволяет выполнять сборку по тэгу (флаг "Enable to use tags in the branch specification [24]"), что и было в конце концов сделано.Резюме:
bash
мы будем в другой раз.При запуске первой же сборки мы увидим, что dpkg-buildpackage
завершил работу с кодом возврата 3:
В результате просмотра протокола сборки выяснится, что какие-то зависимости всё-таки отсутствуют:
Но вот мы установили всё, что требовалось (на всех агентах), а dpkg-buildpackage
завершается с тем же кодом. В чём же дело? Здесь есть несколько нюансов.
dpkg-buildpackage
будет "ругаться", что ваши стабильные версии зависимостей "устарели"). Для подавления ошибки иногда достаточно добавить ключ -d [26]:
dpkg-buildpackage -uc -us -d
configure
, созданный более новой версией GNU Autotools, чем в настоящее время установлены в системе. dpkg-buildpackage
не в состоянии диагностировать такую ситуацию — вместо этого в протоколе сборки мы наблюдаем загадочные сообщения об отсутствующих макросах m4
. Решением является повторное создание сценария configure
с помощью текущей версии GNU Autotools. Просто добавьте первым шагом сборки следующую команду:
autoreconf -i
Если мы всё-таки хотим себя обмануть и таки собрать наш пакет, достаточно будет запустить dpkg-buildpackage
в изменённом окружении:
DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage -uc -us
О других способах самообмана можно почитать здесь [27].
После того, как все круги ада пройдены, мы увидим, что очередная сборка завершилась созданием артефактов:
Теперь самое время настроить наш Debian-репозиторий. Это достигается добавлением артефакт-фильтров в настройках модуля tcDebRepository. Некоторое неудобство состоит в том, что для каждой конфигурации (читай: программного пакета) приходится добавлять новый фильтр, фактически идентичный предыдущему:
Уже существующие артефакты не будут проиндексированы, поэтому после окончательной настройки Debian-репозитория в каждой конфигурации должна пройти как минимум одна сборка. После этого наступает предвкушение:
При добавлении репозитория в /etc/apt/sources.list
можно наблюдать все те же пакеты уже со стороны клиента:
N.B.! Если вы собираете под несколько архитектур (i386
, x32
, amd64
, arm
), стоит либо иметь несколько отдельных конфигураций сборки, соответствующих одному пакету и различающихся требованиями к агентам, либо, в дополнение к VCS Trigger, добавить Schedule Trigger [28] с флагом "Trigger build on all enabled and compatible agents":
Через какое-то время вы увидите, что проект dpkg
активно развивается, а вот остальные участники, похоже, курят бамбук.
Автор: unix_junkie
Источник [29]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/222619
Ссылки в тексте:
[1] tcDebRepository: https://github.com/tcplugins/tcDebRepository
[2] сюда: https://www.youtube.com/playlist?list=PLQ176FUIyIUZGrzpC-C_jwXpsa22XKXdt
[3] Debian New Maintainers' Guide: https://www.debian.org/doc/manuals/maint-guide/
[4] Professional: https://www.jetbrains.com/teamcity/buy/#license-type=new-license
[5] Astra Linux: http://www.astralinux.com/download.html
[6] autotools-dev: https://packages.debian.org/source/unstable/autotools-dev
[7] Git: https://anonscm.debian.org/gitweb/?p=users/hmh/autotools-dev.git
[8] bash: https://packages.debian.org/source/unstable/bash
[9] Git: http://git.savannah.gnu.org/cgit/bash.git
[10] Bazaar: https://code.launchpad.net/~doko/+junk/pkg-bash-debian
[11] debhelper: https://packages.debian.org/source/unstable/debhelper
[12] Git: https://anonscm.debian.org/git/debhelper/debhelper.git
[13] dpkg: https://packages.debian.org/source/unstable/dpkg
[14] Git: https://anonscm.debian.org/git/dpkg/dpkg.git
[15] загружается: https://www.jetbrains.com/teamcity/download/#section=linux-version
[16] build-essential: https://packages.debian.org/jessie/build-essential
[17] подробнее: https://wiki.debian.org/DebianMentorsFaq#What_is_the_difference_between_a_native_Debian_package_and_a_non-native_package.3F
[18] artifact paths: https://confluence.jetbrains.com/display/TCD10/Configuring+General+Settings#ConfiguringGeneralSettings-ArtifactPaths
[19] внешний модуль: https://launchpad.net/bzr4j/
[20] bzr xmlls и bzr xmllog: http://wiki.bazaar.canonical.com/XMLOutput
[21] Command Line Runner: https://confluence.jetbrains.com/display/TCD10/Command+Line
[22] It's All Text!: https://addons.mozilla.org/en-US/firefox/addon/its-all-text/
[23] savannah.gnu.org: http://savannah.gnu.org/
[24] Enable to use tags in the branch specification: https://confluence.jetbrains.com/display/TCD10/Git#Git-GeneralSettings
[25] Debain experimental: https://wiki.debian.org/DebianExperimental
[26] -d: http://man7.org/linux/man-pages/man1/dpkg-buildpackage.1.html
[27] здесь: https://wiki.debian.org/BuildProfileSpec
[28] Schedule Trigger: https://confluence.jetbrains.com/display/TCD10/Configuring+Schedule+Triggers
[29] Источник: https://habrahabr.ru/post/204496/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.