Buildbot v príkladoch

Bolo potrebné nastaviť proces zostavovania a dodávky balíkov softvéru na stránku z Git repozitára. A keď som nedávno videl článok o buildbote (odkaz na konci) rozhodol som sa, že ho vyskúšam a aplikujem.

Keďže buildbot je distribuovaný systém, je logické vytvoriť samostatný zostavovací host pre každú architektúru a operačný systém. V našom prípade to budú LXC kontajnery (pre linux) a qemu (pre windows):

  • vm-srv-build1 — centos 7, tu bude buildbot majster (master) a jeden z robotov (worker)
  • vm-srv-build2 — debian 10, pre zostavovanie DEB balíkov
  • vm-srv-build3 — windows 10, pre zostavovanie, sami chápete, na čo

Zostavovať budeme Rac GUI — grafické rozhranie pre 1C rac na správu serverových klastrov. Pre linux budú použité štandardné nástroje pre každú OS, na zostavenie exe súboru pre windows z tcl skriptu sa používa freewrap.

Inštalácia

GNU/Linux

Dostatočne veľa dokumentácie a inštalačných pokynov je k dispozícii na internete. 1,2A nevytvára zvláštne problémy:
Pre majstra:

pip3 install buildbot
pip3 install twisted
pip3 install autobahn
pip3 install pysqlite3
pip3 install sqlalchemy sqlalchemy-migrate
pip3 install buildbot-www buildbot-grid-view buildbot-console-view buildbot-waterfall-view
pip3 install python-dateutil

Pre "roboty" bude stačiť toto:

pip3 install buildbot-worker

Samozrejme, správnejšie by bolo zostaviť balíky pre každú OS, ale to nie je predmetom tohto článku. Odkážem len, že používam ProxMox VE. A navyše bude potrebné nainštalovať balíky potrebné pre zostavovanie pre každú platformu (centos: rpmdevtools atď.; debian: build-essential, dh-make, pbuilder atď.)

Zostavenie projektov a služby buildbot sa budú spúšťať pod nezprivilegovaným používateľom, preto je potrebné ho vytvoriť na všetkých hostoch zúčastnených v procese:


adduser buildbot

Ďalej nastavíme automatické spúšťanie služieb na každom z hostov (kontajnerov):

Systemd jednotka na spustenie majstra:

touch /etc/systemd/buildbot-master.service 

[Unit]
Description=BuildBot master service
After=network.target

[Service]
User=buildbot
Group=buildbot
WorkingDirectory=/home/buildbot/master
ExecStart=/usr/local/bin/buildbot start --nodaemon
ExecReload=/bin/kill -HUP $MAINPID

[Install]
WantedBy=multi-user.target

a "robotov"

touch /etc/systemd/buildbot-worker.service 

[Unit]
Description=BuildBot worker service
After=network.target

[Service]master
User=buildbot
Group=buildbot
WorkingDirectory=/home/buildbot/worker
ExecStart=/usr/local/bin/buildbot-worker start --nodaemon

[Install]
WantedBy=buildbot-master.service

Jelikož všetky skripty (v našom prípade) ležia v /usr/local/, je potrebné zapísať cestu k nim do premenných prostredia:

nano /root/.bash_profile

PATH=$PATH:$HOME/.local/bin:$HOME/bin:/usr/local/bin

Potom môžete vytvoriť infraštruktúru adresárov pre „pracovníkov“ (na všetkých hostiteľoch), za týmto účelom sa zaregistruje pod používateľom buildbot a vykonáte nasledovné príkazy:

Na prvom hoste 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

Na druhom hoste 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

Na pracovných hostoch možno spustiť službu buildbot-worker

systemctl start buildbot-worker

MS Windows

Ako „pracovníka“ pre zostavenie pre Windows bude použitá virtuálna mašina s posledným vydaním Win10.
Na prácu budete potrebovať:

Po inštalácii všetkého vyššie uvedeného môžeme nainštalovať aj samotný buildbot:

pip install buildbot-worker

Vytvoríme pracovný adresár

md c:worker

A spustíme

buildbot-worker start c:worker

Ak všetko funguje (pozri log c:workertwistd.log), môžeme nášho „pracovníka“ zaregistrovať ako službu pridaním položky do registra s pracovným adresárom (príkazy sa vykonávajú v powershell spustenom s právami správcu):

buildbot_worker_windows_service.exe --user VM-SRV-BUILD3buildbot --password 123456 --startup auto install
New-ItemProperty -path Registry::HKEY_LOCAL_MACHINESYSTEMCurrentControlSetservicesBuildBotParameters -Name directories -PropertyType String -Value c:worker

A môžeme spustiť službu

Start-Service buildbot

S „pracovníkmi“ je toto všetko, ďalej ich netreba trápiť, všetka správa sa deje z mastera.

Nastavenie mastera

Na začiatok vytvoríme infraštruktúru pre mastera (na hlavnom hoste), za týmto účelom sa zaregistruje pod používateľom buildbot a vykonáte nasledovné príkazy:

su - buildbot
mkdir /home/buildbot/master
cd ~
buildbot create-master master

Pre hotové balíky vytvoríme adresár builds

mkdir /home/buildbot/builds

V adresári /home/buildbot/master/ bol vytvorený súbor master.cfg. Tento súbor predstavuje kód v Pythone a obsahuje opis všetkých mechanizmov práce systému, s ktorým budeme pracovať ďalej.

nano /home/buildbot/master/master.cfg

import os, re
from buildbot.plugins import steps, util, schedulers, worker, changes, reporters

c= BuildmasterConfig ={}

# Opis našich pracovníků.
c['workers'] = [ worker.Worker('CentOS', '123456'), worker.Worker('Debian-10', '123456'), worker.Worker('Windows-10', '123456')]
c['protocols'] = {'pb': {'port': 4000}} 

# Určenie, ktorú repozitár má master sledovať
c['change_source'] = []
c['change_source'].append(changes.GitPoller(
       repourl = 'https://bitbucket.org/svk28/rac-gui.git',
       project = 'Rac-GUI',
       branches = True,
       pollInterval = 60
      )
)

# Služba na spustenie zostavenia
c['schedulers'] = []
c['schedulers'].append(schedulers.SingleBranchScheduler(
       name="Rac-GUI-schedulers",
       change_filter=util.ChangeFilter(branch='master'),
       builderNames=["Rac-GUI-RPM-builder", "Rac-GUI-DEB-builder", "Rac-GUI-WIN-builder"],
       properties = {'owner': 'admin'}
       )
)
@util.renderer

######################################3
# Zostavenie RPM balíčka
 rac_gui_build_RPM = util.BuildFactory()

rac_gui_build_RPM.addStep(steps.Git(
       repourl = 'https://bitbucket.org/svk28/rac-gui.git',
       workdir = 'rac-gui',
       haltOnFailure = True,
       submodules = True,
       mode='full',
       progress = True)
)

Na automatizáciu zostavenia balíčkov rôznych verzií, aby sa nemuselo kód súboru master.cfg prehľadávať, boli do hlavného skriptu programu rac_gui.tcl pridané riadky s aktuálnou verziou a vydaním:

######################################################
#        Rac GUI
...
# version: 1.0.3
# release: 1

A na základe týchto riadkov bude buildbot číslovať balíčky. Na získavanie dát sa používa volanie príkazu grep. V buildbote jednoducho nie je možné určiť premenné pre „pracovníkov“ (aspoň som nenašiel spôsob). K tomu slúžia vlastnosti (property). T.j. do zostavovacieho procesu pridáme kroky na určenie verzie a vydania a samozrejme, nastavíme vlastnosti version a release. Vlastnosti je možné nastavovať rôznymi spôsobmi, v tomto prípade je to volanie terminálu:

# Добавим определение версии из основного файла
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"
       )
)

Získané hodnoty je možné dosadiť prostredníctvom volania util.Interpolate().

# Запакуем исходники
rac_gui_build_RPM.addStep(
       steps.ShellCommand(
          command=["tar", "czf", util.Interpolate("/home/buildbot/rpmbuild/SOURCES/rac-gui-%(prop:version)s-%(prop:release)s.tar.gz"), "../rac-gui"]
       )
)

Treba poznamenať, že pretože je hostiteľ používaný aj na ručné zostavenie balíčkov, proces zostavenia prebieha cez štandardné cesty.

# Копируем spec
rac_gui_build_RPM.addStep(steps.ShellCommand(
       command=["cp", "../rac-gui/rac_gui.spec", "/home/buildbot/rpmbuild/SPECS/rac_gui.spec"]))

Na správne nastavenie čísiel vydania a verzie sa používa volanie štandardného sed, t.j. príkaz nahrádza hodnoty vo vnútri súboru spec na potrebné

# меняем версию
rac_gui_build_RPM.addStep(steps.ShellCommand(
       command=["sed", "-i", util.Interpolate("s/.*Version:.*/Version:t%(prop:version)s/"), "/home/buildbot/rpmbuild/SPECS/rac_gui.spec"]))
# меняем релиз
rac_gui_build_RPM.addStep(steps.ShellCommand(
       command=["sed", "-i", util.Interpolate("s/.*Release:.*/Release:t%(prop:release)s/"), "/home/buildbot/rpmbuild/SPECS/rac_gui.spec"]))

# запускаем процесс сборки
rac_gui_build_RPM.addStep(steps.RpmBuild(
       specfile="/home/buildbot/rpmbuild/SPECS/rac_gui.spec",
       dist='.el5',
       topdir='/home/buildbot/rpmbuild',
       builddir='/home/buildbot/rpmbuild/build',
       rpmdir='/home/buildbot/rpmbuild/RPMS',
       sourcedir='/home/buildbot/rpmbuild/SOURCES'
      )
)

Hotový zostavený balík a archív so zdrojovými kódmi skopírujeme na master. Ale je možné skopírovať priamo z pracovného súboru do svojho repozitára alebo na web.

# Скопируем файл на мастер
rac_gui_build_RPM.addStep(
       steps.FileUpload(
          workersrc=util.Interpolate("/home/buildbot/rpmbuild/RPMS/noarch/rac-gui-%(prop:version)s-%(prop:release)s.noarch.rpm"),
          masterdest=util.Interpolate("/home/buildbot/builds/rac-gui-%(prop:version)s-%(prop:release)s.noarch.rpm")
      )
)

rac_gui_build_RPM.addStep(
       steps.FileUpload(
       workersrc=util.Interpolate("/home/buildbot/rpmbuild/SOURCES/rac-gui-%(prop:version)s-%(prop:release)s.tar.gz"),
          masterdest=util.Interpolate("/home/buildbot/builds/rac-gui-%(prop:version)s-%(prop:release)s.tar.gz")
       )
)

Spustíme na masteri proces kopírovania zostavených balíkov na hosting cez FTP. Na to sa používa skript na tcl.

rac_gui_build_RPM.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.noarch.rpm"),
                util.Interpolate("--remote-file=uploads/rac-gui/rac-gui-%(prop:version)s-%(prop:release)s.noarch.rpm")]
        )
)

rac_gui_build_RPM.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.tar.gz"),
                util.Interpolate("--remote-file=uploads/rac-gui/rac-gui-%(prop:version)s-%(prop:release)s.tar.gz")]
        )
)

S RPM sme sme skončili. Teraz prejdeme na opis algoritmu zostavenia DEB balíka. Pretože procesy zostavenia balíkov pre rôzne systémy sú nezávislé, mnoho krokov sa bude opakovať.


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)
)

# Pridáme určenie verzie z hlavného súboru
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"
       )
)

# Pridáme určenie vydania z hlavného súboru
rac_gui_build_DEB.addStep(
       steps.SetPropertyFromCommand(
       command="grep release rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
       )
)

# Premenovanie spúšťacieho súboru
    rac_gui_build_DEB.addStep(steps.ShellCommand(
       command=["mv", "rac_gui.tcl", "racgui"]))

Pre RPM balík časť z nasledujúcich procedúr robí samotný rpm počas zostavenia, a sú popísané v špecifikácii, pre debian to musíme urobiť tu:

# Поменяем пути к библиотекам
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")]
        )
)

A je to s DEB hotové, teraz prejdeme na Windows!

rac_gui_build_WIN = util.BuildFactory()

rac_gui_build_WIN.addStep(steps.Git(
       repourl = 'https://bitbucket.org/svk28/rac-gui.git',
       haltOnFailure = True,
       submodules = True,
       mode='full',
       workdir='build',
       progress = True)
)

Keďže vo Windows chýba grep a sed (alebo sú?), budeme používať powershell.

# Добавим определение версии из основного файла
rac_gui_build_WIN.addStep(
       steps.SetPropertyFromCommand(
       command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'version:') -split 's')[2]",
       property="version"
       )
    )

# Добавим определение релиза из основного файла
rac_gui_build_WIN.addStep(
       steps.SetPropertyFromCommand(
       command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'release:') -split 's')[2]",
       property="release"
       )
)

# Создадим запускаемый файл
rac_gui_build_WIN.addStep(steps.ShellCommand(
       command=["c:binfreewrap.exe", "rac_gui.tcl"]))

# запакуем то, что получилось
rac_gui_build_WIN.addStep(steps.ShellCommand(
       command=["c:Program Files7-zip7z.exe", "a", "-r", util.Interpolate("..rac-gui_%(prop:version)s-%(prop:release)s.win.zip"), "..build"]))

# скопируем на мастер
rac_gui_build_WIN.addStep(
       steps.FileUpload(
       workersrc=util.Interpolate("..rac-gui_%(prop:version)s-%(prop:release)s.win.zip"),
           masterdest=util.Interpolate("/home/buildbot/builds/rac-gui_%(prop:version)s-%(prop:release)s.win.zip")
       )
)
# Скопируем файл на хостинг
rac_gui_build_WIN.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.win.zip"),
            util.Interpolate("--remote-file=uploads/rac-gui/rac-gui_%(prop:version)s-%(prop:release)s.win.zip")]
       )
)

# Тут определяем какие сборщики у нас есть
c['builders'] = [
        util.BuilderConfig(name="Rac-GUI-RPM-builder", workername='CentOS', factory=rac_gui_build_RPM),
        util.BuilderConfig(name="Rac-GUI-DEB-builder", workername='Debian-10', factory=rac_gui_build_DEB),
        util.BuilderConfig(name="Rac-GUI-WIN-builder", workername='Windows-10', factory=rac_gui_build_WIN),
]

Pre oznámenie o stave procesu zostavenia budeme používať elektronickú poštu.


c['services'] = []

template=u'''
    <h4>Stav zostavenia: {{ summary }}</h4>
    <p> Použitý pracovník: {{ workername }}</p>
    {% for step in build['steps'] %}
    <p> {{ step['name'] }}: {{ step['result'] }}</p>
    {% endfor %}
    <p><b> -- The Buildbot</b></p>
    '''

mailNotifier = reporters.MailNotifier(fromaddr="builder@domain.ru",
             sendToInterestedUsers=False,
             mode=('all'),
             extraRecipients=["admin@domain.ru"],
             relayhost="mail.domain.ru",
             smtpPort=587,
             smtpUser="builder@domain.ru",
             smtpPassword="******",
             messageFormatter=reporters.MessageFormatter(
                                 template=template, template_type='html',
                                 wantProperties=True, wantSteps=True))

c['services'].append(mailNotifier)

# Hlavné nastavenia majstra
c['title'] = "Proces zostavovania"
c['titleURL'] = "http://vm-srv-build1:80/"
c['buildbotURL'] = "http://vm-srv-build1/"
c['www'] = dict(port=80,
                plugins=dict(waterfall_view={}, console_view={}, grid_view={}))
c['db'] = {
       'db_url' : "sqlite://state.sqlite"
}

Uložíme súbor a môžeme skúsiť spustiť službu majstra:

systemctl restart buildbot-master

V logu skontrolujeme, že s konfiguráciou je všetko v poriadku a všetko funguje v normálnom režime. Všetci naši pracovníci sa teraz musia pripojiť, čo bude v logu »»'/home/buildbot/master/twistd.log'»» šťastne oznámené:

 2019-07-24 16:50:35+0300 [-] Načítanie buildbot.tac...
 2019-07-24 16:50:35+0300 [-] Načítané.
 2019-07-24 16:50:35+0300 [-] twistd 19.2.1 (\/usr\/bin\/python3.6 3.6.8) sa spúšťa.
 2019-07-24 16:50:35+0300 [-] Typ reaktora: twisted.internet.epollreactor.EPollReactor.
 2019-07-24 16:50:35+0300 [-] Spúšťam BuildMaster -- buildbot.version: 2.3.1
 2019-07-24 16:50:35+0300 [-] Načítanie konfigurácie z '\/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 a novšie] `buildbotNetUsageData` nie je nakonfigurované a predvolene je nastavené na základné.
 Tento parameter pomáha tímu vývoja buildbota pochopiť základňu inštalácie.
 Nebudú zhromaždené žiadne osobné údaje.
 Iba informácie o verzii inštalačného softvéru a používaní pluginov budú odoslané.
 Môžete sa 'odhlásiť' nastavením tejto premennej na None.
 Alebo sa 'prihlásiť' pre viac informácií nastavením na "full".

 2019-07-24 16:50:36+0300 [-] Nastavujem databázu s URL 'sqlite:\/state.sqlite'
 2019-07-24 16:50:36+0300 [-] Nastavujem režim žurnálu databázy na 'wal'
 2019-07-24 16:50:36+0300 [-] pridávam 1 novú službu, odstraňujem 0
 2019-07-24 16:50:36+0300 [-] pridávam 1 nový zdroj zmien, odstraňujem 0
 2019-07-24 16:50:36+0300 [-] gitpoller: používam pracovnú zložku '\/home\/buildbot\/master\/gitpoller-work'
 2019-07-24 16:50:36+0300 [-] pridávam 3 nových staviteľov, odstraňujem 0
 2019-07-24 16:50:36+0300 [-] pridávam 1 nový plánovač, odstraňujem 0
 2019-07-24 16:50:36+0300 [-] inicializujem www plugin 'waterfall_view'
 2019-07-24 16:50:36+0300 [-] inicializujem www plugin 'console_view'
 2019-07-24 16:50:36+0300 [-] inicializujem www plugin 'grid_view'
 2019-07-24 16:50:36+0300 [-] POZNÁMKA: www plugin 'sitenav' je nainštalovaný, ale nie je nakonfigurovaný
 2019-07-24 16:50:36+0300 [-] inicializujem www plugin 'waterfall_view'
 2019-07-24 16:50:36+0300 [-] inicializujem www plugin 'console_view'
 2019-07-24 16:50:36+0300 [-] inicializujem www plugin 'grid_view'
 2019-07-24 16:50:36+0300 [-] POZNÁMKA: www plugin 'sitenav' je nainštalovaný, ale nie je nakonfigurovaný
 2019-07-24 16:50:36+0300 [-] BuildbotSite sa spúšťa na porte 80
 2019-07-24 16:50:36+0300 [-] Spúšťam továreň 
 2019-07-24 16:50:36+0300 [-] pridávam 3 nových pracovníkov, odstraňujem 0
 2019-07-24 16:50:36+0300 [-] PBServerFactory sa spúšťa na porte 4000
 2019-07-24 16:50:36+0300 [-] Spúšťam továreň 
 2019-07-24 16:50:37+0300 [-] BuildMaster beží
 2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: odosielam {'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] pracovník 'CentOS' sa pripája z IPv4Address(type='TCP', host='127.0.0.1', port=37332)
 2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Získané informácie o pracovníkovi z 'CentOS'
 2019-07-24 16:50:37+0300 [-] bot pripojený
 2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Pracovník CentOS pripojený k Rac-GUI-RPM-builder
 2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: buildbot.net povedal: ok
 2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] pracovník 'Windows-10' sa pripája z IPv4Address(type='TCP', host='192.168.5.145', port=49831)
 2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] Získané informácie o pracovníkovi z 'Windows-10'
 2019-07-24 16:50:40+0300 [-] bot pripojený
 2019-07-24 16:50:40+0300 [Broker,1,192.168.55.15] Pracovník Windows-10 pripojený k Rac-GUI-WIN-builder
 2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] pracovník 'Debian-10' sa pripája z IPv4Address(type='TCP', host='192.168.5.9', port=44430)
 2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Získané informácie o pracovníkovi z 'Debian-10'
 2019-07-24 16:50:41+0300 [-] bot pripojený
 2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Pracovník Debian-10 pripojený k Rac-GUI-DEB-builder

Na tomto procese je nastavenie dokončené. Aktuálny stav môžete skontrolovať prostredníctvom webového rozhrania. Kde si môžete tiež pozrieť chyby kompilácie, reštartovať zaseknutý proces, ak niečo nešlo podľa plánu, atď.

Hneď po spustení našich pracovníkov môžete pozrieť cez menu „Builds“ -> „Workers“

Buildbot v príkladoch

Po prvom procese kompilácie (t.j. po zmenách v Git repozitári) sa na prvej stránke objaví stav procesov.

Buildbot v príkladoch

Ak kliknete myšou na potrebný riadok, otvorí sa stránka s aktuálnym stavom tohto procesu, kde môžete vidieť, čo sa deje, aké sú chyby, atď.

Buildbot v príkladoch

Celkové nastavenie majstra môžete získať tu

import os, re
from buildbot.plugins import steps, util, schedulers, worker, changes, reporters

c= BuildmasterConfig ={}

c['workers'] = [ worker.Worker('CentOS', '123456'), worker.Worker('Debian-10', '123456'), worker.Worker('Windows-10', '123456')]
c['protocols'] = {'pb': {'port': 4000}} 

c['change_source'] = []
c['change_source'].append(changes.GitPoller(
    repourl = 'https://bitbucket.org/svk28/rac-gui.git',
    project = 'Rac-GUI',
    branches = True,
    pollInterval = 600
    ))

# Služba spustenia zostavy
c['schedulers'] = []
c['schedulers'].append(schedulers.SingleBranchScheduler(
    name="Rac-GUI-schedulers",
    change_filter=util.ChangeFilter(branch='master'),
    builderNames=["Rac-GUI-RPM-builder", "Rac-GUI-DEB-builder", "Rac-GUI-WIN-builder"],
    properties = {'owner': 'admin'}
    ))
@util.renderer
def get_name_version_release(props):
    prog_name = "rac-gui"
    prog_version = "1.0.3"
    prog_release = "3"

    return {
    "prog_name": prog_name
    #"prog_version": prog_version,
    #"prog_release": prog_release
}

rac_gui_build_RPM = util.BuildFactory()

rac_gui_build_RPM.addStep(steps.Git(
    repourl = 'https://bitbucket.org/svk28/rac-gui.git',
    workdir = 'rac-gui',
    haltOnFailure = True,
    submodules = True,
    mode='full',
    progress = True)
    )

# Pridáme určenie verzie z hlavného súboru
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"
    )
)

# Pridáme určenie vydania z hlavného súboru
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"
    )
)

rac_gui_build_RPM.addStep(steps.ShellCommand(
    command=["tar", "czf", util.Interpolate("\/home\/buildbot\/rpmbuild\/SOURCES\/rac-gui-%(prop:version)s-%(prop:release)s.tar.gz"), "..\/rac-gui"]))

rac_gui_build_RPM.addStep(steps.ShellCommand(
    command=["cp", "..\/rac-gui\/rac_gui.spec", "\/home\/buildbot\/rpmbuild\/SPECS\/rac_gui.spec"]))

rac_gui_build_RPM.addStep(steps.ShellCommand(
    command=["sed", "-i", util.Interpolate("s\/.*Version:.*\/Version:t%(prop:version)s\/"), "\/home\/buildbot\/rpmbuild\/SPECS\/rac_gui.spec"]))

rac_gui_build_RPM.addStep(steps.ShellCommand(
    command=["sed", "-i", util.Interpolate("s\/.*Release:.*\/Release:t%(prop:release)s\/"), "\/home\/buildbot\/rpmbuild\/SPECS\/rac_gui.spec"]))

rac_gui_build_RPM.addStep(steps.RpmBuild(
    specfile="\/home\/buildbot\/rpmbuild\/SPECS\/rac_gui.spec",
    dist='.el5',
    topdir='\/home\/buildbot\/rpmbuild',
    builddir='\/home\/buildbot\/rpmbuild\/build',
    rpmdir='\/home\/buildbot\/rpmbuild\/RPMS',
    sourcedir='\/home\/buildbot\/rpmbuild\/SOURCES'
    ))

# Skopírujeme súbor na majstra
rac_gui_build_RPM.addStep(
    steps.FileUpload(
    workersrc=util.Interpolate("\/home\/buildbot\/rpmbuild\/RPMS\/noarch\/rac-gui-%(prop:version)s-%(prop:release)s.noarch.rpm"),
        masterdest=util.Interpolate("\/home\/buildbot\/builds\/rac-gui-%(prop:version)s-%(prop:release)s.noarch.rpm")
    )
)

rac_gui_build_RPM.addStep(
    steps.FileUpload(
    workersrc=util.Interpolate("\/home\/buildbot\/rpmbuild\/SOURCES\/rac-gui-%(prop:version)s-%(prop:release)s.tar.gz"),
        masterdest=util.Interpolate("\/home\/buildbot\/builds\/rac-gui-%(prop:version)s-%(prop:release)s.tar.gz")
    )
)

rac_gui_build_RPM.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.noarch.rpm"),
     util.Interpolate("--remote-file=uploads\/rac-gui\/rac-gui-%(prop:version)s-%(prop:release)s.noarch.rpm")]
    )
)

rac_gui_build_RPM.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.tar.gz"),
     util.Interpolate("--remote-file=uploads\/rac-gui\/rac-gui-%(prop:version)s-%(prop:release)s.tar.gz")]
    )
)
####################################
##      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)
    )

# Pridáme určenie verzie z hlavného súboru
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"
    )
)

# Pridáme určenie vydania z hlavného súboru
rac_gui_build_DEB.addStep(
    steps.SetPropertyFromCommand(
    command="grep release rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
    )
)

# Premenujeme spúšťací súbor
rac_gui_build_DEB.addStep(steps.ShellCommand(
    command=["mv", "rac_gui.tcl", "racgui"]))

# Zmeníme cesty k knižniciam
rac_gui_build_DEB.addStep(steps.ShellCommand(
    command=["sed", "-i", "s+^set dir(lib)+set dir(lib) \/usr\/share\/rac-gui\/lib ;#+g", "racgui"]))

# Zmeníme cesty k súborom
rac_gui_build_DEB.addStep(steps.ShellCommand(
    command=["sed", "-i", "s+[pwd]+\/usr\/share\/rac-gui+g", "racgui"]))

# Zaarchivujeme zdrojové kódy
rac_gui_build_DEB.addStep(steps.ShellCommand(
    command=["tar", "czf", util.Interpolate("..\/rac-gui_%(prop:version)s.orig.tar.gz"), "."]))

# Zostavíme balík
rac_gui_build_DEB.addStep(steps.ShellCommand(
    command=["dpkg-buildpackage"]))

# Skopírujeme súbor na majstra
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")]
    )
)
############################################
#       WIN
############################################

rac_gui_build_WIN = util.BuildFactory()

rac_gui_build_WIN.addStep(steps.Git(
    repourl = 'https://bitbucket.org/svk28/rac-gui.git',
    haltOnFailure = True,
    submodules = True,
    mode='full',
    workdir='build',
    progress = True)
    )

# Pridáme určenie verzie z hlavného súboru
rac_gui_build_WIN.addStep(
    steps.SetPropertyFromCommand(
    command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'version:') -split 's')[2]",
    property="version"
    )
)

# Pridáme určenie vydania z hlavného súboru
rac_gui_build_WIN.addStep(
    steps.SetPropertyFromCommand(
    command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'release:') -split 's')[2]",
    property="release"
    )
)

# Vytvoríme spúšťací súbor
rac_gui_build_WIN.addStep(steps.ShellCommand(
    command=["c:binfreewrap.exe", "rac_gui.tcl"]))

# Zabalíme to, čo sme získali
rac_gui_build_WIN.addStep(steps.ShellCommand(
    command=["c:Program Files7-zip7z.exe", "a", "-r", util.Interpolate("..rac-gui_%(prop:version)s-%(prop:release)s.win.zip"), "..build"]))

# Skopírujeme na majstra
rac_gui_build_WIN.addStep(
    steps.FileUpload(
    workersrc=util.Interpolate("..rac-gui_%(prop:version)s-%(prop:release)s.win.zip"),
        masterdest=util.Interpolate("\/home\/buildbot\/builds\/rac-gui_%(prop:version)s-%(prop:release)s.win.zip")
    )
)

# Skopírujeme súbor na hosting
rac_gui_build_WIN.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.win.zip"),
     util.Interpolate("--remote-file=uploads\/rac-gui\/rac-gui_%(prop:version)s-%(prop:release)s.win.zip")]
    )
)

c['builders'] = [
        util.BuilderConfig(name="Rac-GUI-RPM-builder", workername='CentOS', factory=rac_gui_build_RPM),
        util.BuilderConfig(name="Rac-GUI-DEB-builder", workername='Debian-10', factory=rac_gui_build_DEB),
        util.BuilderConfig(name="Rac-GUI-WIN-builder", workername='Windows-10', factory=rac_gui_build_WIN),
]

c['services'] = []

template=u'''
<h4>Stav zostavenia: {{ summary }}</h4>
<p> Použitý pracovník: {{ workername }}</p>
{% for step in build['steps'] %}
<p> {{ step['name'] }}: {{ step['result'] }}</p>
{% endfor %}
<p><b> -- The Buildbot</b></p>
'''

mailNotifier = reporters.MailNotifier(fromaddr="112@icvibor.ru",
          sendToInterestedUsers=False,
          mode=('all'),
          extraRecipients=["my@domain.local"],
          relayhost="mail.domain.local",
          smtpPort=587,
          smtpUser="buildbot@domain.local",
          smtpPassword="**********",
          messageFormatter=reporters.MessageFormatter(
                                 template=template, template_type='html',
                                 wantProperties=True, wantSteps=True))

c['services'].append(mailNotifier)

c['title'] = "Proces budovania"
c['titleURL'] = "http://vm-srv-build1:80/"

c['buildbotURL'] = "http://vm-srv-build1/"

c['www'] = dict(port=80,
                plugins=dict(waterfall_view={}, console_view={}, grid_view={}))
c['db'] = {
    'db_url' : "sqlite:///state.sqlite"
}

Materiály

Pri príprave článku boli použité nasledujúce materiály:

Zdroj: habr.com

Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Kúpte si spoľahlivý hosting pre webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster