Eu precisei configurar o processo de construção e entrega de pacotes de programas do repositório Git para o site. E, ao ver, não faz muito tempo, aqui no Habr um artigo sobre buildbot (link no final), decidi experimentá-lo e aplicá-lo.
Como o buildbot é um sistema distribuído, seria lógico ter um host de construção separado para cada arquitetura e sistema operacional. No nosso caso, serão contêineres LXC (no caso do linux) e qemu (no caso do windows):
- vm-srv-build1 — centos 7, aqui estará o mestre (master) do buildbot e um dos trabalhadores (worker)
- vm-srv-build2 — debian 10, para construir pacotes DEB
- vm-srv-build3 — windows 10, para construção, vocês entendem para quê
Vamos construir — interface gráfica para 1С rac para gerenciamento de um cluster de servidores. No linux, usaremos as ferramentas padrão para cada SO, para construir arquivos exe no windows a partir de um script tcl utilizamos .
Instalação
GNU/Linux
Há muitas informações na rede sobre instalação e documentação. ,E não causa muitos problemas:
Para o mestre:
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-dateutilPara os "trabalhadores", é suficiente isso:
pip3 install buildbot-workerClaro, seria mais correto construir pacotes para cada SO, mas isso não faz parte do artigo. Também ignoraremos a descrição da configuração dos contêineres para funcionamento, observando apenas que uso o ProxMox VE. E ainda será necessário instalar os pacotes necessários para construção em cada sistema (centos: rpmdevtools, etc.; debian: build-essential, dh-make, pbuilder, etc.)
Os projetos de construção e os serviços do buildbot serão iniciados sob o nome de um usuário não privilegiado, portanto é necessário criá-lo em todos os hosts envolvidos no processo:
adduser buildbotEm seguida, configuraremos a inicialização automática dos serviços, respectivamente em cada um dos hosts (contêineres):
Unidade Systemd para iniciar o mestre:
touch /etc/systemd/buildbot-master.service
[Unit]
Description=Serviço mestre do 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 do "trabalhador"
touch /etc/systemd/buildbot-worker.service
[Unit]
Description=Serviço trabalhador do BuildBot
After=network.target
[Service]master
User=buildbot
Group=buildbot
WorkingDirectory=/home/buildbot/worker
ExecStart=/usr/local/bin/buildbot-worker start --nodaemon
[Install]
WantedBy=buildbot-master.serviceComo todos os scripts (no nosso caso) estão em /usr/local/, devemos adicionar o caminho a eles nas variáveis de ambiente:
nano /root/.bash_profile
PATH=$PATH:$HOME/.local/bin:$HOME/bin:/usr/local/binApós isso, você pode criar a infraestrutura de diretórios para os 'trabalhadores' (em todos os hosts), para isso, registre-se como o usuário buildbot e execute os seguintes comandos:
No primeiro host vm-srv-build1:
su - buildbot
mkdir /home/buildbot/worker
cd ~
buildbot-worker create-worker --umask=0o22 --keepalive=60 worker vm-srv-build1:4000 CentOS 123456No segundo host vm-srv-build2:
su - buildbot
mkdir /home/buildbot/worker
cd ~
buildbot-worker create-worker --umask=0o22 --keepalive=60 worker vm-srv-build1:4000 Debian-10 123456Nos hosts trabalhadores, é possível iniciar o serviço buildbot-worker
systemctl start buildbot-workerMS Windows
Como 'trabalhador' para a construção no Windows, será utilizada uma máquina virtual com a última versão do Win10.
Para isso, será necessário:
- Para instalar diversas dependências em Python, foi necessário baixar
- 7Zip
Após tudo isso ter sido instalado, você pode instalar o próprio buildbot:
pip install buildbot-workerVamos criar o diretório de trabalho
md c:workerE iniciar
buildbot-worker start c:workerSe tudo estiver funcionando (veja o log c:workertwistd.log), você pode registrar nosso 'trabalhador' como um serviço, adicionando um item no registro com o diretório de trabalho (os comandos são executados no PowerShell iniciado como administrador):
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 você pode iniciar o serviço
Start-Service buildbotSobre os 'trabalhadores' é isso, não precisa fazer mais nada, toda a gestão é feita a partir do mestre.
Configuração do Mestre
Para começar, vamos criar a infraestrutura para o mestre (no host principal), para isso, registre-se como o usuário buildbot e execute os seguintes comandos:
su - buildbot
mkdir /home/buildbot/master
cd ~
buildbot create-master masterPara os pacotes prontos, criaremos o diretório builds
mkdir /home/buildbot/buildsNo diretório /home/buildbot/master/ foi criado o arquivo master.cfg. Este arquivo representa código em Python e contém a descrição de todos os mecanismos de funcionamento do sistema, e é com ele que iremos trabalhar adiante.
nano /home/buildbot/master/master.cfgimport os, re
from buildbot.plugins import steps, util, schedulers, worker, changes, reporters
c= BuildmasterConfig ={}
# Descrição dos nossos trabalhadores.
c['workers'] = [ worker.Worker('CentOS', '123456'), worker.Worker('Debian-10', '123456'), worker.Worker('Windows-10', '123456')]
c['protocols'] = {'pb': {'port': 4000}}
# Indicação ao mestre de qual repositório monitorar
c['change_source'] = []
c['change_source'].append(changes.GitPoller(
repourl = 'https://bitbucket.org/svk28/rac-gui.git',
project = 'Rac-GUI',
branches = True,
pollInterval = 60
)
)
# Serviço de inicialização de construção
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
# Construção do pacote 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)
)Para automatizar a construção de pacotes de diferentes versões, evitando a necessidade de editar o código do arquivo master.cfg, o script principal do programa rac_gui.tcl foi atualizado com as linhas da versão e lançamento atuais:
######################################################
# Rac GUI
...
# version: 1.0.3
# release: 1E com base nessas linhas, o buildbot numera os pacotes. Para extrair os dados, é utilizado o comando console grep. No buildbot, não é possível definir variáveis para os "trabalhadores" (pelo menos, eu não encontrei essa opção). Para isso, utilizamos propriedades (property). Ou seja, no processo de construção, adicionamos etapas para determinar a versão e o lançamento, estabelecendo assim as propriedades version e release. As propriedades podem ser definidas de várias maneiras, e neste caso, utilizamos o comando da 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"
)
)Os valores obtidos podem ser inseridos chamando 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"]
)
)Vale notar que, como o host é utilizado também para construção manual de pacotes, a construção seguirá os caminhos padrão.
# Копируем spec
rac_gui_build_RPM.addStep(steps.ShellCommand(
command=["cp", "../rac-gui/rac_gui.spec", "/home/buildbot/rpmbuild/SPECS/rac_gui.spec"]))Para definir corretamente os números de versão e lançamento, isso é feito através do comando padrão sed, que substitui os valores dentro do arquivo spec pelos necessários.
# меняем версию
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'
)
)O pacote construído e o arquivo fonte são copiados para o mestre. Mas também é possível copiar diretamente do arquivo de trabalho para o seu repositório ou site.
# Скопируем файл на мастер
rac_gui_build_RPM.addStep(
steps.FileUpload(
workersrc=util.Interpolate("/home/buildbot/rpmbuild/RPMS/noarch/rac-gui-%(prop:version)s-%(prop:release)s.noarch.rpm"),
masterdest=util.Interpolate("/home/buildbot/builds/rac-gui-%(prop:version)s-%(prop:release)s.noarch.rpm")
)
)
rac_gui_build_RPM.addStep(
steps.FileUpload(
workersrc=util.Interpolate("/home/buildbot/rpmbuild/SOURCES/rac-gui-%(prop:version)s-%(prop:release)s.tar.gz"),
masterdest=util.Interpolate("/home/buildbot/builds/rac-gui-%(prop:version)s-%(prop:release)s.tar.gz")
)
)Vamos iniciar no mestre o processo de cópia dos pacotes construídos para o hosting via FTP. Para isso, utilizamos em 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")]
)
)Terminamos com o RPM. Agora vamos descrever o algoritmo de construção do pacote DEB. Como os processos de construção de pacotes para diferentes sistemas são independentes entre si, muitos passos se repetirã.
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)
)
# Vamos adicionar a definição da versão a partir do arquivo principal
rac_gui_build_DEB.addStep(
steps.SetPropertyFromCommand(
command="grep version rac_gui.tcl | grep -oE 'b[0-9]{1,2}.[0-9]{1,2}.[0-9]{1,2}b'", property="version"
)
)
# Vamos adicionar a definição da release a partir do arquivo principal
rac_gui_build_DEB.addStep(
steps.SetPropertyFromCommand(
command="grep release rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
)
)
# Renomearemos o arquivo executável
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["mv", "rac_gui.tcl", "racgui"]))Para o pacote RPM, parte dos procedimentos abaixo é realizada pelo próprio rpm durante a construção e está descrita no spec, para o Debian, é necessário fazer isso aqui:
# Поменяем пути к библиотекам
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 com o DEB terminado, agora é a vez do 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)
)Como o Windows não tem o grep e sed por padrão (ou tem?), vamos usar o 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),
]Para notificar sobre o estado do processo de construção, vamos usar e-mail elétrico
c['services'] = []
template=u'''
<h4>Status da construção: {{ summary }}</h4>
<p> Trabalhador utilizado: {{ workername }}</p>
{% for step in build['steps'] %}
<p> {{ step['name'] }}: {{ step['result'] }}</p>
{% endfor %}
<p><b> -- O 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)
# Configurações principais do mestre
c['title'] = "O processo de construção"
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"
}Salvamos o arquivo e podemos tentar iniciar o serviço do mestre:
systemctl restart buildbot-masterNo log, vamos verificar se a configuração está em ordem e tudo está funcionando corretamente. Todos os nossos trabalhadores devem agora se conectar, como será alegremente comunicado no log »»'/home/buildbot/master/twistd.log»».
2019-07-24 16:50:35+0300 [-] Carregando buildbot.tac...
2019-07-24 16:50:35+0300 [-] Carregado.
2019-07-24 16:50:35+0300 [-] twistd 19.2.1 (\usr\bin\python3.6 3.6.8) iniciando.
2019-07-24 16:50:35+0300 [-] classe do reator: twisted.internet.epollreactor.EPollReactor.
2019-07-24 16:50:35+0300 [-] Iniciando BuildMaster -- buildbot.version: 2.3.1
2019-07-24 16:50:35+0300 [-] Carregando configuração de '\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 posteriores] `buildbotNetUsageData` não está configurado e padrões para básico.
Isso ajuda a equipe de desenvolvimento do buildbot a entender a base de instalações.
Nenhuma informação pessoal é coletada.
Somente informações sobre a versão do software de instalação e o uso de plugins são enviadas.
Você pode `optar por não participar` definindo esta variável como None.
Ou `optar por participar` para mais informações definindo como "full".
2019-07-24 16:50:36+0300 [-] Configurando banco de dados com URL 'sqlite:\state.sqlite'
2019-07-24 16:50:36+0300 [-] definindo o modo de journal do banco de dados para 'wal'
2019-07-24 16:50:36+0300 [-] adicionando 1 novo serviço, removendo 0
2019-07-24 16:50:36+0300 [-] adicionando 1 nova fonte de mudanças, removendo 0
2019-07-24 16:50:36+0300 [-] gitpoller: usando diretório de trabalho '\home\buildbot\master\gitpoller-work'
2019-07-24 16:50:36+0300 [-] adicionando 3 novos construtores, removendo 0
2019-07-24 16:50:36+0300 [-] adicionando 1 novo agendador, removendo 0
2019-07-24 16:50:36+0300 [-] inicializando plugin www 'waterfall_view'
2019-07-24 16:50:36+0300 [-] inicializando plugin www 'console_view'
2019-07-24 16:50:36+0300 [-] inicializando plugin www 'grid_view'
2019-07-24 16:50:36+0300 [-] NOTA: plugin www 'sitenav' está instalado mas não configurado
2019-07-24 16:50:36+0300 [-] inicializando plugin www 'waterfall_view'
2019-07-24 16:50:36+0300 [-] inicializando plugin www 'console_view'
2019-07-24 16:50:36+0300 [-] inicializando plugin www 'grid_view'
2019-07-24 16:50:36+0300 [-] NOTA: plugin www 'sitenav' está instalado mas não configurado
2019-07-24 16:50:36+0300 [-] BuildbotSite iniciando na porta 80
2019-07-24 16:50:36+0300 [-] Iniciando fábrica
2019-07-24 16:50:36+0300 [-] adicionando 3 novos trabalhadores, removendo 0
2019-07-24 16:50:36+0300 [-] PBServerFactory iniciando na porta 4000
2019-07-24 16:50:36+0300 [-] Iniciando fábrica
2019-07-24 16:50:37+0300 [-] BuildMaster está em execução
2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: enviando {'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-com-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] trabalhador 'CentOS' anexando de IPv4Address(tipo='TCP', host='127.0.0.1', port=37332)
2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Recebeu workerinfo de 'CentOS'
2019-07-24 16:50:37+0300 [-] bot anexado
2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Trabalhador CentOS anexado ao Rac-GUI-RPM-builder
2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: buildbot.net disse: ok
2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] trabalhador 'Windows-10' anexando de IPv4Address(tipo='TCP', host='192.168.5.145', port=49831)
2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] Recebeu workerinfo de 'Windows-10'
2019-07-24 16:50:40+0300 [-] bot anexado
2019-07-24 16:50:40+0300 [Broker,1,192.168.55.15] Trabalhador Windows-10 anexado ao Rac-GUI-WIN-builder
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] trabalhador 'Debian-10' anexando de IPv4Address(tipo='TCP', host='192.168.5.9', port=44430)
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Recebeu workerinfo de 'Debian-10'
2019-07-24 16:50:41+0300 [-] bot anexado
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Trabalhador Debian-10 anexado ao Rac-GUI-DEB-builderA configuração foi concluída. É possível verificar o estado atual através da interface web, onde você também pode ver erros de compilação, reiniciar um processo que travou, entre outros.
Logo após o início dos nossos trabalhadores, você pode visualizar através do menu "Builds" -> "Workers".

Após o primeiro processo de compilação ser realizado (ou seja, mudanças no repositório Git), o estado dos processos aparecerá na primeira página.

Se você clicar com o mouse na linha desejada, uma página se abrirá mostrando o estado atual desse processo, onde é possível ver o que está acontecendo, quais erros ocorreram, entre outros.

Você pode baixar a configuração completa do mestre aqui.
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
))
# Serviço de execução da construção
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)
)
# Adicionaremos a definição de versão do arquivo principal
rac_gui_build_RPM.addStep(
steps.SetPropertyFromCommand(
command="grep version ..\rac-gui\rac_gui.tcl | grep -oE 'b[0-9]{1,2}.[0-9]{1,2}.[0-9]{1,2}b'", property="version"
)
)
# Adicionaremos a definição de release do arquivo principal
rac_gui_build_RPM.addStep(
steps.SetPropertyFromCommand(
command="grep release ..\rac-gui\rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
)
)
rac_gui_build_RPM.addStep(steps.ShellCommand(
command=["tar", "czf", util.Interpolate("/home/buildbot/rpmbuild/SOURCES/rac-gui-%(prop:version)s-%(prop:release)s.tar.gz"), "..\rac-gui"]))
rac_gui_build_RPM.addStep(steps.ShellCommand(
command=["cp", "..\rac-gui\rac_gui.spec", "/home/buildbot/rpmbuild/SPECS/rac_gui.spec"]))
rac_gui_build_RPM.addStep(steps.ShellCommand(
command=["sed", "-i", util.Interpolate("s/.*Version:.*/Version:t%(prop:version)s/"), "/home/buildbot/rpmbuild/SPECS/rac_gui.spec"]))
rac_gui_build_RPM.addStep(steps.ShellCommand(
command=["sed", "-i", util.Interpolate("s/.*Release:.*/Release:t%(prop:release)s/"), "/home/buildbot/rpmbuild/SPECS/rac_gui.spec"]))
rac_gui_build_RPM.addStep(steps.RpmBuild(
specfile="/home/buildbot/rpmbuild/SPECS/rac_gui.spec",
dist='.el5',
topdir='/home/buildbot/rpmbuild',
builddir='/home/buildbot/rpmbuild/build',
rpmdir='/home/buildbot/rpmbuild/RPMS',
sourcedir='/home/buildbot/rpmbuild/SOURCES'
))
# Copiaremos o arquivo para o mestre
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)
)
# Adicionaremos a definição de versão do arquivo principal
rac_gui_build_DEB.addStep(
steps.SetPropertyFromCommand(
command="grep version rac_gui.tcl | grep -oE 'b[0-9]{1,2}.[0-9]{1,2}.[0-9]{1,2}b'", property="version"
)
)
# Adicionaremos a definição de release do arquivo principal
rac_gui_build_DEB.addStep(
steps.SetPropertyFromCommand(
command="grep release rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
)
)
# Renomearemos o arquivo executável
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["mv", "rac_gui.tcl", "racgui"]))
# Alteraremos os caminhos para as bibliotecas
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["sed", "-i", "s+^set dir(lib)+set dir(lib) /usr/share/rac-gui/lib ;#+g", "racgui"]))
# Alteraremos os caminhos para os arquivos
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["sed", "-i", "s+[pwd]/usr/share/rac-gui+g", "racgui"]))
# Arquivaremos os fontes
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["tar", "czf", util.Interpolate("..\rac-gui_%(prop:version)s.orig.tar.gz"), "."]))
# Vamos construir o pacote
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["dpkg-buildpackage"]))
# Copiaremos o arquivo para o mestre
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)
)
# Adicionaremos a definição de versão do arquivo principal
rac_gui_build_WIN.addStep(
steps.SetPropertyFromCommand(
command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'version:') -split 's')[2]",
property="version"
)
)
# Adicionaremos a definição de release do arquivo principal
rac_gui_build_WIN.addStep(
steps.SetPropertyFromCommand(
command="powershell -command "((Get-Content .rac_gui.tcl | Select-String -Pattern 'release:') -split 's')[2]",
property="release"
)
)
# Criaremos o arquivo executável
rac_gui_build_WIN.addStep(steps.ShellCommand(
command=["c:binfreewrap.exe", "rac_gui.tcl"]))
# Vamos compactar o que foi gerado
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"]))
# Copiaremos para o mestre
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")
)
)
# Copiaremos o arquivo para o 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>Status da construção: {{ summary }}</h4>
<p> Trabalhador utilizado: {{ workername }}</p>
{% for step in build['steps'] %}
<p> {{ step['name'] }}: {{ step['result'] }}</p>
{% endfor %}
<p><b> -- O Buildbot</b></p>
'''
mailNotifier = reporters.MailNotifier(fromaddr="112@icvibor.pt",
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'] = "O processo de construção"
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"
}Materiais
Para a preparação deste artigo, foram utilizados os seguintes materiais:
- E a documentação do produto.
Fonte: habr.com
