Buildbot Π²ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΈ

Π’Ρ€Π΅Π±Π°ΡˆΠ΅ Π΄Π° Π³ΠΎ поставам процСсот Π½Π° ΡΠΊΠ»ΠΎΠΏΡƒΠ²Π°ΡšΠ΅ ΠΈ Π΄ΠΎΡΡ‚Π°Π²ΡƒΠ²Π°ΡšΠ΅ софтвСрски ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ ΠΎΠ΄ ΡΠΊΠ»Π°Π΄ΠΈΡˆΡ‚Π΅Ρ‚ΠΎ Π½Π° Git Π½Π° страницата. И ΠΊΠΎΠ³Π° Π²ΠΈΠ΄ΠΎΠ², Π½Π΅ Ρ‚ΠΎΠ»ΠΊΡƒ ΠΎΠ΄Π°ΠΌΠ½Π°, ΠΎΠ²Π΄Π΅ Π½Π° Π₯Π°Π±Ρ€Π΅ ΡΡ‚Π°Ρ‚ΠΈΡ˜Π° Π·Π° buildbot (Π»ΠΈΠ½ΠΊ Π½Π° ΠΊΡ€Π°Ρ˜ΠΎΡ‚), Ρ€Π΅ΡˆΠΈΠ² Π΄Π° ја ΠΏΡ€ΠΎΠ±Π°ΠΌ ΠΈ Π΄Π° ја ΠΏΡ€ΠΈΠΌΠ΅Π½Π°ΠΌ.

Π‘ΠΈΠ΄Π΅Ρ˜ΡœΠΈ buildbot Π΅ дистрибуиран систСм, Π±ΠΈ Π±ΠΈΠ»ΠΎ Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ Π΄Π° сС создадС посСбСн build host Π·Π° сСкоја Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΈΠ²Π΅Π½ систСм. Π’ΠΎ Π½Π°ΡˆΠΈΠΎΡ‚ ΡΠ»ΡƒΡ‡Π°Ρ˜, ΠΎΠ²Π° ќС Π±ΠΈΠ΄Π°Ρ‚ ΠΊΠΎΠ½Ρ‚Π΅Ρ˜Π½Π΅Ρ€ΠΈ LXC (Π²ΠΎ ΡΠ»ΡƒΡ‡Π°Ρ˜ Π½Π° Linux) ΠΈ qemu (Π²ΠΎ ΡΠ»ΡƒΡ‡Π°Ρ˜ Π½Π° Windows):

  • vm-srv-build1 - centos 7, ќС ΠΈΠΌΠ° buildbot master ΠΈ Π΅Π΄Π΅Π½ ΠΎΠ΄ Ρ€Π°Π±ΠΎΡ‚Π½ΠΈΡ†ΠΈΡ‚Π΅
  • vm-srv-build2 - debian 10, Π·Π° Π³Ρ€Π°Π΄Π΅ΡšΠ΅ DEB ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ
  • vm-srv-build3 - windows 10, Π·Π° ΡΠΊΠ»ΠΎΠΏΡƒΠ²Π°ΡšΠ΅, знаСш Π·Π° ΡˆΡ‚ΠΎ

ЌС собСрСмС Rac GUI β€” Π³Ρ€Π°Ρ„ΠΈΡ‡ΠΊΠΈ ΠΈΠ½Ρ‚Π΅Ρ€Ρ„Π΅Ρ˜Ρ Π·Π° 1C rac Π·Π° ΡƒΠΏΡ€Π°Π²ΡƒΠ²Π°ΡšΠ΅ со кластСр Π½Π° сСрвСри. Π—Π° Linux, ќС сС користат стандардни Π°Π»Π°Ρ‚ΠΊΠΈ Π·Π° сСкој ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΈΠ²Π΅Π½ систСм Π·Π° Π΄Π° сС ΠΈΠ·Π³Ρ€Π°Π΄ΠΈ Π΄Π°Ρ‚ΠΎΡ‚Π΅ΠΊΠ° exe Π·Π° Windows ΠΎΠ΄ tcl скрипта слободна ΠΎΠ±Π²ΠΈΠ²ΠΊΠ°.

Π˜Π½ΡΡ‚Π°Π»Π°Ρ†ΠΈΡ˜Π°

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

Π‘Π»Π΅Π΄Π½ΠΎ, ќС Π³ΠΎ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€ΠΈΡ€Π°ΠΌΠ΅ автоматското ΡΡ‚Π°Ρ€Ρ‚ΡƒΠ²Π°ΡšΠ΅ Π½Π° услугитС, соодвСтно, Π½Π° сСкој ΠΎΠ΄ Π΄ΠΎΠΌΠ°ΡœΠΈΠ½ΠΈΡ‚Π΅ (ΠΊΠΎΠ½Ρ‚Π΅Ρ˜Π½Π΅Ρ€ΠΈΡ‚Π΅):

