Buildbot i eksempler

Jeg skulle opsætte en proces til at samle og levere softwarepakker fra Git-repositoriet til hjemmesiden. Og da jeg for nylig så en artikel om buildbot her på Habr (linket i slutningen), besluttede jeg at prøve det til dette formål og anvende det.

Da buildbot er et distribueret system, vil det være logisk at lave en separat byggeshost til hver arkitektur og operativsystem. I vores tilfælde vil dette være LXC-containere (for linux) og qemu (for windows):

  • vm-srv-build1 — centos 7, her vil være buildbot master (master) og en af arbejderne (worker)
  • vm-srv-build2 — debian 10, til at bygge DEB pakker
  • vm-srv-build3 — windows 10, til at bygge, som I selv forstår.

Vi vil samle Rac GUI — den grafiske grænseflade til 1C rac for styring af serverklynger. For linux vil der blive brugt de indbyggede værktøjer til hvert operativsystem, mens exe-filen til windows vil blive bygget fra tcl-scriptet ved hjælp af freewrap.

Installation

GNU/Linux

Der er tilstrækkelig dokumentation til installationen på nettet. 1,2. Og den giver ikke store problemer:
Til masteren:

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

For "arbejderne" er dette tilstrækkeligt:

pip3 install buildbot-worker

Selvfølgelig vil det være mere korrekt at bygge pakker til hvert operativsystem, men det falder uden for artiklens rammer. Vi vil også udelade beskrivelsen af opsætningen af containerne til arbejdet, jeg vil kun nævne, at jeg bruger ProxMox VE. Derudover skal man installere pakkerne, der er nødvendige for bygningen til hver platform (centos: rpmdevtools osv.; debian: build-essential, dh-make, pbuilder osv.)

Byggede projekter og services i buildbot vil køre som en ikke-privilegeret bruger, så det er nødvendigt at oprette denne bruger på alle værter, der deltager i processen:


adduser buildbot

Dernæst skal vi konfigurere automatisk opstart af tjenesterne på hver af værterne (containerne):

Systemd-enhed til at starte masteren:

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

og "arbejderen"

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

Da alle scripts (i vores tilfælde) ligger i /usr/local/, skal vi inkludere stien til dem i miljøvariablerne:

nano /root/.bash_profile

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

Derefter kan der oprettes en kataloginfrastruktur for "arbejdere" (på alle værter), hvilket kræver, at man registrerer sig som brugeren buildbot og udfører følgende kommandoer:

På den første vært 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 anden vært 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å arbejderserverne kan buildbot-worker-tjenesten startes.

systemctl start buildbot-worker

MS Windows

Som "arbejder" til bygning under Windows vil der blive brugt en virtuel maskine med den nyeste version af Win10.
For at arbejdet kan udføres, er der behov for:

Når alt det ovenstående er installeret, kan selve buildbot installeres:

pip install buildbot-worker

Lad os oprette en arbejdsmappe.

md c:worker

Og lad os starte den.

buildbot-worker start c:worker

Hvis alt fungerer (se log c:workertwistd.log), kan vi registrere vores "arbejder" som en tjeneste ved at tilføje et punkt i registreringsdatabasen med arbejdsbiblioteket (kommandoerne udføres i PowerShell, der er åbnet som 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

Og man kan starte tjenesten.

Start-Service buildbot

Det var alt for "arbejdere"; de kan nu stå ubeskedne, da al kontrol foregår fra master.

Konfiguration af master

For at begynde skal vi oprette en infrastruktur for master (på den primære vært), hvilket kræver, at man registrerer sig som brugeren buildbot og udfører følgende kommandoer:

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

For de færdige pakker opretter vi en mappe til builds.

mkdir /home/buildbot/builds

I mappen /home/buildbot/master/ er filen master.cfg blevet oprettet. Denne fil indeholder Python-kode og beskriver alle systemets arbejdsmekanismer, som vi vil arbejde med fremover.

nano /home/buildbot/master/master.cfg

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

c= BuildmasterConfig ={}

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

# Angivelse til master om hvilket repository der skal overvåges
c['change_source'] = []
c['change_source'].append(changes.GitPoller(
       repourl = 'https://bitbucket.org/svk28/rac-gui.git',
       project = 'Rac-GUI',
       branches = True,
       pollInterval = 60
      )
)

# Tjeneste til at starte bygningen
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
# Bygning af RPM-pakke
 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)
)

For at automatisere bygningen af pakker i forskellige versioner, så man ikke skal ind i koden i master.cfg-filen, er der i hovedprogrammet rac_gui.tcl tilføjet linjer med den aktuelle version og udgivelse:

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

Og baseret på disse linjer vil buildbot nummerere pakkerne. For at udtrække data anvendes kommandoen grep i konsollen. I buildbot er det ikke muligt at definere variabler for 'arbejdere' (i hvert fald har jeg ikke fundet ud af hvordan). Ejendommene (property) tjener dette formål. Det vil sige, at vi i byggeprocessen tilføjer trin til at definere versionen og udgivelsen, og tilsvarende, indstiller vi egenskaberne version og release. Egenskaber kan indstilles på forskellige måder, i dette tilfælde er det kaldet af en konsolkommando:

# Добавим определение версии из основного файла
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 opnåede værdier kan indsættes ved at kalde 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"]
       )
)

Her skal det bemærkes, at da værten også bruges til manuel bygning af pakker, vil bygningen foregå efter standardveje.

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

For at sætte korrekte udgivelses- og versionsnumre bruges kaldet til standard sed, d.v.s. kommandoen erstatter værdierne i spec-filen med de nødvendige

# меняем версию
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ærdigbyggede pakke og arkiv med kildekoden kopieres til master. Men det er også muligt straks at kopiere fra arbejdsfilerne til sit eget repository eller website.

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

Lad os starte processen med at kopiere de byggede pakker til hosting via FTP på master. Dette gøres ved hjælp af script 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 er færdige med RPM. Nu går vi videre til beskrivelsen af DEB-pakkeopbygningsalgoritmen. Da opbygningsprocesserne for forskellige systemer er uafhængige af hinanden, vil mange trin blive gentaget.


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

# Tilføj versiondefinition fra hovedfilen
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"
       )
)

# Tilføj release-definition fra hovedfilen
rac_gui_build_DEB.addStep(
       steps.SetPropertyFromCommand(
       command="grep release rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
       )
)

# Omdøb den udførelige fil
    rac_gui_build_DEB.addStep(steps.ShellCommand(
       command=["mv", "rac_gui.tcl", "racgui"]))

For RPM-pakken udføres nogle af de følgende procedurer af rpm selv under opbygningen, og de er beskrevet i spec'en, mens det for Debian skal gøres her:

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

Og med DEB er vi færdige, nu til 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)
)

Da grep og sed normalt ikke findes i Windows (eller gør de?), vil vi bruge 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),
]

Til at informere om status på opbygningsprocessen vil vi bruge elektrisk post.


c['services'] = []

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

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

c['services'].append(mailNotifier)

# Grundlæggende opsætning af master
c['title'] = "Byggeprocessen"
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"
}

Gem filen, og så kan vi prøve at starte mastertjenesten:

systemctl restart buildbot-master

I loggen kan vi kontrollere, at alt er i orden med konfigurationen og at alt fungerer som det skal. Alle vores arbejdere bør nu tilslutte sig, hvilket vil blive glædeligt meddelt i loggen »»'/home/buildbot/master/twistd.log»».

 2019-07-24 16:50:35+0300 [-] Indlæser buildbot.tac...
 2019-07-24 16:50:35+0300 [-] Indlæst.
 2019-07-24 16:50:35+0300 [-] twistd 19.2.1 (\usr\bin\python3.6 3.6.8) starter op.
 2019-07-24 16:50:35+0300 [-] reaktorklasse: twisted.internet.epollreactor.EPollReactor.
 2019-07-24 16:50:35+0300 [-] Starter BuildMaster -- buildbot.version: 2.3.1
 2019-07-24 16:50:35+0300 [-] Indlæser konfiguration fra '\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 og nyere] `buildbotNetUsageData` er ikke konfigureret og standardværdien er grundlæggende.
        Denne parameter hjælper buildbot-udviklingsteamet med at forstå installationsbasen.
        Der indsamles ingen personlige oplysninger.
        Kun installationssoftwareversionsoplysninger og brug af plugins sendes.
        Du kan "fravælge" ved at sætte denne variabel til None.
        Eller "tilvælge" for flere oplysninger ved at sætte den til "fuld".

 2019-07-24 16:50:36+0300 [-] Opsætter database med URL 'sqlite:\state.sqlite'
 2019-07-24 16:50:36+0300 [-] indstiller databasejournalstatus til 'wal'
 2019-07-24 16:50:36+0300 [-] tilføjer 1 ny service, fjerner 0
 2019-07-24 16:50:36+0300 [-] tilføjer 1 ny change_source, fjerner 0
 2019-07-24 16:50:36+0300 [-] gitpoller: bruger arbejdsmappe '\home\buildbot\master\gitpoller-work'
 2019-07-24 16:50:36+0300 [-] tilføjer 3 nye byggere, fjerner 0
 2019-07-24 16:50:36+0300 [-] tilføjer 1 ny planlægger, fjerner 0
 2019-07-24 16:50:36+0300 [-] initialiserer www-plugin 'waterfall_view'
 2019-07-24 16:50:36+0300 [-] initialiserer www-plugin 'console_view'
 2019-07-24 16:50:36+0300 [-] initialiserer www-plugin 'grid_view'
 2019-07-24 16:50:36+0300 [-] NOTE: www-plugin 'sitenav' er installeret, men ikke konfigureret
 2019-07-24 16:50:36+0300 [-] initialiserer www-plugin 'waterfall_view'
 2019-07-24 16:50:36+0300 [-] initialiserer www-plugin 'console_view'
 2019-07-24 16:50:36+0300 [-] initialiserer www-plugin 'grid_view'
 2019-07-24 16:50:36+0300 [-] NOTE: www-plugin 'sitenav' er installeret, men ikke konfigureret
 2019-07-24 16:50:36+0300 [-] BuildbotSite starter på 80
 2019-07-24 16:50:36+0300 [-] Starter fabrik 
 2019-07-24 16:50:36+0300 [-] tilføjer 3 nye arbejdere, fjerner 0
 2019-07-24 16:50:36+0300 [-] PBServerFactory starter på 4000
 2019-07-24 16:50:36+0300 [-] Starter fabrik 
 2019-07-24 16:50:37+0300 [-] BuildMaster kører
 2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: sender {'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] arbejder 'CentOS' tilslutter fra IPv4Address(type='TCP', host='127.0.0.1', port=37332)
 2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Fik workerinfo fra 'CentOS'
 2019-07-24 16:50:37+0300 [-] bot tilsluttet
 2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Arbejder CentOS tilsluttet til Rac-GUI-RPM-builder
 2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: buildbot.net sagde: ok
 2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] arbejder 'Windows-10' tilslutter fra IPv4Address(type='TCP', host='192.168.5.145', port=49831)
 2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] Fik workerinfo fra 'Windows-10'
 2019-07-24 16:50:40+0300 [-] bot tilsluttet
 2019-07-24 16:50:40+0300 [Broker,1,192.168.55.15] Arbejder Windows-10 tilsluttet til Rac-GUI-WIN-builder
 2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] arbejder 'Debian-10' tilslutter fra IPv4Address(type='TCP', host='192.168.5.9', port=44430)
 2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Fik workerinfo fra 'Debian-10'
 2019-07-24 16:50:41+0300 [-] bot tilsluttet
 2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Arbejder Debian-10 tilsluttet til Rac-GUI-DEB-builder

Opsætningen er nu afsluttet. Den aktuelle tilstand kan ses gennem webgrænsefladen, hvor man også kan finde byggefejl, genstarte en fastlåst proces, hvis noget skulle gå galt, osv.

Umiddelbart efter opstart af vores arbejdere kan man se dem gennem menuen „Builds“ -> „Workers“

Buildbot i eksempler

Efter den første byggeproces (dvs. ændringer i Git-repositoriet) vil tilstanden for processerne blive vist på den første side.

Buildbot i eksempler

Hvis man klikker med musen på den ønskede linje, åbnes en side med den aktuelle tilstand af den pågældende proces, hvor man kan se, hvad der sker, hvilke fejl osv.

Buildbot i eksempler

Hele konfigurationen af masteren kan hentes her

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

# Tjeneste for at starte byggeprocessen
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)
    )

# Tilføj versiondefinering fra hovedfilen
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"
    )
)

# Tilføj release-definition fra hovedfilen
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'
    ))

# Kopier filen til 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)
    )

# Tilføj versiondefinering fra hovedfilen
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"
    )
)

# Tilføj release-definition fra hovedfilen
rac_gui_build_DEB.addStep(
    steps.SetPropertyFromCommand(
    command="grep release rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
    )
)

# Omdøb eksekverbar fil
rac_gui_build_DEB.addStep(steps.ShellCommand(
    command=["mv", "rac_gui.tcl", "racgui"]))

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

# Ændre stier til filer
rac_gui_build_DEB.addStep(steps.ShellCommand(
    command=["sed", "-i", "s+[pwd]+/usr/share/rac-gui+g", "racgui"]))

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

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

# Kopier filen til 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)
    )

# Tilføj versiondefinering fra hovedfilen
rac_gui_build_WIN.addStep(
    steps.SetPropertyFromCommand(
    command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'version:') -split 's')[2]",
    property="version"
    )
)

# Tilføj release-definition fra hovedfilen
rac_gui_build_WIN.addStep(
    steps.SetPropertyFromCommand(
    command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'release:') -split 's')[2]",
    property="release"
    )
)

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

# Pak det, der er blevet lavet
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"]))

# Kopier til 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")
    )
)

# Kopier filen til 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>Byggestatus: {{ summary }}</h4>
<p> Bruger: {{ workername }}</p>
{% for step in build['steps'] %}
<p> {{ step['name'] }}: {{ step['result'] }}</p>
{% endfor %}
<p><b> -- 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'] = "Byggeprocessen"
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"
}

Materialer

I forberedelsen af artiklen blev der brugt følgende materialer:

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster