Buildbot in voorbeelden

Ik had de noodzaak om het proces van het bouwen en leveren van softwarepakketten vanaf een Git-repository naar de site in te stellen. En, niet zo lang geleden, zag ik hier op Habr een artikel over buildbot (link onderaan) en besloot het uit te proberen en toe te passen.

Aangezien buildbot een gedistribueerd systeem is, is het logisch om voor elke architectuur en elk besturingssysteem een aparte build-host te maken. In ons geval zullen dit LXC-containers zijn (in het geval van Linux) en QEMU (in het geval van Windows):

  • vm-srv-build1 — centos 7, hier zal de buildbot master (hoofd) en een van de werkers draaien
  • vm-srv-build2 — debian 10, voor het bouwen van DEB-pakketten
  • vm-srv-build3 — windows 10, voor het bouwen, u begrijpt wel, voor wat

We zullen bouwen Rac GUI — de grafische interface voor 1C rac voor het beheren van een cluster van servers. Voor Linux zullen de standaard hulpmiddelen voor elk OS worden gebruikt, voor het bouwen van een exe-bestand voor Windows uit een TCL-script wordt gebruikt freewrap.

Installatie

GNU/Linux

Er is voldoende documentatie online over de installatie 1,2. Bovendien veroorzaakt het geen speciale problemen:
Voor de 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-dateutil

Voor de "werkers", is dit voldoende:

pip3 install buildbot-worker

Natuurlijk is het beter om de pakketten voor elk OS apart te bouwen, maar dat valt buiten de reikwijdte van dit artikel. We laten ook de beschrijving van de configuratie van de containers voor de werking achterwege, ik zal alleen opmerken dat ik ProxMox VE gebruik. En daarnaast moeten de nodige pakketten voor het bouwen worden geïnstalleerd voor elk systeem (centos: rpmdevtools, enz.; debian: build-essential, dh-make, pbuilder, enz.)

De bouwprojecten en buildbot-services zullen worden uitgevoerd onder de naam van een niet-geprivilegieerde gebruiker, dus het is nodig om deze gebruiker te creëren op alle hosts die bij het proces betrokken zijn:


adduser buildbot

Daarna zullen we de automatische start van de services instellen, dienovereenkomstig op elk van de hosts (containers):

Systemd-eenheid voor het starten van de master:

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

en de "werker"

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

Aangezien alle scripts (in ons geval) zich in /usr/local/ bevinden, moet het pad naar hen worden opgenomen in de omgevingsvariabelen:

nano /root/.bash_profile

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

Daarna kan een directory-infrastructuur worden gemaakt voor de 'workers' (op alle hosts), hiervoor wordt ingelogd als gebruiker buildbot en voeren we de volgende commando's uit:

Op de eerste host 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

Op de tweede host 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

Op de worker-hosts kan de buildbot-worker service worden gestart

systemctl start buildbot-worker

MS Windows

Als 'worker' voor het bouwen op Windows wordt een virtuele machine met de laatste versie van Win10 gebruikt.
Voor de werking is het nodig:

Nadat alles hierboven is geïnstalleerd, kan buildbot zelf worden geïnstalleerd:

pip install buildbot-worker

Laten we een werkdirectory aanmaken

md c:worker

En starten

buildbot-worker start c:worker

Als alles werkt (zie log c:workertwistd.log), kan onze 'worker' als service worden geregistreerd door een item met de werkdirectory aan het register toe te voegen (de commando's worden uitgevoerd in powershell dat als administrator is gestart):

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

En de service kan worden gestart

Start-Service buildbot

Wat de 'workers' betreft, dat is alles, ze hoeven verder niet aangeraakt te worden, alle beheertaken worden vanuit de master uitgevoerd.

Configuratie van de master

Om te beginnen, creëren we een infrastructuur voor de master (op de hoofdhost), hiervoor wordt ingelogd als gebruiker buildbot en voeren we de volgende commando's uit:

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

Voor kant-en-klare pakketten maken we een directory builds

mkdir /home/buildbot/builds

In de directory /home/buildbot/master/ is het bestand master.cfg aangemaakt. Dit bestand bevat Python-code en beschrijft alle mechanismen van het systeem, waarmee we verder zullen werken.

nano /home/buildbot/master/master.cfg

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

c= BuildmasterConfig ={}

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

# Opgeven aan de master welke repository gevolgd moet worden
c['change_source'] = []
c['change_source'].append(changes.GitPoller(
       repourl = 'https://bitbucket.org/svk28/rac-gui.git',
       project = 'Rac-GUI',
       branches = True,
       pollInterval = 60
      )
)

# Diensten om de build te starten
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
# Bouwen van het RPM-pakket
 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)
)