БистСмска Π΅Π΄ΠΈΠ½ΠΈΡ†Π° Π·Π° ΡΡ‚Π°Ρ€Ρ‚ΡƒΠ²Π°ΡšΠ΅ Π½Π° Π²ΠΎΠ»ΡˆΠ΅Π±Π½ΠΈΠΊΠΎΡ‚:

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.
Π—Π° Ρ€Π°Π±ΠΎΡ‚Π° ќС Π²ΠΈ Ρ‚Ρ€Π΅Π±Π°Π°Ρ‚:

ΠžΡ‚ΠΊΠ°ΠΊΠΎ ќС сС инсталира сСто Π³ΠΎΡ€Π΅Π½Π°Π²Π΅Π΄Π΅Π½ΠΎ, ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π³ΠΎ инсталиратС самиот buildbot:

pip install buildbot-worker

АјдС Π΄Π° создадСмС Ρ€Π°Π±ΠΎΡ‚Π΅Π½ Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΡƒΠΌ

md c:worker

И Π΄Π° Π·Π°ΠΏΠΎΡ‡Π½Π΅ΠΌΠ΅

buildbot-worker start c:worker

Ако сè Ρ€Π°Π±ΠΎΡ‚ΠΈ (Π²ΠΈΠ΄Π΅Ρ‚Π΅ log 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

Π—Π° Π³ΠΎΡ‚ΠΎΠ²ΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ, ΠΊΡ€Π΅ΠΈΡ€Π°Ρ˜Ρ‚Π΅ Π΄ΠΈΡ€Π΅ΠΊΡ‚ΠΎΡ€ΠΈΡƒΠΌ Π·Π° ΠΈΠ·Π³Ρ€Π°Π΄Π±Π°

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 Сдноставно Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π΄Π΅Ρ„ΠΈΠ½ΠΈΡ€Π°Ρ‚Π΅ ΠΏΡ€ΠΎΠΌΠ΅Π½Π»ΠΈΠ²ΠΈ Π·Π° β€žΡ€Π°Π±ΠΎΡ‚Π½ΠΈΡ†ΠΈβ€œ (Π±Π°Ρ€Π΅ΠΌ, јас Π½Π΅ најдов ΠΊΠ°ΠΊΠΎ). Π—Π° ΠΎΠ²Π° сС користат ΡΠ²ΠΎΡ˜ΡΡ‚Π²Π°Ρ‚Π°. ОниС. Π’ΠΎ процСсот Π½Π° ΡΠΊΠ»ΠΎΠΏΡƒΠ²Π°ΡšΠ΅, Π΄ΠΎΠ΄Π°Π²Π°ΠΌΠ΅ Ρ‡Π΅ΠΊΠΎΡ€ΠΈ Π·Π° ΠΎΠ΄Ρ€Π΅Π΄ΡƒΠ²Π°ΡšΠ΅ Π½Π° Π²Π΅Ρ€Π·ΠΈΡ˜Π°Ρ‚Π° ΠΈ ΠΎΡΠ»ΠΎΠ±ΠΎΠ΄ΡƒΠ²Π°ΡšΠ΅Ρ‚ΠΎ ΠΈ, соодвСтно, Π³ΠΈ поставувамС ΡΠ²ΠΎΡ˜ΡΡ‚Π²Π°Ρ‚Π° Π½Π° Π²Π΅Ρ€Π·ΠΈΡ˜Π°Ρ‚Π° ΠΈ ΠΎΡΠ»ΠΎΠ±ΠΎΠ΄ΡƒΠ²Π°ΡšΠ΅Ρ‚ΠΎ. Π‘Π²ΠΎΡ˜ΡΡ‚Π²Π°Ρ‚Π° ΠΌΠΎΠΆΠ΅ Π΄Π° сС постават Π½Π° Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ Π½Π°Ρ‡ΠΈΠ½ΠΈ, Π²ΠΎ овој ΡΠ»ΡƒΡ‡Π°Ρ˜ со ΠΏΠΎΠ²ΠΈΠΊΡƒΠ²Π°ΡšΠ΅ Π½Π° ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ‚Π° Π½Π° ΠΊΠΎΠ½Π·ΠΎΠ»Π°Ρ‚Π°:

# Π”ΠΎΠ±Π°Π²ΠΈΠΌ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ вСрсии ΠΈΠ· основного Ρ„Π°ΠΉΠ»Π°
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 ΠΏΠΎΠ²ΠΈΠΊ, Ρ‚.Π΅. ΠΊΠΎΠΌΠ°Π½Π΄Π°Ρ‚Π° Π³ΠΈ Π·Π°ΠΌΠ΅Π½ΡƒΠ²Π° врСдноститС Π²ΠΎ спСцификационата Π΄Π°Ρ‚ΠΎΡ‚Π΅ΠΊΠ° со ΠΏΠΎΡ‚Ρ€Π΅Π±Π½ΠΈΡ‚Π΅

# мСняСм Π²Π΅Ρ€ΡΠΈΡŽ
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")
       )
)

Π”Π° Π³ΠΎ Π·Π°ΠΏΠΎΡ‡Π½Π΅ΠΌΠ΅ процСсот Π½Π° ΠΊΠΎΠΏΠΈΡ€Π°ΡšΠ΅ Π½Π° собранитС ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ Π²ΠΎ хостинг ΠΏΡ€Π΅ΠΊΡƒ FTP Π½Π° мастСрот. Π—Π° Ρ‚Π°Π° Ρ†Π΅Π» сС користи скрипта Π½Π° 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 Π·Π° Π²Ρ€Π΅ΠΌΠ΅ Π½Π° ΡΠΊΠ»ΠΎΠΏΡƒΠ²Π°ΡšΠ΅Ρ‚ΠΎ ΠΈ сС опишани Π²ΠΎ спСцификациитС Π·Π° Debian, Ρ‚ΠΎΠ° Ρ‚Ρ€Π΅Π±Π° Π΄Π° Π³ΠΎ Π½Π°ΠΏΡ€Π°Π²ΠΈΡ‚Π΅ ΠΎΠ²Π΄Π΅:

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

Π‘ΠΈΠ΄Π΅Ρ˜ΡœΠΈ grep ΠΈ sed Π½Π΅ сС стандардни Π²ΠΎ Windows (ΠΈΠ»ΠΈ Π³ΠΈ ΠΈΠΌΠ°?), ќС користимС 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

Ова Π³ΠΎ ΠΊΠΎΠΌΠΏΠ»Π΅Ρ‚ΠΈΡ€Π° процСсот Π½Π° ΠΏΠΎΡΡ‚Π°Π²ΡƒΠ²Π°ΡšΠ΅. Π’Π΅ΠΊΠΎΠ²Π½ΠΈΠΎΡ‚ статус ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π³ΠΎ Π²ΠΈΠ΄ΠΈΡ‚Π΅ ΠΏΡ€Π΅ΠΊΡƒ Π²Π΅Π±-ΠΈΠ½Ρ‚Π΅Ρ€Ρ„Π΅Ρ˜ΡΠΎΡ‚. ΠžΠ½Π°ΠΌΡƒ ΠΊΠ°Π΄Π΅ ΡˆΡ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° Π²ΠΈΠ΄ΠΈΡ‚Π΅ ΠΈ Π³Ρ€Π΅ΡˆΠΊΠΈ Π²ΠΎ ΠΈΠ·Π³Ρ€Π°Π΄Π±Π°Ρ‚Π°, Π΄Π° Π·Π°ΠΏΠΎΡ‡Π½Π΅Ρ‚Π΅ Π·Π°ΠΌΡ€Π·Π½Π°Ρ‚ процСс Π°ΠΊΠΎ Π½Π΅ΡˆΡ‚ΠΎ Ρ‚Ρ€Π³Π½Π΅ Π½Π°ΠΎΠΏΠ°ΠΊΡƒ, ΠΈΡ‚Π½.

Π’Π΅Π΄Π½Π°Ρˆ ΠΏΠΎ Π»Π°Π½ΡΠΈΡ€Π°ΡšΠ΅Ρ‚ΠΎ, Π½Π°ΡˆΠΈΡ‚Π΅ Π²Ρ€Π΅Π΄Π½ΠΈ Ρ€Π°Π±ΠΎΡ‚Π½ΠΈΡ†ΠΈ ΠΌΠΎΠΆΠ΅ Π΄Π° сС Π²ΠΈΠ΄Π°Ρ‚ ΠΏΡ€Π΅ΠΊΡƒ ΠΌΠ΅Π½ΠΈΡ‚ΠΎ β€ž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"
}

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

Π‘Π»Π΅Π΄Π½ΠΈΠ²Π΅ ΠΌΠ°Ρ‚Π΅Ρ€ΠΈΡ˜Π°Π»ΠΈ Π±Π΅Π° користСни Π·Π° ΠΏΠΎΠ΄Π³ΠΎΡ‚ΠΎΠ²ΠΊΠ° Π½Π° ΡΡ‚Π°Ρ‚ΠΈΡ˜Π°Ρ‚Π°:

Π˜Π·Π²ΠΎΡ€: www.habr.com

Π”ΠΎΠ΄Π°Π΄Π΅Ρ‚Π΅ ΠΊΠΎΠΌΠ΅Π½Ρ‚Π°Ρ€