Ho dovuto configurare il processo di build e consegna di pacchetti software dal repository Git al sito. E vedendo, non molto tempo fa, un articolo su Habr riguardante buildbot (link alla fine), ho deciso di provarlo e applicarlo.
Poiché buildbot è un sistema distribuito, sarà logico creare un host di build separato per ogni architettura e sistema operativo. Nel nostro caso, si tratterà di contenitori LXC (per Linux) e qemu (per Windows):
- vm-srv-build1 — centos 7, qui ci sarà il master di buildbot e uno dei worker
- vm-srv-build2 — debian 10, per la costruzione di pacchetti DEB
- vm-srv-build3 — windows 10, per la costruzione, sapete già per cosa
Costruiremo — interfaccia grafica per 1C rac per gestire un cluster di server. Per Linux verranno utilizzati gli strumenti predefiniti per ogni OS, mentre per costruire un file exe per Windows da uno script tcl si utilizza .
Installazione
GNU/Linux
Per l'installazione, ci sono molte documentazioni online. ,E non causa problemi particolari:
Per il 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-dateutilPer i "worker", è sufficiente questo:
pip3 install buildbot-workerCertamente, sarebbe più corretto compilare i pacchetti per ciascun sistema operativo, ma questo esula dallo scopo dell'articolo. Inoltre, salteremo la descrizione della configurazione dei container per il funzionamento, segnalo solo che utilizzo ProxMox VE. È inoltre necessario installare i pacchetti richiesti per la compilazione per ciascuna distribuzione (centos: rpmdevtools, ecc.; debian: build-essential, dh-make, pbuilder, ecc.)
La compilazione dei progetti e i servizi buildbot verranno eseguiti con un utente non privilegiato, quindi è necessario crearlo su tutti gli host coinvolti nel processo:
adduser buildbotSuccessivamente, configureremo l'avvio automatico dei servizi, rispettivamente su ciascuno degli host (container):
Unità Systemd per avviare il master:
touch /etc/systemd/buildbot-master.service
[Unit]
Description=Servizio master BuildBot
After=network.target
[Service]
User=buildbot
Group=buildbot
WorkingDirectory=/home/buildbot/master
ExecStart=/usr/local/bin/buildbot start --nodaemon
ExecReload=/bin/kill -HUP $MAINPID
[Install]
WantedBy=multi-user.targete «worker»
touch /etc/systemd/buildbot-worker.service
[Unit]
Description=Servizio worker BuildBot
After=network.target
[Service]
User=buildbot
Group=buildbot
WorkingDirectory=/home/buildbot/worker
ExecStart=/usr/local/bin/buildbot-worker start --nodaemon
[Install]
WantedBy=buildbot-master.servicePoiché tutti gli script (nel nostro caso) si trovano in /usr/local/, è necessario specificare il percorso per loro nelle variabili d'ambiente:
nano /root/.bash_profile
PATH=$PATH:$HOME/.local/bin:$HOME/bin:/usr/local/binDopo ciò, puoi creare la struttura delle directory per i "lavoratori" (su tutti gli host), registrandoti come utente buildbot ed eseguendo i seguenti comandi:
Sull'host principale vm-srv-build1:
su - buildbot
mkdir /home/buildbot/worker
cd ~
buildbot-worker create-worker --umask=0o22 --keepalive=60 worker vm-srv-build1:4000 CentOS 123456Sull'host secondario 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 123456Sugli host lavoratori, il servizio buildbot-worker può essere avviato
systemctl start buildbot-workerMS Windows
Come "lavoratore" per la compilazione su Windows, verrà utilizzata una macchina virtuale con l'ultima versione di Win10.
Per operare, avrai bisogno di:
- Per installare varie librerie in Python, è stato necessario scaricare
- 7Zip
Dopo che tutto il sopra elencato è stato installato, puoi installare anche il buildbot:
pip install buildbot-workerCreiamo la directory di lavoro
md c:workerE avviamo
buildbot-worker start c:workerSe tutto funziona (vedi log c:workertwistd.log), puoi registrare il tuo "lavoratore" come servizio, aggiungendo una voce nel registro con la directory di lavoro (i comandi devono essere eseguiti in powershell aperto come amministratore):
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
E si può avviare il servizio
Start-Service buildbotCon i "lavoratori" è tutto, da qui in poi possono rimanere inalterati, tutto il controllo avviene dal master.
Configurazione del master
Per prima cosa, creiamo l'infrastruttura per il master (sull'host principale), per farlo ci registriamo come utente buildbot e eseguiamo i seguenti comandi:
su - buildbot
mkdir /home/buildbot/master
cd ~
buildbot create-master masterPer i pacchetti pronti, creiamo una cartella builds
mkdir /home/buildbot/buildsNella cartella /home/buildbot/master/ è stato creato il file master.cfg. Questo file è un codice Python e contiene la descrizione di tutti i meccanismi di funzionamento del sistema, e lavoreremo con esso in seguito.
nano /home/buildbot/master/master.cfgimport os, re
from buildbot.plugins import steps, util, schedulers, worker, changes, reporters
c = BuildmasterConfig = {}
# Descrizione dei nostri lavoratori.
c['workers'] = [ worker.Worker('CentOS', '123456'), worker.Worker('Debian-10', '123456'), worker.Worker('Windows-10', '123456')]
c['protocols'] = {'pb': {'port': 4000}}
# Indica al master quale repository monitorare
c['change_source'] = []
c['change_source'].append(changes.GitPoller(
repourl = 'https://bitbucket.org/svk28/rac-gui.git',
project = 'Rac-GUI',
branches = True,
pollInterval = 60
)
)
# Servizio di avvio della 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
######################################3
# Build del pacchetto RPM
rac_gui_build_RPM = util.BuildFactory()
rac_gui_build_RPM.addStep(steps.Git(
repourl = 'https://bitbucket.org/svk28/rac-gui.git',
workdir = 'rac-gui',
haltOnFailure = True,
submodules = True,
mode='full',
progress = True)
)Per automatizzare la costruzione di pacchetti di diverse versioni, evitando di dover modificare il codice del file master.cfg, nel principale script del programma rac_gui.tcl sono state aggiunte righe con la versione corrente e il rilascio:
######################################################
# Rac GUI
...
# version: 1.0.3
# release: 1E sulla base di queste righe, buildbot numererà i pacchetti. Per estrarre i dati, si utilizza la chiamata console grep. In buildbot non è possibile definire variabili per i "lavoratori" così facilmente (almeno, non ho trovato come). A questo scopo servono le proprietà. Cioè, nel processo di build, aggiungiamo passaggi per definire la versione e il rilascio e quindi impostiamo le proprietà version e release. Le proprietà possono essere impostate in vari modi, in questo caso si tratta di una chiamata a un comando della console:
# Добавим определение версии из основного файла
rac_gui_build_RPM.addStep(
steps.SetPropertyFromCommand(
command="grep version ../rac-gui/rac_gui.tcl | grep -oE 'b[0-9]{1,2}.[0-9]{1,2}.[0-9]{1,2}b'", property="version"
)
)
# Добавим определение релиза из основного файла
rac_gui_build_RPM.addStep(
steps.SetPropertyFromCommand(
command="grep release ../rac-gui/rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
)
)I valori ottenuti possono essere inseriti tramite la chiamata 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"]
)
)È importante notare che, poiché l'host viene utilizzato anche per la build manuale dei pacchetti, la compilazione seguirà i percorsi standard.
# Копируем spec
rac_gui_build_RPM.addStep(steps.ShellCommand(
command=["cp", "../rac-gui/rac_gui.spec", "/home/buildbot/rpmbuild/SPECS/rac_gui.spec"]))Per impostare correttamente i numeri di rilascio e versione si utilizza la chiamata standard sed, cioè il comando sostituisce i valori all'interno del file spec con quelli necessari.
# меняем версию
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'
)
)Il pacchetto assemblato completo e l'archivio con i sorgenti vengono copiati sul master. Ma è possibile anche copiare direttamente i file di lavoro nel proprio repository o sul sito.
# Скопируем файл на мастер
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")
)
)Avviamo sul master il processo di copia dei pacchetti assemblati sul hosting via FTP. A questo scopo si utilizza su 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")]
)
)Abbiamo concluso con RPM. Ora passiamo alla descrizione dell'algoritmo per la creazione del pacchetto DEB. Poiché i processi di creazione dei pacchetti per sistemi diversi sono indipendenti tra loro, molti passaggi si ripeteranno.
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)
)
# Aggiungiamo la definizione della versione dal file principale
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"
)
)
# Aggiungiamo la definizione del rilascio dal file principale
rac_gui_build_DEB.addStep(
steps.SetPropertyFromCommand(
command="grep release rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
)
)
# Rinominiamo il file eseguibile
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["mv", "rac_gui.tcl", "racgui"]))Per il pacchetto RPM, parte delle seguenti procedure è gestita da rpm durante la compilazione e sono descritte all'interno dello spec, per Debian è necessario farlo qui:
# Поменяем пути к библиотекам
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")]
)
)E con il DEB è tutto, ora tocca a 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)
)Poiché in Windows non ci sono grep e sed (o ci sono?), utilizzeremo 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),
]Per notificare lo stato del processo di compilazione utilizzeremo la posta elettronica.
c['services'] = []
template=u'''
<h4>Stato della costruzione: {{ summary }}</h4>
<p> Lavoratore utilizzato: {{ workername }}</p>
{% for step in build['steps'] %}
<p> {{ step['name'] }}: {{ step['result'] }}</p>
{% endfor %}
<p><b> -- Il Buildbot</b></p>
'''
mailNotifier = reporters.MailNotifier(fromaddr="builder@domain.it",
sendToInterestedUsers=False,
mode=('all'),
extraRecipients=["admin@domain.it"],
relayhost="mail.domain.it",
smtpPort=587,
smtpUser="builder@domain.it",
smtpPassword="******",
messageFormatter=reporters.MessageFormatter(
template=template, template_type='html',
wantProperties=True, wantSteps=True))
c['services'].append(mailNotifier)
# Impostazioni principali del master
c['title'] = "Il processo di costruzione"
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"
}Salviamo il file e possiamo provare a lanciare il servizio master:
systemctl restart buildbot-masterNel log verificheremo che la configurazione sia a posto e tutto funzioni regolarmente. Tutti i nostri lavoratori devono ora connettersi, e nel log »»’/home/buildbot/master/twistd.log»»’ sarà comunicato con gioia:
2019-07-24 16:50:35+0300 [-] Caricamento buildbot.tac...
2019-07-24 16:50:35+0300 [-] Caricato.
2019-07-24 16:50:35+0300 [-] twistd 19.2.1 (/usr/bin/python3.6 3.6.8) avviato.
2019-07-24 16:50:35+0300 [-] classe reactor: twisted.internet.epollreactor.EPollReactor.
2019-07-24 16:50:35+0300 [-] Avvio BuildMaster -- buildbot.version: 2.3.1
2019-07-24 16:50:35+0300 [-] Caricamento della configurazione da '/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 e successivi] `buildbotNetUsageData` non è configurato e predefinito a base.
Questo parametro aiuta il team di sviluppo di buildbot a comprendere la base di installazione.
Non vengono raccolte informazioni personali.
Vengono inviati solo informazioni sulla versione del software di installazione e sull'uso dei plugin.
Puoi `disattivarti` impostando questa variabile su None.
Oppure `attivarti` per ulteriori informazioni impostandola su "full".
2019-07-24 16:50:36+0300 [-] Configurazione del database con URL 'sqlite:/state.sqlite'
2019-07-24 16:50:36+0300 [-] impostazione della modalità diario del database su 'wal'
2019-07-24 16:50:36+0300 [-] aggiunta di 1 nuovo servizio, rimozione 0
2019-07-24 16:50:36+0300 [-] aggiunta di 1 nuova sorgente di cambiamenti, rimozione 0
2019-07-24 16:50:36+0300 [-] gitpoller: utilizzo della directory di lavoro '/home/buildbot/master/gitpoller-work'
2019-07-24 16:50:36+0300 [-] aggiunta di 3 nuovi builder, rimozione 0
2019-07-24 16:50:36+0300 [-] aggiunta di 1 nuovo scheduler, rimozione 0
2019-07-24 16:50:36+0300 [-] inizializzazione del plugin www 'waterfall_view'
2019-07-24 16:50:36+0300 [-] inizializzazione del plugin www 'console_view'
2019-07-24 16:50:36+0300 [-] inizializzazione del plugin www 'grid_view'
2019-07-24 16:50:36+0300 [-] NOTA: il plugin www 'sitenav' è installato ma non configurato
2019-07-24 16:50:36+0300 [-] inizializzazione del plugin www 'waterfall_view'
2019-07-24 16:50:36+0300 [-] inizializzazione del plugin www 'console_view'
2019-07-24 16:50:36+0300 [-] inizializzazione del plugin www 'grid_view'
2019-07-24 16:50:36+0300 [-] NOTA: il plugin www 'sitenav' è installato ma non configurato
2019-07-24 16:50:36+0300 [-] BuildbotSite avviato sulla porta 80
2019-07-24 16:50:36+0300 [-] Avvio della factory <buildbot.www.service.BuildbotSite object at 0x7fe31c2657b8>
2019-07-24 16:50:36+0300 [-] aggiunta di 3 nuovi lavoratori, rimozione 0
2019-07-24 16:50:36+0300 [-] PBServerFactory avviata sulla porta 4000
2019-07-24 16:50:36+0300 [-] Avvio della factory <twisted.spread.pb.PBServerFactory object at 0x7fe31c147470>
2019-07-24 16:50:37+0300 [-] BuildMaster è in esecuzione
2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: invio {'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] lavoratore 'CentOS' attaching da IPv4Address(type='TCP', host='127.0.0.1', port=37332)
2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Ricevuto workerinfo da 'CentOS'
2019-07-24 16:50:37+0300 [-] bot attached
2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Lavoratore CentOS attaccato a Rac-GUI-RPM-builder
2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: buildbot.net ha detto: ok
2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] lavoratore 'Windows-10' attaching da IPv4Address(type='TCP', host='192.168.5.145', port=49831)
2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] Ricevuto workerinfo da 'Windows-10'
2019-07-24 16:50:40+0300 [-] bot attached
2019-07-24 16:50:40+0300 [Broker,1,192.168.55.15] Lavoratore Windows-10 attaccato a Rac-GUI-WIN-builder
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] lavoratore 'Debian-10' attaching da IPv4Address(type='TCP', host='192.168.5.9', port=44430)
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Ricevuto workerinfo da 'Debian-10'
2019-07-24 16:50:41+0300 [-] bot attached
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Lavoratore Debian-10 attaccato a Rac-GUI-DEB-builderLa configurazione è stata completata. È possibile visualizzare lo stato attuale tramite la web interface, dove è possibile anche controllare gli errori di compilazione, interrompere processi bloccati, e così via.
Subito dopo l'avvio dei nostri lavoratori, puoi controllare attraverso il menu 'Builds' -> 'Workers'.

Dopo il primo processo di compilazione (cioè, modifiche nel repository Git), apparirà lo stato dei processi nella prima pagina.

Cliccando sulla riga desiderata si aprirà una pagina con lo stato attuale di questo processo, dove si può vedere cosa sta succedendo, gli errori, ecc.

Puoi trovare l'intera configurazione del master qui.
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
))
# Servizio di avvio costruzione
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)
)
# Aggiungeremo la definizione della versione dal file principale
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"
)
)
# Aggiungeremo la definizione del rilascio dal file principale
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'
))
# Copiamo il file sul 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)
)
# Aggiungeremo la definizione della versione dal file principale
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"
)
)
# Aggiungeremo la definizione del rilascio dal file principale
rac_gui_build_DEB.addStep(
steps.SetPropertyFromCommand(
command="grep release rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
)
)
# Rinomineremo il file eseguibile
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["mv", "rac_gui.tcl", "racgui"]))
# Cambieremo i percorsi delle librerie
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["sed", "-i", "s+^set dir(lib)+set dir(lib) /usr/share/rac-gui/lib ;#+g", "racgui"]))
# Cambieremo i percorsi dei file
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["sed", "-i", "s+[pwd]+/usr/share/rac-gui+g", "racgui"]))
# Archivieremo i sorgenti
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["tar", "czf", util.Interpolate("../rac-gui_%(prop:version)s.orig.tar.gz"), "."]))
# Prepariamo il pacchetto
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["dpkg-buildpackage"]))
# Copiamo il file sul 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)
)
# Aggiungeremo la definizione della versione dal file principale
rac_gui_build_WIN.addStep(
steps.SetPropertyFromCommand(
command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'version:') -split 's')[2]",
property="version"
)
)
# Aggiungeremo la definizione del rilascio dal file principale
rac_gui_build_WIN.addStep(
steps.SetPropertyFromCommand(
command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'release:') -split 's')[2]",
property="release"
)
)
# Creeremo il file eseguibile
rac_gui_build_WIN.addStep(steps.ShellCommand(
command=["c:binfreewrap.exe", "rac_gui.tcl"]))
# Compattiamo il risultato
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"]))
# Copiamo sul 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")
)
)
# Copiamo il file sul 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>Stato della costruzione: {{ summary }}</h4>
<p> Lavoratore utilizzato: {{ workername }}</p>
{% for step in build['steps'] %}
<p> {{ step['name'] }}: {{ step['result'] }}</p>
{% endfor %}
<p><b> -- Il 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'] = "Il processo di costruzione"
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"
}Materiali
Per la preparazione dell'articolo sono stati utilizzati i seguenti materiali:
- E la documentazione del prodotto.
Fonte: habr.com