Voor de automatisering van het bouwen van pakketten van verschillende versies, zodat er niet in de code van het bestand master.cfg gehanneld hoeft te worden, zijn in het hoofdscript van het programma rac_gui.tcl regels met de huidige versie en release toegevoegd:

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

Op basis van deze regels zal buildbot de pakketten nummeren. Voor het extraheren van gegevens wordt de console-oproep grep gebruikt. In buildbot is het simpelweg niet mogelijk om variabelen voor "werkers" te definiëren (in ieder geval heb ik niet gevonden hoe). Hiervoor dienen eigenschappen (property). Dus voegen we stappen toe aan het bouwproces om versie en release te bepalen en stellen we de eigenschappen version en release in. Eigenschappen kunnen op verschillende manieren worden ingesteld, in dit geval is dit via de console-oproep:

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

Je kunt de verkregen waarden invoegen door gebruik te maken van 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"]
       )
)

Hier moet opgemerkt worden dat, aangezien de host ook gebruikt wordt voor handmatige pakketbouw, de bouw volgens de standaardpaden zal plaatsvinden.

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

Voor het instellen van de correcte release- en versienummers wordt de standaard sed-oproep gebruikt, d.w.z. de opdracht vervangt waarden in het spec-bestand door de vereiste waarden.

# меняем версию
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'
      )
)

Het gereed gebouwde pakket en het archief met de brondocumenten worden naar de master gekopieerd. Maar je kunt ook direct van de werkmap naar je repository of website kopiëren.

# Скопируем файл на мастер
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")
       )
)

Laten we het proces op de master starten van het kopiëren van de gebouwde pakketten naar de hosting via ftp. Hiervoor wordt gebruikt: script in 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")]
        )
)

We hebben de RPM afgemaakt. Laten we nu de beschrijving van het DEB-pakket bouwalgoritme beginnen. Aangezien de bouwprocessen voor verschillende systemen onafhankelijk van elkaar zijn, zullen veel stappen herhaald worden.


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

# Laten we de versie bepalen uit het hoofd bestand
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"
       )
)

# Laten we de release bepalen uit het hoofd bestand
rac_gui_build_DEB.addStep(
       steps.SetPropertyFromCommand(
       command="grep release rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
       )
)

# Hernoem het uitvoerbare bestand
    rac_gui_build_DEB.addStep(steps.ShellCommand(
       command=["mv", "rac_gui.tcl", "racgui"]))

Voor het RPM-pakket worden sommige van de volgende procedures door rpm zelf afgehandeld tijdens het bouwen en zijn beschreven in de spec, voor debian moeten we dit hier doen:

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

En we zijn klaar met DEB, nu 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)
)

Aangezien Windows standaard geen grep en sed heeft (of heeft het dat?), zullen we powershell gebruiken.

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

Om de status van het bouwproces te melden, zullen we elektrische post gebruiken.


c['services'] = []

template=u'''
    <h4>Bouwstatus: {{ summary }}</h4>
    <p> Gebruikte werknemer: {{ workername }}</p>
    {% for step in build['steps'] %}
    <p> {{ step['name'] }}: {{ step['result'] }}</p>
    {% endfor %}
    <p><b> -- De Buildbot</b></p>
    '''

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

c['services'].append(mailNotifier)

# Basisinstellingen van de master
c['title'] = "Het proces van bouwen"
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"
}

Sla het bestand op en we kunnen proberen de master service te starten:

systemctl restart buildbot-master

