Buildbot i exempel

Jag behövde ställa in bygg- och leveransprocessen för programvarupaket från Git-repositoryn. Och efter att jag nyligen sett en artikel om buildbot här på Habré (länk i slutet) bestämde jag mig för att prova och använda det.

Eftersom buildbot är ett distribuerat system, skulle det vara logiskt att skapa en separat byggvärd för varje arkitektur och operativsystem. I vårt fall blir detta LXC-containrar (för Linux) och QEMU (för Windows):

  • vm-srv-build1 — CentOS 7, här kommer buildbot-mastern (master) och en av arbetarna (worker) att befinna sig
  • vm-srv-build2 — Debian 10, för att bygga DEB-paket
  • vm-srv-build3 — Windows 10, för byggen, som ni förstår.

Vi kommer att bygga Rac GUI — grafiskt gränssnitt för 1C rac för att hantera serverkluster. För Linux kommer standardverktyg att användas för varje OS, för att bygga exe-filer för Windows från TCL-skript används freewrap.

Installation

GNU/Linux

Det finns tillräckligt med installationsdokumentation på nätet. 1,2Och det orsakar inga särskilda problem:
För mastern:

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

För "arbetarna", är det tillräckligt med detta:

pip3 install buildbot-worker

Självklart skulle det vara mer korrekt att bygga paketen för varje OS, men det ligger utanför artikelns ramar. Vi hoppar även över beskrivningen av inställningen av containrarna, bara att jag använder ProxMox VE. Och vi behöver också installera paket för varje system som krävs för byggandet (CentOS: rpmdevtools osv; Debian: build-essential, dh-make, pbuilder osv.)

Byggprojekten och tjänsterna för buildbot kommer att köras under en icke-privilegierad användare, så det är nödvändigt att skapa en sådan användare på alla värdar som deltar i processen:


adduser buildbot

Därefter ställer vi in automatisk start av tjänsterna, på varje värd (container):

Systemd-enhet för att starta mastern:

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

och "arbetaren"

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

Eftersom alla skript (i vårt fall) ligger i /usr/local/, bör vi ange sökvägen till dem i miljövariablerna:

nano /root/.bash_profile

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

Därefter kan du skapa en kataloginfrastruktur för "arbetare" (på alla värdar), registrera under användaren buildbot och utföra följande kommandon:

På den första värden 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

På den andra värden 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

På arbetsvärdarna kan du starta tjänsten buildbot-worker.

systemctl start buildbot-worker

MS Windows

Som "arbetare" för byggandet för Windows kommer en virtuell maskin med den senaste versionen av Win10 att användas.
För att detta ska fungera behöver du:

När allt ovanstående har installerats kan vi även installera buildbot:

pip install buildbot-worker

Vi skapar en arbetskatalog

md c:worker

Och startar

buildbot-worker start c:worker

Om allt fungerar (se logg c:workertwistd.log), kan vi registrera vår "arbetare" som en tjänst genom att lägga till en post i registret med arbetskatalogen (kommandona utförs i Powershell som körs som administratör):

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

Och så kan vi starta tjänsten.

Start-Service buildbot

Det är allt om "arbetarna", vi behöver inte röra dem mer; all hantering sker från mastern.

Inställning av mastern

Först skapar vi infrastrukturen för mastern (på huvudvärden), registrera under användaren buildbot och utför följande kommandon:

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

För de färdiga paketen skapar vi en katalog builds.

mkdir /home/buildbot/builds

I katalogen /home/buildbot/master/ har en fil skapats som heter master.cfg. Denna fil är kod i Python och innehåller beskrivning av alla systemets funktioner, och det är den vi kommer att arbeta med framöver.

nano /home/buildbot/master/master.cfg

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

c = BuildmasterConfig = {}

# Beskrivning av våra arbetare.
c['workers'] = [ worker.Worker('CentOS', '123456'), worker.Worker('Debian-10', '123456'), worker.Worker('Windows-10', '123456')]
c['protocols'] = {'pb': {'port': 4000}}

# Angivelse till mastern om vilken repository som ska övervakas
c['change_source'] = []
c['change_source'].append(changes.GitPoller(
       repourl = 'https://bitbucket.org/svk28/rac-gui.git',
       project = 'Rac-GUI',
       branches = True,
       pollInterval = 60
      )
)

# Tjänst för att starta bygget
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
# Bygg en RPM-paket
 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)
)

För att automatisera byggandet av paket i olika versioner, och för att slippa gå in och ändra i master.cfg-filen, har rader med aktuell version och release lagts till i den huvudsakliga programmet rac_gui.tcl.

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

Och baserat på dessa rader kommer buildbot att numrera paketen. För att hämta data används ett konsolvärde av grep. I buildbot går det inte enkelt att definiera variabler för "arbetare" (i alla fall har jag inte hittat hur). Detta görs genom egenskaper (property). D.v.s. i byggprocessen lägger vi till steg för att definiera version och release och sätter därför egenskaperna version och release. Egenskaper kan sättas på olika sätt, i detta fall genom att anropa en konsol kommando:

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

