Potřeboval jsem nastavit proces sestavení a dodání balíčků programů na web ze Git-repozitáře. A když jsem nedávno viděl článek na Habré o buildbote (odkaz na konci), rozhodl jsem se ho pro toto zkusit a použít.
Jelikož je buildbot distribuovaný systém, bude logické vytvořit samostatný build host pro každou architekturu a operační systém. V našem případě to budou LXC kontejnery (pro Linux) a qemu (pro Windows):
- vm-srv-build1 — CentOS 7, zde bude buildbot master a jeden z workerů.
- vm-srv-build2 — Debian 10, pro sestavení DEB balíčků.
- vm-srv-build3 — Windows 10, pro sestavení, to asi chápete.
Budeme sestavovat — grafické rozhraní k 1C rac pro správu clusteru serverů. Pro Linux budou použity standardní nástroje pro každou OS, pro sestavení exe souboru pro Windows z tcl skriptu se používá .
Instalace
GNU/Linux
K dispozici je dostatečná dokumentace a instalace je snadná. ,A nevytváří zvláštní problémy:
Pro master:
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-dateutilPro „workery“ stačí toto:
pip3 install buildbot-workerSamozřejmě, bylo by správnější vybudovat balíčky pro každý OS, ale to není náplní tohoto článku. Také vynecháme popis nastavení kontejnerů pro práci, jen zmíním, že používám ProxMox VE. A bude také potřeba nainstalovat balíčky pro každou os potřebné pro sestavení (centos: rpmdevtools atd.; debian: build-essential, dh-make, pbuilder atd.)
Sestavení projektů a služby buildbot budou spuštěny pod jménem neprivilegovaného uživatele, proto je nutné ho vytvořit na všech hostech, které se procesu účastní:
adduser buildbotDále nastavíme automatické spuštění služeb, a to na každém z hostů (kontejnerů):
Systemd jednotka pro spuštění masteru:
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.targeta „workera“
touch /etc/systemd/buildbot-worker.service
[Unit]
Description=BuildBot worker service
After=network.target
[Service]
User=buildbot
Group=buildbot
WorkingDirectory=/home/buildbot/worker
ExecStart=/usr/local/bin/buildbot-worker start --nodaemon
[Install]
WantedBy=buildbot-master.serviceJelikož všechny skripty (v našem případě) leží v /usr/local/, je potřeba zapsat cestu k nim do proměnných prostředí:
nano /root/.bash_profile
PATH=$PATH:$HOME/.local/bin:$HOME/bin:/usr/local/binPoté můžete vytvořit infrastrukturu adresářů pro "pracovníky" (na všech hostech), za tímto účelem se registrujte jako uživatel buildbot a spusťte následující příkazy:
Na prvním hostu vm-srv-build1:
su - buildbot
mkdir /home/buildbot/worker
cd ~
buildbot-worker create-worker --umask=0o22 --keepalive=60 worker vm-srv-build1:4000 CentOS 123456Na druhém hostu 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 123456Na pracovních hostech lze službu buildbot-worker spustit
systemctl start buildbot-workerMS Windows
Jako "pracovníka" pro sestavení pod Windows bude použita virtuální stroj s poslední verzí Win10.
K práci bude potřeba:
- Pro instalaci různých věcí v Pythonu bylo nutné stáhnout
- 7Zip
Poté, co se nainstaluje všechno výše uvedené, můžeme nainstalovat i samotný buildbot:
pip install buildbot-workerVytvoříme pracovní adresář
md c:workerA spustíme
buildbot-worker start c:workerPokud všechno funguje (viz log c:workertwistd.log), můžeme našeho "pracovníka" zaregistrovat jako službu, přidáním položky do registru s pracovním adresářem (příkazy se provádějí v PowerShellu spuštěném jako správce):
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 službu lze spouštět
Start-Service buildbotS "pracovníky" je to vše, dále je není potřeba upravovat, veškerá správa probíhá z masteru.
Nastavení masteru
Nejprve vytvoříme infrastrukturu pro mastera (na hlavním hostu), k tomu se registrujeme jako uživatel buildbot a provedeme následující příkazy:
su - buildbot
mkdir /home/buildbot/master
cd ~
buildbot create-master masterPro hotové balíčky vytvoříme adresář builds
mkdir /home/buildbot/buildsV adresáři /home/buildbot/master/ byl vytvořen soubor master.cfg. Tento soubor představuje kód v Pythonu a obsahuje popis všech mechanismů funkce systému, s ním budeme dále pracovat.
nano /home/buildbot/master/master.cfgimport os, re
from buildbot.plugins import steps, util, schedulers, worker, changes, reporters
c= BuildmasterConfig ={}
# Popis 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čení, jaký repozitář má master sledovat
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 spouštění sestavení
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
# Sestavení RPM balíčku
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)
)Pro automatizaci sestavení balíčků různých verzí, aby nebylo nutné sahat do kódu souboru master.cfg, byly do hlavního skriptu programu rac_gui.tcl přidány řádky s aktuální verzí a vydáním:
######################################################
# Rac GUI
...
# version: 1.0.3
# release: 1A na základě těchto řádků buildbot bude číslo balíčků. Pro získání dat se používá volání консольного grep. V buildbotu není možné jednoduše definovat proměnné pro „pracovníky“ (aspoň jsem nenalezl, jak). K tomu slouží vlastnosti (property). Tedy do sestavovacího procesu přidáme kroky pro určení verze a vydání a tím pádem nastavíme vlastnosti version a release. Vlastnosti lze nastavovat různými způsoby, v tomto případě je to volání консольной команды:
# Добавим определение версии из основного файла
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 lze vložit pomocí volání 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"]
)
)Je třeba poznamenat, že protože se host používá i pro ruční sestavení balíčků, projde sestavení standardními cestami.
# Копируем spec
rac_gui_build_RPM.addStep(steps.ShellCommand(
command=["cp", "../rac-gui/rac_gui.spec", "/home/buildbot/rpmbuild/SPECS/rac_gui.spec"]))Pro správné nastavení čísel vydání a verze se používá standardní sed, tedy příkaz nahrazuje hodnoty uvnitř spec-souboru na požadované.
# меняем версию
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ý sestavený balíček a archiv se zdrojovými kódy zkopírujeme na master. Ale lze také ihned kopírovat ze pracovního souboru do svého repozitáře nebo 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 masteru proces kopírování sestavených balíčků na hosting přes ftp. K tomu se používá 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 jsme skončili. Teď přejdeme k popisu algoritmu pro sestavení DEB balíčku. Protože procesy sestavování balíčků pro různé systémy jsou nezávislé na sobě, mnohé kroky se budou opakovat.
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)
)
# Přidáme určení verze z hlavního souboru
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"
)
)
# Přidáme určení vydání z hlavního souboru
rac_gui_build_DEB.addStep(
steps.SetPropertyFromCommand(
command="grep release rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
)
)
# Přejmenujeme spouštěcí soubor
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["mv", "rac_gui.tcl", "racgui"]))Pro RPM balíček část následujících procedur provádí samotné rpm při sestavování a jsou popsány uvnitř specifikace, pro debian to musíme dělat zde:
# Поменяем пути к библиотекам
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 s DEB je hotovo, teď 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)
)Protože ve Windows standardně není grep a sed (nebo jsou?), budeme používat 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),
]Pro oznámení o stavu procesu sestavení budeme používat elektronickou poštu
c['services'] = []
template=u'''
<h4>Stav sestavení: {{ 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.cz",
sendToInterestedUsers=False,
mode=('all'),
extraRecipients=["admin@domain.cz"],
relayhost="mail.domain.cz",
smtpPort=587,
smtpUser="builder@domain.cz",
smtpPassword="******",
messageFormatter=reporters.MessageFormatter(
template=template, template_type='html',
wantProperties=True, wantSteps=True))
c['services'].append(mailNotifier)
# Hlavní nastavení masteru
c['title'] = "Proces sestavení"
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žte soubor a můžeme zkusit spustit službu master:
systemctl restart buildbot-masterV logu zkontrolujeme, že je s konfigurací vše v pořádku a všechno funguje v normálním režimu. Všichni naši pracovníci by se nyní měli připojit, což bude v logu »»’/home/buildbot/master/twistd.log»»’ šťastně oznámeno:
2019-07-24 16:50:35+0300 [-] Načítání buildbot.tac...
2019-07-24 16:50:35+0300 [-] Načteno.
2019-07-24 16:50:35+0300 [-] twistd 19.2.1 (\/usr\/bin\/python3.6 3.6.8) se spouští.
2019-07-24 16:50:35+0300 [-] Třída reaktoru: twisted.internet.epollreactor.EPollReactor.
2019-07-24 16:50:35+0300 [-] Spouští se BuildMaster -- buildbot.version: 2.3.1
2019-07-24 16:50:35+0300 [-] Načítání konfigurace 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 později] `buildbotNetUsageData` není nakonfigurováno a je ve výchozím nastavení základní.
Tento parametr pomáhá týmu vývojářů Buildbotu pochopit instalační základnu.
Nebudou shromažďovány žádné osobní informace.
Odesílány jsou pouze informace o verzi instalačního softwaru a použití pluginů.
Můžete se `odhlásit` nastavením této proměnné na None.
Nebo `přihlásit` pro více informací nastavením na "full".
2019-07-24 16:50:36+0300 [-] Nastavování databáze s URL 'sqlite:\/state.sqlite'
2019-07-24 16:50:36+0300 [-] Nastavení režimu žurnálu databáze na 'wal'
2019-07-24 16:50:36+0300 [-] Přidání 1 nové služby, odstranění 0
2019-07-24 16:50:36+0300 [-] Přidání 1 nového change_sources, odstranění 0
2019-07-24 16:50:36+0300 [-] gitpoller: používání pracovního adresáře '\/home\/buildbot\/master\/gitpoller-work'
2019-07-24 16:50:36+0300 [-] Přidání 3 nových builderů, odstranění 0
2019-07-24 16:50:36+0300 [-] Přidání 1 nového plánovače, odstranění 0
2019-07-24 16:50:36+0300 [-] Inicializace www pluginu 'waterfall_view'
2019-07-24 16:50:36+0300 [-] Inicializace www pluginu 'console_view'
2019-07-24 16:50:36+0300 [-] Inicializace www pluginu 'grid_view'
2019-07-24 16:50:36+0300 [-] POZNÁMKA: www plugin 'sitenav' je nainstalován, ale není nakonfigurován
2019-07-24 16:50:36+0300 [-] Inicializace www pluginu 'waterfall_view'
2019-07-24 16:50:36+0300 [-] Inicializace www pluginu 'console_view'
2019-07-24 16:50:36+0300 [-] Inicializace www pluginu 'grid_view'
2019-07-24 16:50:36+0300 [-] POZNÁMKA: www plugin 'sitenav' je nainstalován, ale není nakonfigurován
2019-07-24 16:50:36+0300 [-] BuildbotSite spouští na 80
2019-07-24 16:50:36+0300 [-] Spouští se továrna <buildbot.www.service.BuildbotSite objekt na 0x7fe31c2657b8>
2019-07-24 16:50:36+0300 [-] Přidání 3 nových pracovníků, odstranění 0
2019-07-24 16:50:36+0300 [-] PBServerFactory se spouští na 4000
2019-07-24 16:50:36+0300 [-] Spouští se továrna <twisted.spread.pb.PBServerFactory objekt na 0x7fe31c147470>
2019-07-24 16:50:37+0300 [-] BuildMaster běží
2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: odesílání {'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' se připojuje z IPv4Address(type='TCP', host='127.0.0.1', port=37332)
2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Dostali jsme informace o pracovníkovi z 'CentOS'
2019-07-24 16:50:37+0300 [-] bot se připojil
2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Pracovník CentOS připojen k Rac-GUI-RPM-builder
2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: buildbot.net řekl: ok
2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] pracovník 'Windows-10' se připojuje z IPv4Address(type='TCP', host='192.168.5.145', port=49831)
2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] Dostali jsme informace o pracovníkovi z 'Windows-10'
2019-07-24 16:50:40+0300 [-] bot se připojil
2019-07-24 16:50:40+0300 [Broker,1,192.168.55.15] Pracovník Windows-10 připojen k Rac-GUI-WIN-builder
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] pracovník 'Debian-10' se připojuje z IPv4Address(type='TCP', host='192.168.5.9', port=44430)
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Dostali jsme informace o pracovníkovi z 'Debian-10'
2019-07-24 16:50:41+0300 [-] bot se připojil
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Pracovník Debian-10 připojen k Rac-GUI-DEB-builderTímto je proces nastavení dokončen. Aktuální stav lze zobrazit přes webové rozhraní, kde je možné také vidět chyby zkompilace, restartovat visící proces, pokud něco nešlo podle plánu, atd.
Hned po spuštění našich pracovních serverů lze zkontrolovat přes menu „Builds“ -> „Workers“

Poté, co proběhne první proces kompilace (tj. jakákoliv změna v Git repozitáři), na první stránce se zobrazí stav procesů.

Když kliknete myší na potřebný řádek, otevře se stránka s aktuálním stavem daného procesu, kde uvidíte, co se děje, jaké chyby se vyskytly atd.

Celý konfigurační soubor můžete vzít zde
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 spouštění sestavení
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)
)
# Přidáme určení verze z hlavního souboru
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"
)
)
# Přidáme určení vydání z hlavního souboru
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'
))
# Zkopírujeme soubor na master
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)
)
# Přidáme určení verze z hlavního souboru
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"
)
)
# Přidáme určení vydání z hlavního souboru
rac_gui_build_DEB.addStep(
steps.SetPropertyFromCommand(
command="grep release rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
)
)
# Přejmenujeme spuštěný soubor
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["mv", "rac_gui.tcl", "racgui"]))
# Změníme cesty k knihovnám
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["sed", "-i", "s+^set dir(lib)+set dir(lib) /usr/share/rac-gui/lib ;#+g", "racgui"]))
# Změníme cesty k souborům
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["sed", "-i", "s+[pwd]+/usr/share/rac-gui+g", "racgui"]))
# Zarchivujeme zdrojové kódy
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["tar", "czf", util.Interpolate("../rac-gui_%(prop:version)s.orig.tar.gz"), "."]))
# Sestavíme balíček
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["dpkg-buildpackage"]))
# Zkopírujeme soubor na master
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)
)
# Přidáme určení verze z hlavního souboru
rac_gui_build_WIN.addStep(
steps.SetPropertyFromCommand(
command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'version:') -split 's')[2]",
property="version"
)
)
# Přidáme určení vydání z hlavního souboru
rac_gui_build_WIN.addStep(
steps.SetPropertyFromCommand(
command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'release:') -split 's')[2]",
property="release"
)
)
# Vytvoříme spustitelný soubor
rac_gui_build_WIN.addStep(steps.ShellCommand(
command=["c:binfreewrap.exe", "rac_gui.tcl"]))
# Zabalíme to, co jsme dostali
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"]))
# Zkopírujeme na master
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")
)
)
# Zkopírujeme soubor 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 sestavení: {{ 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 budování"
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
Při přípravě článku byly použity následující materiály:
- A také dokumentace k produktu
Zdroj: habr.com
