Buildbot Π² ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ…

ΠŸΠΎΡ‚Ρ€Π΅Π±ΠΎΠ²Π°Π»ΠΎΡΡŒ ΠΌΠ½Π΅ Π½Π°ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ процСсс сборки ΠΈ доставки Π½Π° сайт ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌ ΠΈΠ· Git-рСпозитария. И ΡƒΠ²ΠΈΠ΄Π΅Π², Π½ΠΈ Ρ‚Π°ΠΊ Π΄Π°Π²Π½ΠΎ, Ρ‚ΡƒΡ‚ Π½Π° Π₯Π°Π±Ρ€Π΅ ΡΡ‚Π°Ρ‚ΡŒΡŽ ΠΏΠΎ buildbot (ссылка Π² ΠΊΠΎΠ½Ρ†Π΅) Ρ€Π΅ΡˆΠΈΠ» для этого ΠΏΠΎΠΏΡ€ΠΎΠ±ΠΎΠ²Π°Ρ‚ΡŒ Π΅Π³ΠΎ ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚ΡŒ.

Π’Π°ΠΊ ΠΊΠ°ΠΊ buildbot β€” это распрСдСлённая систСма, Ρ‚ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ Π»ΠΎΠ³ΠΈΡ‡Π½Ρ‹ΠΌ ΠΏΠΎΠ΄ ΠΊΠ°ΠΆΠ΄ΡƒΡŽ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρƒ ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΎΠ½ΠΊΡƒ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ сборочный хост. Π’ нашСм случаС это Π±ΡƒΠ΄ΡƒΡ‚ LXC-ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρ‹ (Π² случаС linux) ΠΈ qemu (Π² случаС windows):

  • vm-srv-build1 β€” centos 7, Ρ‚ΡƒΡ‚ Π±ΡƒΠ΄Π΅Ρ‚ buildbot мастСр (master) ΠΈ ΠΎΠ΄ΠΈΠ½ ΠΈΠ· Ρ€Π°Π±ΠΎΡ‡ΠΈΡ… (worker)
  • vm-srv-build2 β€” debian 10, для сборки DEB ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ²
  • vm-srv-build3 β€” windows 10, для сборки, сами ΠΏΠΎΠ½ΠΈΠΌΠ°Π΅Ρ‚Π΅, ΠΏΠΎΠ΄ Ρ‡Ρ‚ΠΎ

Π‘ΠΎΠ±ΠΈΡ€Π°Ρ‚ΡŒ Π±ΡƒΠ΄Π΅ΠΌ Rac GUI β€” графичСская ΠΌΠΎΡ€Π΄Π° ΠΊ 1Π‘ rac для управлСния кластСром сСрвСров. Под линукс Π±ΡƒΠ΄ΡƒΡ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ ΡˆΡ‚Π°Ρ‚Π½Ρ‹Π΅ срСдства ΠΏΠΎΠ΄ ΠΊΠ°ΠΆΠ΄ΡƒΡŽ ОБ, для сборки exe-Ρ„Π°ΠΉΠ»Π° ΠΏΠΎΠ΄ windows ΠΈΠ· tcl-скрипта ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ freewrap.

Установка

GNU/Linux

По установкС, Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ Π² сСти достаточно 1,2. Π”Π° ΠΈ особых ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ ΠΎΠ½Π° Π½Π΅ Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚:
Для мастСра:

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

Для «Ρ€Π°Π±ΠΎΡ‡ΠΈΡ…», достаточного этого:

pip3 install buildbot-worker

ΠšΠΎΠ½Π΅Ρ‡Π½ΠΎ, Π±ΠΎΠ»Π΅Π΅ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Ρ‹ΠΌ Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΎΠ±Ρ€Π°Ρ‚ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ ΠΏΠΎΠ΄ ΠΊΠ°ΠΆΠ΄ΡƒΡŽ ОБ, Π½ΠΎ это Π² Ρ€Π°ΠΌΠΊΠΈ ΡΡ‚Π°Ρ‚ΡŒΠΈ Π½Π΅ Π²Ρ…ΠΎΠ΄ΠΈΡ‚. Π’Π°ΠΊΠΆΠ΅ опустим описаниС настройки ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠ² для Ρ€Π°Π±ΠΎΡ‚Ρ‹, ΠΎΡ‚ΠΌΠ΅Ρ‡Ρƒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ, Ρ‡Ρ‚ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽ ProxMox VE. И Π΅Ρ‰Ρ‘ потрСбуСтся ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ ΠΏΠΎΠ΄ ΠΊΠ°ΠΆΠ΄ΡƒΡŽ ось ΠΏΠΎΡ‚Ρ€Π΅Π±Π½Ρ‹Π΅ для сборки (centos: rpmdevtools ΠΈ Ρ‚.Π΄; debian: build-essential, dh-make, pbuilder ΠΈ Ρ‚.Π΄.)

Π‘Π±ΠΎΡ€ΠΊΠ° ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ΠΎΠ² ΠΈ сСрвисы buildbot Π±ΡƒΠ΄ΡƒΡ‚ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒΡΡ ΠΎΡ‚ ΠΈΠΌΠ΅Π½ΠΈ Π½Π΅ΠΏΡ€ΠΈΠ²ΠΈΠ»Π΅Π³ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Ρ, поэтому Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΅Π³ΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Π½Π° всСх хостах, ΡƒΡ‡Π°ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… Π² процСссС:


adduser buildbot

Π”Π°Π»ΡŒΡˆΠ΅ настроим автоматичСский запуск сСрвисов, соотвСтствСнно Π½Π° ΠΊΠ°ΠΆΠ΄ΠΎΠΌ ΠΈΠ· хостов (ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠ²):

Systemd ΡŽΠ½ΠΈΡ‚ для запуска мастСра:

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

ΠΈ «Ρ€Π°Π±ΠΎΡ‡Π΅Π³ΠΎ»

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

Π’Π°ΠΊ ΠΊΠ°ΠΊ всС скрипты (Π² нашСм случаС) Π»Π΅ΠΆΠ°Ρ‚ Π² /usr/local/, Ρ‚ΠΎ слСдуСт ΠΏΡ€ΠΎΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΏΡƒΡ‚ΡŒ ΠΊ Π½ΠΈΠΌ Π² ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ окруТСния:

nano /root/.bash_profile

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

ПослС этого, ΠΌΠΎΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ инфраструктуру ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ΠΎΠ² для «Ρ€Π°Π±ΠΎΡ‡ΠΈΡ…» (Π½Π° всСх хостах), для этого рСгистрируСтся ΠΏΠΎΠ΄ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΌ buildbot ΠΈ выполняСм ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹:

На ΠΏΠ΅Ρ€Π²ΠΎΠΌ хостС 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

На Π²Ρ‚ΠΎΡ€ΠΎΠΌ хостС 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

На хостах-Ρ€Π°Π±ΠΎΡ‡ΠΈΡ… слуТбу buildbot-worker ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ

systemctl start buildbot-worker

MS Windows

Π’ качСствС «Ρ€Π°Π±ΠΎΡ‡Π΅Π³ΠΎ» для сборки ΠΏΠΎΠ΄ windows, Π±ΡƒΠ΄Π΅Ρ‚ использована Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Π°Ρ машина с послСдним Ρ€Π΅Π»ΠΈΠ·ΠΎΠΌ Win10.
Для Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΏΠΎΠ½Π°Π΄ΠΎΠ±ΠΈΡ‚ΡŒΡΡ:

  • Python
  • PyWIN
  • Git
  • Для установки всякого-Ρ€Π°Π·Π½ΠΎΠ³ΠΎ Π² ΠΏΠΈΡ‚ΠΎΠ½Π΅ понадобилось ΡΠΊΠ°Ρ‡Π°Ρ‚ΡŒ Build Tools for Visual Studio 2019
  • 7Zip

ПослС Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ установится всё Π²Ρ‹ΡˆΠ΅ΠΏΠ΅Ρ€Π΅Ρ‡ΠΈΡΠ»Π΅Π½Π½ΠΎΠ΅, ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ ΠΈ сам buildbot:

pip install buildbot-worker

Π‘ΠΎΠ·Π΄Π°Π΄ΠΈΠΌ Ρ€Π°Π±ΠΎΡ‡ΠΈΠΉ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³

md c:worker

И запустим

buildbot-worker start c:worker

Если всё Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ (см. Π»ΠΎΠ³ c:workertwistd.log), Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ нашСго «Ρ€Π°Π±ΠΎΡ‡Π΅Π³ΠΎ», Π·Π°Ρ€Π΅Π³ΠΈΡΡ‚Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠ°ΠΊ слуТбу, Π΄ΠΎΠ±Π°Π²ΠΈΠ² Π² рССстр ΠΏΡƒΠ½ΠΊΡ‚ с Ρ€Π°Π±ΠΎΡ‡ΠΈΠΌ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ΠΎΠΌ (ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ Π² powershell Π·Π°ΠΏΡƒΡ‰Π΅Π½Π½ΠΎΠΌ ΠΎΡ‚ ΠΈΠΌΠ΅Π½ΠΈ администратора):

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

И ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΏΡƒΡΠΊΠ°Ρ‚ΡŒ слубТу

Start-Service buildbot

Π‘ «Ρ€Π°Π±ΠΎΡ‡ΠΈΠΌΠΈ» Π½Π° этом всё, дальшС ΠΈΡ… ΠΌΠΎΠΆΠ½ΠΎ Π½Π΅ Ρ‚Ρ€ΠΎΠ³Π°Ρ‚ΡŒ, всё ΡƒΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ ΠΈΠ΄Ρ‘Ρ‚ с мастСра.

Настройка мастСра

Для Π½Π°Ρ‡Π°Π»Π°, создадим инфраструктуру для мастСра (Π½Π° Π³Π»Π°Π²Π½ΠΎΠΌ хостС), для этого рСгистрируСтся ΠΏΠΎΠ΄ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»Π΅ΠΌ buildbot ΠΈ выполняСм ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹:

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

Для Π³ΠΎΡ‚ΠΎΠ²Ρ‹Ρ… ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² создадим ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³ builds

mkdir /home/buildbot/builds

Π’ ΠΊΠ°Ρ‚Π°Π»ΠΎΠ³Π΅ /home/buildbot/master/ Π±Ρ‹Π» создан Ρ„Π°ΠΉΠ» master.cfg. Π”Π°Π½Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» прСдставляСт собой ΠΊΠΎΠ΄ Π½Π° python ΠΈ содСрТит описаниС всСх ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠΎΠ² Ρ€Π°Π±ΠΎΡ‚Ρ‹ систСмы, с Π½ΠΈΠΌ ΠΈ Π±ΡƒΠ΄Π΅ΠΌ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² дальнСйшСм.

nano /home/buildbot/master/master.cfg

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

# слуТба запуска сборки
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
# Π‘Π±ΠΎΡ€ΠΊΠ° 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)
)

Для Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ΠΈΠ·Π°Ρ†ΠΈΠΈ сборки ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² Ρ€Π°Π·Π½Ρ‹Ρ… вСрсий, Π΄Π°Π±Ρ‹ Π½Π΅ ΠΏΡ€ΠΈΡ…ΠΎΠ΄ΠΈΠ»ΠΎΠΎΡΡŒ Π»Π°Π·ΠΈΡ‚ΡŒ Π² ΠΊΠΎΠ΄ Ρ„Π°ΠΉΠ»Π° master.cfg, Π² основном скриптС ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ rac_gui.tcl Π² Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ΅, Π΄ΠΎΠ±Π°Π²Π»Π΅Π½Ρ‹ строки с Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΌΠΈ вСрсиСй ΠΈ Ρ€Π΅Π»ΠΈΠ·ΠΎΠΌ:

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

И Π½Π° основС этих строк buildbot Π±ΡƒΠ΄Π΅Ρ‚ Π½ΡƒΠΌΠ΅Ρ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹. Для выдёргивания Π΄Π°Π½Π½Ρ‹Ρ…, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Π²Ρ‹Π·ΠΎΠ² консольного grep. Π’ buildbot просто Ρ‚Π°ΠΊ нСльзя ΠΎΠΏΠ΅Ρ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ для «Ρ€Π°Π±ΠΎΡ‡ΠΈΡ…» (Π²ΠΎ всяком случаС, я Π½Π΅ Π½Π°ΡˆΡ‘Π» ΠΊΠ°ΠΊ). Для этого слуТат свойства (property). Π’.Π΅. Π² сборочный процСсс, добавляСм шаги ΠΏΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΡŽ вСрсии ΠΈ Ρ€Π΅Π»ΠΈΠ·Π° ΠΈ соотвСтсвСнно, устанавливаСм свойства version ΠΈ release. Бвойства ΠΌΠΎΠΆΠ½ΠΎ ΡƒΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°Ρ‚ΡŒ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹ΠΌΠΈ способами, Π² Π΄Π°Π½Π½ΠΎΠΌ случаС это Π²Ρ‹Π·ΠΎΠ² консольной ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹:

# Π”ΠΎΠ±Π°Π²ΠΈΠΌ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ вСрсии ΠΈΠ· основного Ρ„Π°ΠΉΠ»Π°
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"
       )
)

ΠŸΠΎΠ΄ΡΡ‚Π°Π²Π»ΡΡ‚ΡŒ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹Π΅ значСния ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡƒΡ‚Ρ‘ΠΌ Π²Ρ‹Π·ΠΎΠ²Π° 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"]
       )
)

Π’ΡƒΡ‚ слСдуСт Π·Π°ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ Ρ‡Ρ‚ΠΎ, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ хост ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΈ для Ρ€ΡƒΡ‡Π½ΠΎΠΉ сборки ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ², Ρ‚ΠΎ сборка Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€ΠΎΡ…ΠΎΠ΄ΠΈΡ‚ΡŒ ΠΏΠΎ стандартным путям.

# ΠšΠΎΠΏΠΈΡ€ΡƒΠ΅ΠΌ spec
rac_gui_build_RPM.addStep(steps.ShellCommand(
       command=["cp", "../rac-gui/rac_gui.spec", "/home/buildbot/rpmbuild/SPECS/rac_gui.spec"]))

Для установки ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½Ρ‹Ρ… Π½ΠΎΠΌΠ΅Ρ€ΠΎΠ² Ρ€Π΅Π»ΠΈΠ·Π° ΠΈ вСрсии ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Π²Ρ‹Π·ΠΎΠ² стандарного sed, Ρ‚.Π΅. ΠΊΠΎΠΌΠ°Π½Π΄Π° замСняСт значСния Π²Π½ΡƒΡ‚Ρ€ΠΈ 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'
      )
)

Π“ΠΎΡ‚ΠΎΠ²Ρ‹ΠΉ собраный ΠΏΠ°ΠΊΠ΅Ρ‚ ΠΈ Π°Ρ€Ρ…ΠΈΠ² с исходниками ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅ΠΌ Π½Π° мастСр. Но ΠΌΠΎΠΆΠ½ΠΎ ΠΈ сразу с Ρ€Π°Π±ΠΎΡ‡Π΅Π³ΠΎ Ρ„Π°ΠΉΠ»Ρ‹ ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π² свой Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΉ ΠΈΠ»ΠΈ Π½Π° сайт.

# Π‘ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅ΠΌ Ρ„Π°ΠΉΠ» Π½Π° мастСр
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")
       )
)

Запустим Π½Π° мастСрС процСсс копирования собранных ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² Π½Π° хостинг ΠΏΠΎ Ρ„Ρ‚ΠΏ. Для этого ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ скрипт Π½Π° 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")]
        )
)

На этом с RPM Π·Π°ΠΊΠΎΠ½Ρ‡ΠΈΠ»ΠΈ. Π’Π΅ΠΏΠ΅Ρ€ΡŒ приступим ΠΊ описанию Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΠ° сборки 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)
)

# Π”ΠΎΠ±Π°Π²ΠΈΠΌ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ вСрсии ΠΈΠ· основного Ρ„Π°ΠΉΠ»Π°
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"]))

Для RPM-ΠΏΠ°ΠΊΠ΅Ρ‚Π° Ρ‡Π°ΡΡ‚ΡŒ Π½ΠΈΠΆΠ΅ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€ дСлаСтся самим rpm ΠΏΡ€ΠΈ сборкС ΠΈ описаны Π²Π½ΡƒΡ‚Ρ€ΠΈ спСка, для Π΄Π΅Π±ΠΈΠ°Π½Π° приходится это Π΄Π΅Π»Π°Ρ‚ΡŒ Ρ‚ΡƒΡ‚:

# ПомСняСм ΠΏΡƒΡ‚ΠΈ ΠΊ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°ΠΌ
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")]
        )
)

И с DEB ΠΏΠΎΠΊΠΎΠ½Ρ‡Π΅Π½ΠΎ, Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ 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)
)

Π’Π°ΠΊ ΠΊΠ°ΠΊ Π² windows ΡˆΡ‚Π°Ρ‚Π½ΠΎ Π½Π΅Ρ‚ grep ΠΈ sed (ΠΈΠ»ΠΈ Π΅ΡΡ‚ΡŒ?) Ρ‚ΠΎ Π±ΡƒΠ΄Π΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ 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),
]

Для оповСщСния ΠΎ состоянии процСсса сборки Π±ΡƒΠ΄Π΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠ»Π΅ΠΊΡ‚Ρ€ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΏΠΎΡ‡Ρ‚Ρƒ


c['services'] = []

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

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

c['services'].append(mailNotifier)

# ΠžΡΠ½ΠΎΠ²Π½Ρ‹Π΅ настройки мастСра
c['title'] = "The process of bulding"
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"
}

БохраняСм Ρ„Π°ΠΉΠ» ΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠΏΡ€ΠΎΠ±ΠΎΠ²Π°Ρ‚ΡŒ Π·Π°ΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ слуТбу мастСра:

systemctl restart buildbot-master

Π’ Π»ΠΎΠ³Π΅ ΠΏΡ€ΠΎΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΈΡ€ΡƒΠ΅ΠΌ Ρ‡Ρ‚ΠΎ с ΠΊΠΎΠ½Ρ„ΠΈΠ³ΠΎΠΌ всС Π² порядкС ΠΈ всС Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Π² ΡˆΡ‚Π°Ρ‚Π½ΠΎΠΌ Ρ€Π΅ΠΆΠΈΠΌΠ΅. ВсС наши Ρ€Π°Π±ΠΎΡ‚Π½ΠΈΠΊΠΈ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΏΠΎΠ΄ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒΡΡ, ΠΎ Ρ‡Π΅ΠΌ Π² Π»ΠΎΠ³Π΅ »»’/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

На этом процСсс настройки Π·Π°Π²Π΅Ρ€ΡˆΡ‘Π½. ΠŸΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ состояниС ΠΌΠΎΠΆΠ½ΠΎ Ρ‡Π΅Ρ€Π΅Π· вэб-ΠΌΠΎΡ€Π΄e. Π“Π΄Π΅ Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ ошибки сборки, ΠΏΠ½ΡƒΡ‚ΡŒ зависший процСсс Ссли Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ пошло Π½ΠΈ Ρ‚Π°ΠΊ ΠΈ Ρ‚.Π΄.

Π‘Ρ€Π°Π·Ρƒ послС запуска Π½Π°ΡˆΠΈΡ… работяг ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ‡Π΅Ρ€Π΅Π· мСню «Builds» -> «Workers»

Buildbot Π² ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ…

ПослС Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€ΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ процСсс сборки (Ρ‚.Π΅. измСнСния Π² Git-Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚Π°Ρ€ΠΈΠΈ), Π½Π° ΠΏΠ΅Ρ€Π²ΠΎΠΉ страничкС появится состояниС процСссов.

Buildbot Π² ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ…

Если Ρ‚ΠΊΠ½ΡƒΡ‚ΡŒ ΠΌΡ‹ΡˆΠΎΠΉ Π² Π½ΡƒΠΆΠ½ΡƒΡŽ строку Ρ‚ΠΎ откроСтся страничка с Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΌ состояниСм Π΄Π°Π½Π½ΠΎΠ³ΠΎ процСсса, Π³Π΄Π΅ Π²ΠΈΠ΄Π½ΠΎ Ρ‡Ρ‚ΠΎ происходит, ΠΊΠ°ΠΊΠΈΠ΅ ошибки ΠΈ Ρ‚.Π΄.

Buildbot Π² ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ…

Π¦Π΅Π»ΠΈΠΊΠΎΠΌ ΠΊΠΎΠ½Ρ„ΠΈΠ³ мастСра ΠΌΠΎΠΆΠ½ΠΎ Π²Π·ΡΡ‚ΡŒ Ρ‚ΡƒΡ‚

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
))
# слуТба запуска сборки
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)
)
# Π”ΠΎΠ±Π°Π²ΠΈΠΌ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ вСрсии ΠΈΠ· основного Ρ„Π°ΠΉΠ»Π°
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"
)
)
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'
))
# Π‘ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅ΠΌ Ρ„Π°ΠΉΠ» Π½Π° мастСр
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)
)
# Π”ΠΎΠ±Π°Π²ΠΈΠΌ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ вСрсии ΠΈΠ· основного Ρ„Π°ΠΉΠ»Π°
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"]))
# ПомСняСм ΠΏΡƒΡ‚ΠΈ ΠΊ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°ΠΌ
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")]
)
)
############################################
#       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)
)
# Π”ΠΎΠ±Π°Π²ΠΈΠΌ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ вСрсии ΠΈΠ· основного Ρ„Π°ΠΉΠ»Π°
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),
]
c['services'] = []
template=u'''
<h4>Build status: {{ summary }}</h4>
<p> Worker used: {{ workername }}</p>
{% for step in build['steps'] %}
<p> {{ step['name'] }}: {{ step['result'] }}</p>
{% endfor %}
<p><b> -- The Buildbot</b></p>
'''
mailNotifier = reporters.MailNotifier(fromaddr="[email protected]",
sendToInterestedUsers=False,
mode=('all'),
extraRecipients=["[email protected]"],
relayhost="mail.domain.local",
smtpPort=587,
smtpUser="[email protected]",
smtpPassword="**********",
messageFormatter=reporters.MessageFormatter(
template=template, template_type='html',
wantProperties=True, wantSteps=True))
c['services'].append(mailNotifier)
c['title'] = "The process of bulding"
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"
}

ΠœΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Ρ‹

ΠŸΡ€ΠΈ ΠΏΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²ΠΊΠ΅ ΡΡ‚Π°Ρ‚ΡŒΠΈ использовались ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΠ°Π»Ρ‹:

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com