De erhållna värdena kan sättas in genom att anropa 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"]
       )
)

Här bör man notera att eftersom värden används för manuell paketbyggnad också, så kommer bygget att ske via standardvägar.

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

För att ställa in korrekta release- och versionsnummer används en standard sed-anrop, det vill säga kommandot ersätter värdena inuti spec-filen med de nödvändiga.

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

Den färdiga byggda paketet och arkivet med källkod kopieras till mastern. Men man kan också direkt kopiera från arbetsfilen till sin repository eller webbplats.

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

Vi kommer att starta en kopieringsprocess av de byggda paketen till hosting via ftp. För detta används skript på 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")]
        )
)

Vi har avslutat arbetet med RPM. Nu går vi vidare till beskrivningen av algoritmen för att bygga DEB-paket. Eftersom byggprocesserna för olika system är oberoende av varandra kommer många steg att upprepas.


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

# Lägger till versionsdefinition från huvudfilen
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"
       )
)

# Lägger till release-definition från huvudfilen
rac_gui_build_DEB.addStep(
       steps.SetPropertyFromCommand(
       command="grep release rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
       )
)

# Byter namn på körfilen
    rac_gui_build_DEB.addStep(steps.ShellCommand(
       command=["mv", "rac_gui.tcl", "racgui"]))

För RPM-paketet utförs en del av de följande procedurerna av rpm under byggprocessen och beskrivs i spec-filen, för Debian måste detta göras här:

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

Och med DEB klart, nu till 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)
)

Eftersom Windows normalt sett inte har grep och sed (eller har det?) kommer vi att använda 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),
]

För att meddela om statusen för byggprocessen kommer vi att använda elektrisk post.


c['services'] = []

template=u'''
    <h4>Byggstatus: {{ summary }}</h4>
    <p> Arbetare som användes: {{ workername }}</p>
    {% for step in build['steps'] %}
    <p> {{ step['name'] }}: {{ step['result'] }}</p>
    {% endfor %}
    <p><b> -- Byggbot</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)

# Grundläggande inställningar för mästaren
c['title'] = "Byggprocessen"
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"
}

Spara filen och vi kan försök köra byggmästarens tjänst:

systemctl restart buildbot-master

I loggen kontrollerar vi att konfigurationen är okej och att allt fungerar som det ska. Alla våra arbetare ska nu ansluta, vilket kommer att meddelas i loggen »»'/home/buildbot/master/twistd.log»».

 2019-07-24 16:50:35+0300 [-] Laddar buildbot.tac...
 2019-07-24 16:50:35+0300 [-] Laddad.
 2019-07-24 16:50:35+0300 [-] twistd 19.2.1 (\/usr\/bin\/python3.6 3.6.8) startar.
 2019-07-24 16:50:35+0300 [-] reaktorklass: twisted.internet.epollreactor.EPollReactor.
 2019-07-24 16:50:35+0300 [-] Startar BuildMaster -- buildbot.version: 2.3.1
 2019-07-24 16:50:35+0300 [-] Laddar konfiguration från '\/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 och senare] `buildbotNetUsageData` är inte konfigurerat och standardinställningen är grundläggande.
 Detta parameter hjälper buildbot-utvecklingsteamet att förstå installationsbasen.
 Ingen personlig information samlas in.
 Endast installationsprogramvaruversionsinformation och pluginanvändning skickas.
 Du kan `opt-out` genom att ställa in denna variabel på None.
 Eller `opt-in` för mer information genom att ställa in den på "full".

 2019-07-24 16:50:36+0300 [-] Sätter upp databas med URL 'sqlite:\/state.sqlite'
 2019-07-24 16:50:36+0300 [-] sätter databasens journalläge till 'wal'
 2019-07-24 16:50:36+0300 [-] lägger till 1 ny tjänst, tar bort 0
 2019-07-24 16:50:36+0300 [-] lägger till 1 ny change_sources, tar bort 0
 2019-07-24 16:50:36+0300 [-] gitpoller: använder arbetskatalog '\/home\/buildbot\/master\/gitpoller-work'
 2019-07-24 16:50:36+0300 [-] lägger till 3 nya byggare, tar bort 0
 2019-07-24 16:50:36+0300 [-] lägger till 1 ny schemaläggare, tar bort 0
 2019-07-24 16:50:36+0300 [-] initiering av www-plugin 'waterfall_view'
 2019-07-24 16:50:36+0300 [-] initiering av www-plugin 'console_view'
 2019-07-24 16:50:36+0300 [-] initiering av www-plugin 'grid_view'
 2019-07-24 16:50:36+0300 [-] OBS: www-plugin 'sitenav' är installerad men inte konfigurerad
 2019-07-24 16:50:36+0300 [-] initiering av www-plugin 'waterfall_view'
 2019-07-24 16:50:36+0300 [-] initiering av www-plugin 'console_view'
 2019-07-24 16:50:36+0300 [-] initiering av www-plugin 'grid_view'
 2019-07-24 16:50:36+0300 [-] OBS: www-plugin 'sitenav' är installerad men inte konfigurerad
 2019-07-24 16:50:36+0300 [-] BuildbotSite startar på 80
 2019-07-24 16:50:36+0300 [-] Startar fabrik <buildbot.www.service.BuildbotSite objekt vid 0x7fe31c2657b8>
 2019-07-24 16:50:36+0300 [-] lägger till 3 nya arbetare, tar bort 0
 2019-07-24 16:50:36+0300 [-] PBServerFactory startar på 4000
 2019-07-24 16:50:36+0300 [-] Startar fabrik <twisted.spread.pb.PBServerFactory objekt vid 0x7fe31c147470>
 2019-07-24 16:50:37+0300 [-] BuildMaster kör
 2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: skickar {'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] arbetare 'CentOS' kopplar från IPv4Address(type='TCP', host='127.0.0.1', port=37332)
 2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Fick workerinfo från 'CentOS'
 2019-07-24 16:50:37+0300 [-] bot kopplad
 2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Arbetare CentOS kopplad till Rac-GUI-RPM-builder
 2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: buildbot.net sade: ok
 2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] arbetare 'Windows-10' kopplar från IPv4Address(type='TCP', host='192.168.5.145', port=49831)
 2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] Fick workerinfo från 'Windows-10'
 2019-07-24 16:50:40+0300 [-] bot kopplad
 2019-07-24 16:50:40+0300 [Broker,1,192.168.55.15] Arbetare Windows-10 kopplad till Rac-GUI-WIN-builder
 2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] arbetare 'Debian-10' kopplar från IPv4Address(type='TCP', host='192.168.5.9', port=44430)
 2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Fick workerinfo från 'Debian-10'
 2019-07-24 16:50:41+0300 [-] bot kopplad
 2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Arbetare Debian-10 kopplad till Rac-GUI-DEB-builder

När inställningsprocessen är klar kan man se den aktuella statusen via webbgränssnittet. Där kan man också se byggfel, starta om en hängande process om något går fel, osv.

Direkt efter att våra arbetare har startats kan man se dem via menyn «Builds» -> «Workers»

Buildbot i exempel

När den första byggprocessen har genomförts (dvs. ändringar i Git-repot), kommer statusen för processerna att visas på den första sidan.

Buildbot i exempel

Om man klickar med musen på den aktuella raden öppnas en sida med det aktuella statusen för denna process, där man kan se vad som händer, vilka fel som uppstår osv.

Buildbot i exempel

Den fullständiga konfigurationen av mästaren kan hämtas här

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

# Tjänst för att starta byggprocessen
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)
)

# Låt oss lägga till versionsbestämning från huvudfilen
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"
    )
)

# Låt oss lägga till releasebestämning från huvudfilen
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'
))

# Låt oss kopiera filen till mastern
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)
)

# Låt oss lägga till versionsbestämning från huvudfilen
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"
    ))

# Låt oss lägga till releasebestämning från huvudfilen
rac_gui_build_DEB.addStep(
    steps.SetPropertyFromCommand(
    command="grep release rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
    ))

# Byt namn på exekverbara filen
rac_gui_build_DEB.addStep(steps.ShellCommand(
    command=["mv", "rac_gui.tcl", "racgui"]))

# Ändra sökvägar till bibliotek
rac_gui_build_DEB.addStep(steps.ShellCommand(
    command=["sed", "-i", "s+^set dir(lib)+set dir(lib) \/usr\/share\/rac-gui\/lib ;#+g", "racgui"]))

# Ändra sökvägar till filer
rac_gui_build_DEB.addStep(steps.ShellCommand(
    command=["sed", "-i", "s+[pwd]+\/usr\/share\/rac-gui+g", "racgui"]))

# Komprimera källkoden
rac_gui_build_DEB.addStep(steps.ShellCommand(
    command=["tar", "czf", util.Interpolate("..\/rac-gui_%(prop:version)s.orig.tar.gz"), "."]))

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

# Låt oss kopiera filen till mastern
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)
)

# Låt oss lägga till versionsbestämning från huvudfilen
rac_gui_build_WIN.addStep(
    steps.SetPropertyFromCommand(
    command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'version:') -split 's')[2]",
    property="version"
    ))

# Låt oss lägga till releasebestämning från huvudfilen
rac_gui_build_WIN.addStep(
    steps.SetPropertyFromCommand(
    command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'release:') -split 's')[2]",
    property="release"
    ))

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

# Packa det vi fick
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"]))

# Kopiera till mastern
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")
    ))

# Låt oss kopiera filen till 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>Byggstatus: {{ summary }}</h4>
<p> Arbetare som användes: {{ workername }}</p>
{% for step in build['steps'] %}
<p> {{ step['name'] }}: {{ step['result'] }}</p>
{% endfor %}
<p><b> -- Byggbot</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'] = "Byggprocessen"
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"
}

Material

Vid förberedelsen av artikeln användes följande material:

Källa: habr.com

Köp pålitlig webbhotell med DDoS-skydd, VPS VDS-servrar 🔥 Köp pålitlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster