Eu precisava configurar o processo de montagem e entrega de pacotes de software de um repositório Git para o site. E quando vi, não faz muito tempo, aqui no Habré um artigo sobre buildbot (link no final), resolvi experimentar e aplicar.
Como o buildbot é um sistema distribuído, seria lógico criar um host de compilaçã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, haverá um buildbot master e um dos trabalhadores
vm-srv-build2 - debian 10, para construir pacotes DEB
vm-srv-build3 - windows 10, para montagem, você sabe para que serve
Nós vamos coletar GUI Rac — uma interface gráfica para 1C rac para gerenciar um cluster de servidores. Para Linux, serão usadas ferramentas padrão para cada sistema operacional; para construir um arquivo exe para Windows a partir de um script tcl, use embrulho livre.
Instalação
GNU / Linux
Existe documentação suficiente na Internet para instalação 1,2. Sim, e não causa problemas especiais:
Para o mestre:
Claro, seria mais correto coletar pacotes para cada sistema operacional, mas isso está além do escopo do artigo. Também omitiremos a descrição da configuração de containers para trabalho, observarei apenas que utilizo ProxMox VE. E você também precisará instalar pacotes para cada eixo necessário para montagem (centos: rpmdevtools, etc.; debian: build-essential, dh-make, pbuilder, etc.)
Os projetos de build e os serviços buildbot serão lançados como um usuário sem privilégios, então você precisa criar um em todos os hosts participantes do processo:
adduser buildbot
A seguir configuraremos o lançamento automático de serviços, respectivamente, em cada um dos hosts (contêineres):
Depois disso, você pode criar uma infraestrutura de diretório para “trabalhadores” (em todos os hosts), para isso, registre-se como 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 123456
No 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 123456
Em hosts trabalhadores, o serviço buildbot-worker pode ser iniciado
systemctl start buildbot-worker
MS Windows
Como “trabalhador” para montagem no Windows, será utilizada uma máquina virtual com a versão mais recente do Win10.
Para trabalhar você precisa de:
Depois que todos os itens acima estiverem instalados, você pode instalar o próprio buildbot:
pip install buildbot-worker
Vamos criar um diretório de trabalho
md c:worker
E vamos lançar
buildbot-worker start c:worker
Se tudo funcionar (veja log c:workertwistd.log), então você pode registrar nosso “trabalhador” como um serviço adicionando um item com o diretório de trabalho ao registro (os comandos são executados no PowerShell rodando como administrador):
Isso é tudo com os “trabalhadores”, você não precisa tocá-los mais, todo o controle vem do mestre.
Configuração do assistente
Para começar, vamos criar a infraestrutura para o master (no host principal), para isso, registre-se como usuário buildbot e execute os seguintes comandos:
su - buildbot
mkdir /home/buildbot/master
cd ~
buildbot create-master master
Para pacotes prontos, crie um diretório builds
mkdir /home/buildbot/builds
Um arquivo master.cfg foi criado no diretório /home/buildbot/master/. Este arquivo é um código python e contém uma descrição de todos os mecanismos do sistema; trabalharemos com ele no futuro.
Para automatizar a montagem de pacotes de diferentes versões, para não ter que se aprofundar no código do arquivo master.cfg, no script principal do programa rac_gui.tcl foram adicionadas linhas com a versão atual e release no cabeçalho :
E com base nessas linhas, o buildbot irá numerar os pacotes. Para extrair dados, use a chamada grep do console. No buildbot você simplesmente não pode definir variáveis para “trabalhadores” (pelo menos, não descobri como). É para isso que as propriedades são usadas. Aqueles. No processo de montagem, adicionamos etapas para determinar a versão e o lançamento e, consequentemente, definir as propriedades da versão e do lançamento. As propriedades podem ser definidas de várias maneiras, neste caso chamando o comando do 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"
)
)
Você pode substituir os valores resultantes chamando util.Interpolate().
Para definir os números corretos de lançamento e versão, use uma chamada sed padrão, ou seja, o comando substitui os valores dentro do arquivo de especificações pelos necessários
Copiamos o pacote montado finalizado e o arquivo com fontes para o master. Mas você pode copiar imediatamente os arquivos do seu 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 o processo de cópia dos pacotes coletados para a hospedagem via FTP no master. Para isso é utilizado escrita no tcl.
É isso com RPM. Agora vamos começar a descrever o algoritmo para construir um pacote DEB. Como os processos de construção de pacotes para diferentes sistemas são independentes entre si, muitas etapas serão repetidas.
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)
)
# Добавим определение версии из основного файла
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"
)
)
# Добавим определение релиза из основного файла
rac_gui_build_DEB.addStep(
steps.SetPropertyFromCommand(
command="grep release rac_gui.tcl | grep -oE 'b[0-9]{1,3}b'", property="release"
)
)
# Переименуем запускаемый файл
rac_gui_build_DEB.addStep(steps.ShellCommand(
command=["mv", "rac_gui.tcl", "racgui"]))
Para um pacote RPM, alguns dos procedimentos a seguir são feitos pelo próprio rpm durante a montagem e são descritos dentro das especificações; para Debian, você deve 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")]
)
)
Salve o arquivo e tente iniciar o serviço do assistente:
systemctl restart buildbot-master
No log verificaremos se está tudo em ordem com a configuração e tudo funcionando normalmente. Todos os nossos trabalhadores devem agora se conectar, o que será felizmente relatado no log »»'/home/buildbot/master/twistd.log»»':
2019-07-24 16:50:35+0300 [-] Loading buildbot.tac...
2019-07-24 16:50:35+0300 [-] Loaded.
2019-07-24 16:50:35+0300 [-] twistd 19.2.1 (/usr/bin/python3.6 3.6.8) starting up.
2019-07-24 16:50:35+0300 [-] reactor class: twisted.internet.epollreactor.EPollReactor.
2019-07-24 16:50:35+0300 [-] Starting BuildMaster -- buildbot.version: 2.3.1
2019-07-24 16:50:35+0300 [-] Loading configuration from '/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 and later] `buildbotNetUsageData` is not configured and defaults to basic.
This parameter helps the buildbot development team to understand the installation base.
No personal information is collected.
Only installation software version info and plugin usage is sent.
You can `opt-out` by setting this variable to None.
Or `opt-in` for more information by setting it to "full".
2019-07-24 16:50:36+0300 [-] Setting up database with URL 'sqlite:/state.sqlite'
2019-07-24 16:50:36+0300 [-] setting database journal mode to 'wal'
2019-07-24 16:50:36+0300 [-] adding 1 new services, removing 0
2019-07-24 16:50:36+0300 [-] adding 1 new change_sources, removing 0
2019-07-24 16:50:36+0300 [-] gitpoller: using workdir '/home/buildbot/master/gitpoller-work'
2019-07-24 16:50:36+0300 [-] adding 3 new builders, removing 0
2019-07-24 16:50:36+0300 [-] adding 1 new schedulers, removing 0
2019-07-24 16:50:36+0300 [-] initializing www plugin 'waterfall_view'
2019-07-24 16:50:36+0300 [-] initializing www plugin 'console_view'
2019-07-24 16:50:36+0300 [-] initializing www plugin 'grid_view'
2019-07-24 16:50:36+0300 [-] NOTE: www plugin 'sitenav' is installed but not configured
2019-07-24 16:50:36+0300 [-] initializing www plugin 'waterfall_view'
2019-07-24 16:50:36+0300 [-] initializing www plugin 'console_view'
2019-07-24 16:50:36+0300 [-] initializing www plugin 'grid_view'
2019-07-24 16:50:36+0300 [-] NOTE: www plugin 'sitenav' is installed but not configured
2019-07-24 16:50:36+0300 [-] BuildbotSite starting on 80
2019-07-24 16:50:36+0300 [-] Starting factory <buildbot.www.service.BuildbotSite object at 0x7fe31c2657b8>
2019-07-24 16:50:36+0300 [-] adding 3 new workers, removing 0
2019-07-24 16:50:36+0300 [-] PBServerFactory starting on 4000
2019-07-24 16:50:36+0300 [-] Starting factory <twisted.spread.pb.PBServerFactory object at 0x7fe31c147470>
2019-07-24 16:50:37+0300 [-] BuildMaster is running
2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: sending {'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] worker 'CentOS' attaching from IPv4Address(type='TCP', host='127.0.0.1', port=37332)
2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Got workerinfo from 'CentOS'
2019-07-24 16:50:37+0300 [-] bot attached
2019-07-24 16:50:37+0300 [Broker,0,127.0.0.1] Worker CentOS attached to Rac-GUI-RPM-builder
2019-07-24 16:50:37+0300 [-] buildbotNetUsageData: buildbot.net said: ok
2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] worker 'Windows-10' attaching from IPv4Address(type='TCP', host='192.168.5.145', port=49831)
2019-07-24 16:50:39+0300 [Broker,1,192.168.55.15] Got workerinfo from 'Windows-10'
2019-07-24 16:50:40+0300 [-] bot attached
2019-07-24 16:50:40+0300 [Broker,1,192.168.55.15] Worker Windows-10 attached to Rac-GUI-WIN-builder
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] worker 'Debian-10' attaching from IPv4Address(type='TCP', host='192.168.5.9', port=44430)
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Got workerinfo from 'Debian-10'
2019-07-24 16:50:41+0300 [-] bot attached
2019-07-24 16:50:41+0300 [Broker,2,192.168.55.99] Worker Debian-10 attached to Rac-GUI-DEB-builder
Isso conclui o processo de configuração. Você pode visualizar o status atual por meio da interface da web. Onde você também pode ver erros de construção, encerrar um processo congelado se algo der errado, etc.
Imediatamente após o lançamento, nossos trabalhadores podem ser visualizados através do menu “Construções” -> “Trabalhadores”
Após a conclusão do primeiro processo de construção (ou seja, alterações no repositório Git), o status dos processos aparecerá na primeira página.
Se você clicar na linha desejada com o mouse, será aberta uma página com o estado atual deste processo, onde você poderá ver o que está acontecendo, quais erros, etc.
A configuração completa do assistente pode ser encontrada aqui