Потребовалось мне настроить процесс сборки и доставки на сайт пакетов программ из Git-репозитария. И увидев, ни так давно, тут на Хабре статью по buildbot (ссылка в конце) решил для этого попробовать его и применить.
Так как buildbot — это распределённая система, то будет логичным под каждую архитектуру и операционку сделать отдельный сборочный хост. В нашем случае это будут LXC-контейнеры (в случае linux) и qemu (в случае windows):
vm-srv-build1 — centos 7, тут будет buildbot мастер (master) и один из рабочих (worker)
vm-srv-build2 — debian 10, для сборки DEB пакетов
vm-srv-build3 — windows 10, для сборки, сами понимаете, под что
Собирать будем Rac GUI — графическая морда к 1С rac для управления кластером серверов. Под линукс будут использоваться штатные средства под каждую ОС, для сборки exe-файла под windows из tcl-скрипта используется freewrap.
Установка
GNU/Linux
По установке, документации в сети достаточно 1,2. Да и особых проблем она не вызывает:
Для мастера:
Конечно, более правильным будет собрать пакеты под каждую ОС, но это в рамки статьи не входит. Также опустим описание настройки контейнеров для работы, отмечу только, что использую ProxMox VE. И ещё потребуется установить пакеты под каждую ось потребные для сборки (centos: rpmdevtools и т.д; debian: build-essential, dh-make, pbuilder и т.д.)
Сборка проектов и сервисы buildbot будут запускаться от имени непривилегированного пользователя, поэтому необходимо его создать на всех хостах, участвующих в процессе:
adduser buildbot
Дальше настроим автоматический запуск сервисов, соответственно на каждом из хостов (контейнеров):
После этого, можно создать инфраструктуру каталогов для «рабочих» (на всех хостах), для этого регистрируется под пользователем buildbot и выполняем следующие команды:
На первом хосте vm-srv-build1:
su - buildbot
mkdir /home/buildbot/worker
cd ~
buildbot-worker create-worker --umask=0o22 --keepalive=60 worker vm-srv-build1:4000 CentOS 123456
На втором хосте vm-srv-build2:
su - buildbot
mkdir /home/buildbot/worker
cd ~
buildbot-worker create-worker --umask=0o22 --keepalive=60 worker vm-srv-build1:4000 Debian-10 123456
На хостах-рабочих службу buildbot-worker можно запустить
systemctl start buildbot-worker
MS Windows
В качестве «рабочего» для сборки под windows, будет использована виртуальная машина с последним релизом Win10.
Для работы понадобиться:
После того, как установится всё вышеперечисленное, можно поставить и сам buildbot:
pip install buildbot-worker
Создадим рабочий каталог
md c:worker
И запустим
buildbot-worker start c:worker
Если всё работает (см. лог c:workertwistd.log), то можно нашего «рабочего», зарегистрировать как службу, добавив в реестр пункт с рабочим каталогом (команды выполняются в powershell запущенном от имени администратора):
С «рабочими» на этом всё, дальше их можно не трогать, всё управление идёт с мастера.
Настройка мастера
Для начала, создадим инфраструктуру для мастера (на главном хосте), для этого регистрируется под пользователем buildbot и выполняем следующие команды:
su - buildbot
mkdir /home/buildbot/master
cd ~
buildbot create-master master
Для готовых пакетов создадим каталог builds
mkdir /home/buildbot/builds
В каталоге /home/buildbot/master/ был создан файл master.cfg. Данный файл представляет собой код на python и содержит описание всех механизмов работы системы, с ним и будем работать в дальнейшем.
Для автоматизации сборки пакетов разных версий, дабы не приходилоось лазить в код файла master.cfg, в основном скрипте программы rac_gui.tcl в заголовке, добавлены строки с текущими версией и релизом:
И на основе этих строк buildbot будет нумеровать пакеты. Для выдёргивания данных, используется вызов консольного grep. В buildbot просто так нельзя опеределить переменные для «рабочих» (во всяком случае, я не нашёл как). Для этого служат свойства (property). Т.е. в сборочный процесс, добавляем шаги по определению версии и релиза и соответсвенно, устанавливаем свойства version и release. Свойства можно устанавливать различными способами, в данном случае это вызов консольной команды:
# Добавим определение версии из основного файла
rac_gui_build_RPM.addStep(
steps.SetPropertyFromCommand(
command="grep version ../rac-gui/rac_gui.tcl | grep -oE 'b[0-9]{1,2}.[0-9]{1,2}.[0-9]{1,2}b'", property="version"
)
)
# Добавим определение релиза из основного файла
rac_gui_build_RPM.addStep(
steps.SetPropertyFromCommand(
command="grep release ../rac-gui/rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
)
)
Подставлять полученные значения можно путём вызова util.Interpolate().
На этом с RPM закончили. Теперь приступим к описанию алгоритма сборки DEB-пакета. Так как процессы сборки пакетов под разные системы независимы друг от друга, то и многие шаги будут повторятся.
rac_gui_build_DEB = util.BuildFactory()
rac_gui_build_DEB.addStep(steps.Git(
repourl = 'https://bitbucket.org/svk28/rac-gui.git',
haltOnFailure = True,
submodules = True,
mode='full',
workdir='build',
progress = True)
)
# Добавим определение версии из основного файла
rac_gui_build_DEB.addStep(
steps.SetPropertyFromCommand(
command="grep version rac_gui.tcl | grep -oE 'b[0-9]{1,2}.[0-9]{1,2}.[0-9]{1,2}b'", property="version"
)
)
# Добавим определение релиза из основного файла
rac_gui_build_DEB.addStep(
steps.SetPropertyFromCommand(
command="grep release rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
)
)
# Переименуем запускаемый файл
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["mv", "rac_gui.tcl", "racgui"]))
Для RPM-пакета часть нижеследующих процедур делается самим rpm при сборке и описаны внутри спека, для дебиана приходится это делать тут:
# Поменяем пути к библиотекам
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["sed", "-i", "s+^set dir(lib)+set dir(lib) /usr/share/rac-gui/lib ;#+g", "racgui"]))
# Поменяем пути к файлам
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["sed", "-i", "s+[pwd]+/usr/share/rac-gui+g", "racgui"]))
# заархивируем исходники
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["tar", "czf", util.Interpolate("../rac-gui_%(prop:version)s.orig.tar.gz"), "."]))
# Соберём пакет
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["dpkg-buildpackage"]))
# Скопируем файл на мастер
rac_gui_build_DEB.addStep(
steps.FileUpload(
workersrc=util.Interpolate("../rac-gui_%(prop:version)s-%(prop:release)s_amd64.deb"),
masterdest=util.Interpolate("/home/buildbot/builds/rac-gui_%(prop:version)s-%(prop:release)s_amd64.deb")
)
)
rac_gui_build_DEB.addStep(
steps.MasterShellCommand(
command=["/usr/local/bin/deploy-ftp.tcl",
util.Interpolate("--local-file=/home/buildbot/builds/rac-gui_%(prop:version)s-%(prop:release)s_amd64.deb"),
util.Interpolate("--remote-file=uploads/rac-gui/rac-gui_%(prop:version)s-%(prop:release)s_amd64.deb")]
)
)
Сохраняем файл и можно попробовать запустить службу мастера:
systemctl restart buildbot-master
В логе проконтролируем что с конфигом все в порядке и все работает в штатном режиме. Все наши работники должны теперь подключиться, о чем в логе »»’/home/buildbot/master/twistd.log»»’ будет радостно сообщено:
2019-07-24 16:50:35+0300 [-] Loading buildbot.tac...
2019-07-24 16:50:35+0300 [-] Loaded.
2019-07-24 16:50:35+0300 [-] twistd 19.2.1 (/usr/bin/python3.6 3.6.8) starting up.
2019-07-24 16:50:35+0300 [-] reactor class: twisted.internet.epollreactor.EPollReactor.
2019-07-24 16:50:35+0300 [-] Starting BuildMaster -- buildbot.version: 2.3.1
2019-07-24 16:50:35+0300 [-] Loading configuration from '/home/buildbot/master/master.cfg'
2019-07-24 16:50:36+0300 [-] /usr/local/lib/python3.6/site-packages/buildbot/config.py:90: buildbot.config.ConfigWarning: [0.9.0 and later] `buildbotNetUsageData` is not configured and defaults to basic.
This parameter helps the buildbot development team to understand the installation base.
No personal information is collected.
Only installation software version info and plugin usage is sent.
You can `opt-out` by setting this variable to None.
Or `opt-in` for more information by setting it to "full".
2019-07-24 16:50:36+0300 [-] Setting up database with URL 'sqlite:/state.sqlite'
2019-07-24 16:50:36+0300 [-] setting database journal mode to 'wal'
2019-07-24 16:50:36+0300 [-] adding 1 new services, removing 0
2019-07-24 16:50:36+0300 [-] adding 1 new change_sources, removing 0
2019-07-24 16:50:36+0300 [-] gitpoller: using workdir '/home/buildbot/master/gitpoller-work'
2019-07-24 16:50:36+0300 [-] adding 3 new builders, removing 0
2019-07-24 16:50:36+0300 [-] adding 1 new schedulers, removing 0
2019-07-24 16:50:36+0300 [-] initializing www plugin 'waterfall_view'
2019-07-24 16:50:36+0300 [-] initializing www plugin 'console_view'
2019-07-24 16:50:36+0300 [-] initializing www plugin 'grid_view'
2019-07-24 16:50:36+0300 [-] NOTE: www plugin 'sitenav' is installed but not configured
2019-07-24 16:50:36+0300 [-] initializing www plugin 'waterfall_view'
2019-07-24 16:50:36+0300 [-] initializing www plugin 'console_view'
2019-07-24 16:50:36+0300 [-] initializing www plugin 'grid_view'
2019-07-24 16:50:36+0300 [-] NOTE: www plugin 'sitenav' is installed but not configured
2019-07-24 16:50:36+0300 [-] BuildbotSite starting on 80
2019-07-24 16:50:36+0300 [-] Starting factory <buildbot.www.service.BuildbotSite object at 0x7fe31c2657b8>
2019-07-24 16:50:36+0300 [-] adding 3 new workers, removing 0
2019-07-24 16:50:36+0300 [-] PBServerFactory starting on 4000
2019-07-24 16:50:36+0300 [-] Starting factory <twisted.spread.pb.PBServerFactory object at 0x7fe31c147470>
2019-07-24 16:50:37+0300 [-] BuildMaster is running
2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: sending {'installid': 'b6193b126b96689351d2fe95787c5a03fc0879f9', 'versions': {'Python': '3.6.8', 'Buildbot': '2.3.1', 'Twisted': '19.2.1'}, 'platform': {'platform': 'Linux-4.15.18-10- pve-x86_64-with-centos-7.6.1810-Core', 'system': 'Linux', 'machine': 'x86_64', 'processor': 'x86_64', 'python_implementation': 'CPython', 'version': '#1 SMP PVE 4.15.18-32', 'distro': 'centos:7'}, 'plugins': {'buildbot/worker/base/Worker': 3, 'buildbot/config/BuilderConfig': 3, 'buildbot/schedulers/basic/SingleBranchScheduler': 1, 'buildbot/reporters/mail/MailNotifier': 1, 'buildbot/changes/gitpoller/GitPoller': 1, 'buildbot/steps/worker/MakeDirectory': 1, 'buildbot/steps/source/git/Git': 3, 'buildbot/steps/shell/ShellCommand': 9, 'buildbot/steps/package/rpm/rpmbuild/RpmBuild': 1}, 'db': 'sqlite', 'mq': 'simple', 'www_plugins': ['waterfall_view', 'console_view', 'grid_view']}
2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] worker 'CentOS' attaching from IPv4Address(type='TCP', host='127.0.0.1', port=37332)
2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Got workerinfo from 'CentOS'
2019-07-24 16:50:37+0300 [-] bot attached
2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Worker CentOS attached to Rac-GUI-RPM-builder
2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: buildbot.net said: ok
2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] worker 'Windows-10' attaching from IPv4Address(type='TCP', host='192.168.5.145', port=49831)
2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] Got workerinfo from 'Windows-10'
2019-07-24 16:50:40+0300 [-] bot attached
2019-07-24 16:50:40+0300 [Broker,1,192.168.55.15] Worker Windows-10 attached to Rac-GUI-WIN-builder
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] worker 'Debian-10' attaching from IPv4Address(type='TCP', host='192.168.5.9', port=44430)
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Got workerinfo from 'Debian-10'
2019-07-24 16:50:41+0300 [-] bot attached
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Worker Debian-10 attached to Rac-GUI-DEB-builder
На этом процесс настройки завершён. Посмотреть текущее состояние можно через вэб-мордe. Где также можно посмотреть ошибки сборки, пнуть зависший процесс если что-то пошло ни так и т.д.
Сразу после запуска наших работяг можно посмотреть через меню «Builds» -> «Workers»
После того, как будет произведен первый процесс сборки (т.е. изменения в Git-репозитарии), на первой страничке появится состояние процессов.
Если ткнуть мышой в нужную строку то откроется страничка с текущим состоянием данного процесса, где видно что происходит, какие ошибки и т.д.