In de log controleren we of de configuratie in orde is en alles normaal werkt. Al onze werkers zouden nu moeten verbinden, waarover in de log »»’/home/buildbot/master/twistd.log»»’ blij zal worden gemeld:

 2019-07-24 16:50:35+0300 [-] Buildbot.tac laden...
 2019-07-24 16:50:35+0300 [-] Geladen.
 2019-07-24 16:50:35+0300 [-] twistd 19.2.1 (\/usr\/bin\/python3.6 3.6.8) start...
 2019-07-24 16:50:35+0300 [-] reactor klasse: twisted.internet.epollreactor.EPollReactor.
 2019-07-24 16:50:35+0300 [-] BuildMaster starten -- buildbot.version: 2.3.1
 2019-07-24 16:50:35+0300 [-] Configuratie laden vanuit '\/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 en later] `buildbotNetUsageData` is niet geconfigureerd en valt terug op basis.
        Deze parameter helpt het buildbot-ontwikkelingsteam de installatiebasis te begrijpen.
        Er worden geen persoonlijke gegevens verzameld.
        Alleen informatie over de versie van de installatie-software en het gebruik van plugins wordt verzonden.
        U kunt zich `afmelden` door deze variabele op None in te stellen.
        Of `toestemming geven` voor meer informatie door deze in te stellen op "volledig".

 2019-07-24 16:50:36+0300 [-] Database instellen met URL 'sqlite:\/state.sqlite'
 2019-07-24 16:50:36+0300 [-] database journalmodus instellen op 'wal'
 2019-07-24 16:50:36+0300 [-] 1 nieuwe services toevoegen, 0 verwijderen
 2019-07-24 16:50:36+0300 [-] 1 nieuwe change_sources toevoegen, 0 verwijderen
 2019-07-24 16:50:36+0300 [-] gitpoller: werkdirectory gebruiken '\/home\/buildbot\/master\/gitpoller-work'
 2019-07-24 16:50:36+0300 [-] 3 nieuwe builders toevoegen, 0 verwijderen
 2019-07-24 16:50:36+0300 [-] 1 nieuwe planners toevoegen, 0 verwijderen
 2019-07-24 16:50:36+0300 [-] www-plugin 'waterfall_view' initialiseren
 2019-07-24 16:50:36+0300 [-] www-plugin 'console_view' initialiseren
 2019-07-24 16:50:36+0300 [-] www-plugin 'grid_view' initialiseren
 2019-07-24 16:50:36+0300 [-] OPGELET: www-plugin 'sitenav' is geïnstalleerd maar niet geconfigureerd
 2019-07-24 16:50:36+0300 [-] www-plugin 'waterfall_view' initialiseren
 2019-07-24 16:50:36+0300 [-] www-plugin 'console_view' initialiseren
 2019-07-24 16:50:36+0300 [-] www-plugin 'grid_view' initialiseren
 2019-07-24 16:50:36+0300 [-] OPGELET: www-plugin 'sitenav' is geïnstalleerd maar niet geconfigureerd
 2019-07-24 16:50:36+0300 [-] BuildbotSite startend op 80
 2019-07-24 16:50:36+0300 [-] Fabriek <buildbot.www.service.BuildbotSite object at 0x7fe31c2657b8> starten
 2019-07-24 16:50:36+0300 [-] 3 nieuwe werkers toevoegen, 0 verwijderen
 2019-07-24 16:50:36+0300 [-] PBServerFactory startend op 4000
 2019-07-24 16:50:36+0300 [-] Fabriek <twisted.spread.pb.PBServerFactory object at 0x7fe31c147470> starten
 2019-07-24 16:50:37+0300 [-] BuildMaster draait
 2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: verzenden {'installid': 'b6193b126b96689351d2fe95787c5a03fc0879f9', 'versies': {'Python': '3.6.8', 'Buildbot': '2.3.1', 'Twisted': '19.2.1'}, 'platform': {'platform': 'Linux-4.15.18-10- pve-x86_64-met-centos-7.6.1810-Core', 'systeem': 'Linux', 'machine': 'x86_64', 'processor': 'x86_64', 'python_implementatie': 'CPython', 'versie': '#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] arbeider 'CentOS' die aan het koppelen is vanaf IPv4Address(type='TCP', host='127.0.0.1', port=37332)
 2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Werk informatie ontvangen van 'CentOS'
 2019-07-24 16:50:37+0300 [-] bot gekoppeld
 2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Arbeider CentOS gekoppeld aan Rac-GUI-RPM-builder
 2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: buildbot.net zei: ok
 2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] arbeider 'Windows-10' die aan het koppelen is vanaf IPv4Address(type='TCP', host='192.168.5.145', port=49831)
 2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] Werk informatie ontvangen van 'Windows-10'
 2019-07-24 16:50:40+0300 [-] bot gekoppeld
 2019-07-24 16:50:40+0300 [Broker,1,192.168.55.15] Arbeider Windows-10 gekoppeld aan Rac-GUI-WIN-builder
 2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] arbeider 'Debian-10' die aan het koppelen is vanaf IPv4Address(type='TCP', host='192.168.5.9', port=44430)
 2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Werk informatie ontvangen van 'Debian-10'
 2019-07-24 16:50:41+0300 [-] bot gekoppeld
 2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Arbeider Debian-10 gekoppeld aan Rac-GUI-DEB-builder

Deze stap in de configuratie is voltooid. U kunt de huidige status bekijken via de webinterface. Hier kunt u ook buildfouten bekijken en vastgelopen processen indien nodig opnieuw starten.

Direct na de lancering van onze werkers kunt u ze bekijken via het menu "Builds" -> "Workers".

Buildbot in voorbeelden

Nadat het eerste buildproces is uitgevoerd (d.w.z. wijzigingen in de Git-repository), verschijnt de status van de processen op de eerste pagina.

Buildbot in voorbeelden

Als u met de muis op de gewenste regel klikt, opent er een pagina met de huidige status van dat proces, waar u kunt zien wat er gebeurt, welke fouten zich voordoen, enzovoort.

Buildbot in voorbeelden

U kunt de volledige configuratie van de wizard hier verkrijgen.

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

# Opdracht voor het opstarten van de build
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)
    )

# Voeg versiebepaling toe vanuit het hoofd bestand
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"
    )
)

# Voeg releasebepaling toe vanuit het hoofd bestand
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'
    ))

# Kopieer bestand naar 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)
    )

# Voeg versiebepaling toe vanuit het hoofd bestand
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"
    )
)

# Voeg releasebepaling toe vanuit het hoofd bestand
rac_gui_build_DEB.addStep(
    steps.SetPropertyFromCommand(
    command="grep release rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
    )
)

# Hernoem uitvoerbestand
rac_gui_build_DEB.addStep(steps.ShellCommand(
    command=["mv", "rac_gui.tcl", "racgui"]))

# Verander bibliotheekpaden
rac_gui_build_DEB.addStep(steps.ShellCommand(
    command=["sed", "-i", "s+^set dir(lib)+set dir(lib) /usr/share/rac-gui/lib ;#+g", "racgui"]))

# Verander bestandslocaties
rac_gui_build_DEB.addStep(steps.ShellCommand(
    command=["sed", "-i", "s+[pwd]/usr/share/rac-gui+g", "racgui"]))

# Archiveer de broncode
rac_gui_build_DEB.addStep(steps.ShellCommand(
    command=["tar", "czf", util.Interpolate("../rac-gui_%(prop:version)s.orig.tar.gz"), "."]))

# Bouw pakket
rac_gui_build_DEB.addStep(steps.ShellCommand(
    command=["dpkg-buildpackage"]))

# Kopieer bestand naar 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)
    )

# Voeg versiebepaling toe vanuit het hoofd bestand
rac_gui_build_WIN.addStep(
    steps.SetPropertyFromCommand(
    command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'version:') -split 's')[2]",
    property="version"
    )
)

# Voeg releasebepaling toe vanuit het hoofd bestand
rac_gui_build_WIN.addStep(
    steps.SetPropertyFromCommand(
    command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'release:') -split 's')[2]",
    property="release"
    )
)

# Maak uitvoerbestand
rac_gui_build_WIN.addStep(steps.ShellCommand(
    command=["c:binfreewrap.exe", "rac_gui.tcl"]))

# Pak in wat er is gemaakt
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"]))

# Kopieer naar 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")
    )
)

# Kopieer bestand naar 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>Bouwstatus: {{ summary }}</h4>
<p> Gebruikte werknemer: {{ workername }}</p>
{% for step in build['steps'] %}
<p> {{ step['name'] }}: {{ step['result'] }}</p>
{% endfor %}
<p><b> -- De 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'] = "Het proces van bouwen"
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"
}

Materialen

Voor het opstellen van het artikel zijn de volgende materialen gebruikt:

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers 🔥 Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster