A trebuit să configurez procesul de construire și livrare pe site a pachetelor de software dintr-un depozit Git. Și văzând, nu de mult aici pe Habr un articol despre buildbot (linkul la sfârșit), am decis să-l încerc și să-l aplic.
Fiindcă buildbot este un sistem distribuit, ar fi logic să facem un host de construire separat pentru fiecare arhitectură și sistem de operare. În cazul nostru, acestea vor fi containere LXC (în cazul Linux) și qemu (în cazul Windows):
- vm-srv-build1 — centos 7, aici va fi masterul buildbot și unul dintre lucrători
- vm-srv-build2 — debian 10, pentru construirea pachetelor DEB
- vm-srv-build3 — windows 10, pentru construirea, știți pentru ce
Vom construi — interfața grafică pentru 1C rac pentru gestionarea clusterului de servere. Pentru Linux se vor folosi instrumentele standard pentru fiecare OS, pentru construcția fișierului exe pentru Windows din scriptul tcl se folosește .
Instalare
GNU/Linux
Există suficientă documentație online pentru instalare ,. De asemenea, nu creează probleme deosebite:
Pentru 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-dateutilPentru «workeri», acest lucru este suficient:
pip3 install buildbot-workerDesigur, ar fi mai corect să construim pachete pentru fiecare OS, dar asta nu face parte din articol. De asemenea, vom omite descrierea configurării containerelor pentru muncă, voi menționa doar că folosesc ProxMox VE. Și va fi necesar să instalăm pachetele necesare pentru fiecare sistem de operare pentru construire (centos: rpmdevtools etc.; debian: build-essential, dh-make, pbuilder etc.)
Construirea proiectelor și serviciile buildbot vor fi lansate în numele unui utilizator neprivilegiat, așa că trebuie să-l creăm pe toate hosturile implicate în proces:
adduser buildbotApoi, vom configura lansarea automată a serviciilor, în consecință, pe fiecare dintre hosturi (containere):
Unitatea Systemd pentru lansarea masterului:
touch /etc/systemd/buildbot-master.service
[Unit]
Description=Serviciul master BuildBot
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și «workerul»
touch /etc/systemd/buildbot-worker.service
[Unit]
Description=Serviciul worker BuildBot
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.serviceDeoarece toate scripturile (în cazul nostru) se află în /usr/local/, este necesar să specificăm calea către ele în variabilele de mediu:
nano /root/.bash_profile
PATH=$PATH:$HOME/.local/bin:$HOME/bin:/usr/local/binDupă aceasta, se poate crea infrastructura directorilor pentru „lucrători” (pe toate gazdele), pentru aceasta se înregistrează sub utilizatorul buildbot și se execută următoarele comenzi:
Pe prima gazdă vm-srv-build1:
su - buildbot
mkdir /home/buildbot/worker
cd ~
buildbot-worker create-worker --umask=0o22 --keepalive=60 worker vm-srv-build1:4000 CentOS 123456Pe a doua gazdă 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 123456Pe gazdele-lucrători serviciul buildbot-worker poate fi pornit
systemctl start buildbot-workerMS Windows
Ca „lucrător” pentru construirea pe Windows, va fi utilizată o mașină virtuală cu cea mai recentă versiune Win10.
Pentru a funcționa, este nevoie de:
- Pentru a instala diversele biblioteci în Python, a fost necesar să descărcați
- 7Zip
După ce tot ce este menționat mai sus se instalează, se poate instala și buildbot în sine:
pip install buildbot-workerSă creăm directorul de lucru
md c:workerȘi să pornim
buildbot-worker start c:workerDacă totul funcționează (vezi log-ul c:workertwistd.log), atunci putem înregistra „lucrătorul” nostru ca serviciu, adăugând în registrul de sistem un element cu directorul de lucru (comenzile se execută în PowerShell deschis ca administrator):
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
Și se poate porni serviciul
Start-Service buildbotCu „lucrătorii” aici se termină, apoi nu se mai intervine, toată gestionarea se face din master.
Configurarea masterului
Pentru început, să creăm infrastructura pentru master (pe gazda principală), pentru aceasta se înregistrează sub utilizatorul buildbot și se execută următoarele comenzi:
su - buildbot
mkdir /home/buildbot/master
cd ~
buildbot create-master masterPentru pachetele gata, să creăm un director builds
mkdir /home/buildbot/buildsÎn directorul /home/buildbot/master/ a fost creat fișierul master.cfg. Acest fișier reprezintă cod Python și conține descrierea tuturor mecanismelor de funcționare ale sistemului, cu el vom lucra în continuare.
nano /home/buildbot/master/master.cfgimport os, re
from buildbot.plugins import steps, util, schedulers, worker, changes, reporters
c= BuildmasterConfig ={}
# Descrierea lucrătorilor noștri.
c['workers'] = [ worker.Worker('CentOS', '123456'), worker.Worker('Debian-10', '123456'), worker.Worker('Windows-10', '123456')]
c['protocols'] = {'pb': {'port': 4000}}
# Indică maestrului ce depozit să monitorizeze
c['change_source'] = []
c['change_source'].append(changes.GitPoller(
repourl = 'https://bitbucket.org/svk28/rac-gui.git',
project = 'Rac-GUI',
branches = True,
pollInterval = 60
)
)
# Serviciul de lansare a construcției
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
# Construirea pachetului RPM
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)
)Pentru automatizarea construcției pachetelor de versiuni diferite, pentru a nu fi necesar să modificăm codul fișierului master.cfg, au fost adăugate în principalul script al programului rac_gui.tcl linii cu versiunea și release-ul curente:
######################################################
# Rac GUI
...
# version: 1.0.3
# release: 1Și pe baza acestor linii, buildbot va număra pachetele. Pentru extragerea datelor, se folosește apelul consolei grep. În buildbot, nu se pot defini variabile pentru „lucrători” (cel puțin, eu nu am găsit cum). Acest lucru se realizează prin proprietăți (property). Adică, în procesul de construcție, adăugăm pașii pentru determinarea versiunii și release-ului și, respectiv, stabilim proprietățile version și release. Proprietățile pot fi setate în diverse moduri, în acest caz fiind apelul unei comenzi console:
# Добавим определение версии из основного файла
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"
)
)Valorile obținute pot fi inserate prin apelul 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"]
)
)Aici trebuie menționat că, deoarece gazda este folosită și pentru construcția manuală a pachetelor, construcția va avea loc pe căile standard.
# Копируем spec
rac_gui_build_RPM.addStep(steps.ShellCommand(
command=["cp", "../rac-gui/rac_gui.spec", "/home/buildbot/rpmbuild/SPECS/rac_gui.spec"]))Pentru a stabili numerele corecte de release și versiune, se folosește apelul standard sed, adică comanda înlocuiește valorile din fișierul spec cu cele necesare
# меняем версию
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'
)
)Pachetul final construit și arhiva cu sursele sunt copiate pe master. Dar se poate copia și direct de pe lucrător în propriul depozit sau pe site.
# Скопируем файл на мастер
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")
)
)Vom lansa pe master procesul de copiere a pachetelor construite pe hosting prin ftp. Pentru aceasta se folosește în 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")]
)
)Am terminat cu RPM. Acum să trecem la descrierea algoritmului de construire a pachetului DEB. Deoarece procesele de construire a pachetelor pentru diferite sisteme sunt independente una de cealaltă, multe dintre pași se vor repeta.
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)
)
# Să adăugăm definiția versiunii din fișierul principal
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"
)
)
# Să adăugăm definiția release-ului din fișierul principal
rac_gui_build_DEB.addStep(
steps.SetPropertyFromCommand(
command="grep release rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
)
)
# Să redenumim fișierul executabil
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["mv", "rac_gui.tcl", "racgui"]))Pentru pachetul RPM, o parte din procedurile de mai jos sunt realizate de rpm în timpul construirii și sunt descrise în interiorul spec-ului, în timp ce pentru Debian trebuie să le facem aici:
# Поменяем пути к библиотекам
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")]
)
)Și cu DEB am terminat, acum trecem la 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)
)Dat fiind că în Windows nu avem grep și sed (sau poate că avem?), vom folosi 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),
]Pentru a notifica despre starea procesului de construire, vom folosi poșta electronică.
c['services'] = []
template=u'''
<h4>Starea construcției: {{ summary }}</h4>
<p> Lucrător utilizat: {{ workername }}</p>
{% for step in build['steps'] %}
<p> {{ step['name'] }}: {{ step['result'] }}</p>
{% endfor %}
<p><b> -- Buildbot-ul</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)
# Setările principale ale master-ului
c['title'] = "Procesul de construcție"
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"
}Salvăm fișierul și putem încerca să pornim serviciul master:
systemctl restart buildbot-masterÎn jurnal vom verifica că totul este în regulă cu configurația și că funcționează în mod normal. Toți muncitorii noștri ar trebui acum să se conecteze, ceea ce va fi anunțat în jurnal »»’/home/buildbot/master/twistd.log»»’.
2019-07-24 16:50:35+0300 [-] Încărcare buildbot.tac...
2019-07-24 16:50:35+0300 [-] Încărcat.
2019-07-24 16:50:35+0300 [-] twistd 19.2.1 (\/usr\/bin\/python3.6 3.6.8) se pornește.
2019-07-24 16:50:35+0300 [-] clasa reactor: twisted.internet.epollreactor.EPollReactor.
2019-07-24 16:50:35+0300 [-] Începerea BuildMaster -- buildbot.version: 2.3.1
2019-07-24 16:50:35+0300 [-] Încărcare configurație din '\/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 și ulterioare] `buildbotNetUsageData` nu este configurat și revine la setările de bază.
Acest parametru ajută echipa de dezvoltare a buildbot să înțeleagă baza de instalare.
Nu sunt colectate informații personale.
Doar informațiile despre versiunea software-ului instalat și utilizarea plugin-urilor sunt trimise.
Puteți `opt-out` setând această variabilă la None.
Sau `opt-in` pentru mai multe informații, setând-o la "full".
2019-07-24 16:50:36+0300 [-] Configurare bază de date cu URL 'sqlite:\/state.sqlite'
2019-07-24 16:50:36+0300 [-] setarea modului jurnal al bazei de date la 'wal'
2019-07-24 16:50:36+0300 [-] adăugare 1 serviciu nou, eliminare 0
2019-07-24 16:50:36+0300 [-] adăugare 1 sursă de schimbări noi, eliminare 0
2019-07-24 16:50:36+0300 [-] gitpoller: utilizând directorul de lucru '\/home\/buildbot\/master\/gitpoller-work'
2019-07-24 16:50:36+0300 [-] adăugare 3 construitori noi, eliminare 0
2019-07-24 16:50:36+0300 [-] adăugare 1 nou programator, eliminare 0
2019-07-24 16:50:36+0300 [-] inițializare plugin www 'waterfall_view'
2019-07-24 16:50:36+0300 [-] inițializare plugin www 'console_view'
2019-07-24 16:50:36+0300 [-] inițializare plugin www 'grid_view'
2019-07-24 16:50:36+0300 [-] NOTĂ: plugin ul www 'sitenav' este instalat, dar nu este configurat.
2019-07-24 16:50:36+0300 [-] inițializare plugin www 'waterfall_view'
2019-07-24 16:50:36+0300 [-] inițializare plugin www 'console_view'
2019-07-24 16:50:36+0300 [-] inițializare plugin www 'grid_view'
2019-07-24 16:50:36+0300 [-] NOTĂ: plugin ul www 'sitenav' este instalat, dar nu este configurat.
2019-07-24 16:50:36+0300 [-] BuildbotSite pornind pe 80
2019-07-24 16:50:36+0300 [-] Pornire fabrică <buildbot.www.service.BuildbotSite object at 0x7fe31c2657b8>
2019-07-24 16:50:36+0300 [-] adăugare 3 lucrători noi, eliminare 0
2019-07-24 16:50:36+0300 [-] PBServerFactory pornind pe 4000
2019-07-24 16:50:36+0300 [-] Pornire fabrică <twisted.spread.pb.PBServerFactory object at 0x7fe31c147470>
2019-07-24 16:50:37+0300 [-] BuildMaster este în execuție
2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: trimit {'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] lucrător 'CentOS' se atașează de IPv4Address(type='TCP', host='127.0.0.1', port=37332)
2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Am primit informațiile lucrătorului de la 'CentOS'
2019-07-24 16:50:37+0300 [-] bot atașat
2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Lucrătorul CentOS atașat la Rac-GUI-RPM-builder
2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: buildbot.net a spus: ok
2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] lucrător 'Windows-10' se atașează de IPv4Address(type='TCP', host='192.168.5.145', port=49831)
2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] Am primit informațiile lucrătorului de la 'Windows-10'
2019-07-24 16:50:40+0300 [-] bot atașat
2019-07-24 16:50:40+0300 [Broker,1,192.168.55.15] Lucrătorul Windows-10 atașat la Rac-GUI-WIN-builder
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] lucrător 'Debian-10' se atașează de IPv4Address(type='TCP', host='192.168.5.9', port=44430)
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Am primit informațiile lucrătorului de la 'Debian-10'
2019-07-24 16:50:41+0300 [-] bot atașat
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Lucrătorul Debian-10 atașat la Rac-GUI-DEB-builderAcest proces de configurare s-a încheiat. Puteți verifica starea curentă prin intermediul interfeței web, unde puteți observa, de asemenea, erorile de construcție, să reporniti procesele blocate dacă ceva nu a mers bine etc.
Imediat după ce muncitorii noștri sunt activi, puteți verifica prin meniul „Builds” -> „Workers”

După ce va fi finalizat primul proces de construcție (adică modificările din repository-ul Git), pe prima pagină va apărea starea proceselor.

Dacă faceți clic pe linia dorită, se va deschide o pagină cu starea curentă a acestui proces, unde se poate observa ce se întâmplă, ce erori sunt etc.

Întreaga configurație a maestrului poate fi găsită aici
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
))
# Serviciul de lansare a compilării
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)
)
# Să adăugăm definirea versiunii din fișierul principal
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"
)
)
# Să adăugăm definirea release-ului din fișierul principal
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'
))
# Să copiem fișierul pe server
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)
)
# Să adăugăm definirea versiunii din fișierul principal
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"
)
)
# Să adăugăm definirea release-ului din fișierul principal
rac_gui_build_DEB.addStep(
steps.SetPropertyFromCommand(
command="grep release rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
)
)
# Să redenumim fișierul executabil
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["mv", "rac_gui.tcl", "racgui"]))
# Să schimbăm căile către biblioteci
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["sed", "-i", "s+^set dir(lib)+set dir(lib) \/usr\/share\/rac-gui\/lib ;#+g", "racgui"]))
# Să schimbăm căile către fișiere
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["sed", "-i", "s+[pwd]+\/usr\/share\/rac-gui+g", "racgui"]))
# Să arhivăm sursele
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["tar", "czf", util.Interpolate("..\/rac-gui_%(prop:version)s.orig.tar.gz"), "."]))
# Să construim pachetul
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["dpkg-buildpackage"]))
# Să copiem fișierul pe server
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)
)
# Să adăugăm definirea versiunii din fișierul principal
rac_gui_build_WIN.addStep(
steps.SetPropertyFromCommand(
command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'version:') -split 's')[2]",
property="version"
)
)
# Să adăugăm definirea release-ului din fișierul principal
rac_gui_build_WIN.addStep(
steps.SetPropertyFromCommand(
command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'release:') -split 's')[2]",
property="release"
)
)
# Să creăm fișierul executabil
rac_gui_build_WIN.addStep(steps.ShellCommand(
command=["c:binfreewrap.exe", "rac_gui.tcl"]))
# Să comprimăm ce am obținut
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"]))
# Să copiem pe server
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")
)
)
# Să copiem fișierul pe 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>Starea construcției: {{ summary }}</h4>
<p> Lucrător utilizat: {{ workername }}</p>
{% for step in build['steps'] %}
<p> {{ step['name'] }}: {{ step['result'] }}</p>
{% endfor %}
<p><b> -- Buildbot-ul</b></p>
'''
mailNotifier = reporters.MailNotifier(fromaddr="112@icvibor.ro",
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'] = "Procesul de construcție"
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"
}Materiale
Pentru pregătirea articolului au fost utilizate următoarele materiale:
- Și documentația produsului
Sursa: habr.com
