Το Buildbot σε παραδείγματα

Χρειάστηκε να ρυθμίσω τη διαδικασία συναρμολόγησης και παράδοσης πακέτων λογισμικού από ένα αποθετήριο Git στον ιστότοπο. Και όταν είδα, όχι πολύ καιρό πριν, εδώ στο Habré ένα άρθρο για το buildbot (σύνδεσμος στο τέλος), αποφάσισα να το δοκιμάσω και να το εφαρμόσω.

Δεδομένου ότι το buildbot είναι ένα κατανεμημένο σύστημα, θα ήταν λογικό να δημιουργηθεί ένας ξεχωριστός κεντρικός υπολογιστής κατασκευής για κάθε αρχιτεκτονική και λειτουργικό σύστημα. Στην περίπτωσή μας, αυτά θα είναι κοντέινερ LXC (στην περίπτωση του Linux) και qemu (στην περίπτωση των Windows):

  • vm-srv-build1 - centos 7, θα υπάρχει ένας κύριος buildbot και ένας από τους εργάτες
  • vm-srv-build2 - debian 10, για τη δημιουργία πακέτων DEB
  • vm-srv-build3 - windows 10, για συναρμολόγηση, ξέρετε για τι

θα μαζέψουμε Rac GUI — μια γραφική διεπαφή για rac 1C για τη διαχείριση ενός συμπλέγματος διακομιστών. Για το 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

Εάν όλα λειτουργούν (δείτε το αρχείο καταγραφής 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

Ένα αρχείο master.cfg δημιουργήθηκε στον κατάλογο /home/buildbot/master/. Αυτό το αρχείο είναι κώδικας 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 στο master. Για το σκοπό αυτό χρησιμοποιείται γραφή στο 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),
]

Θα χρησιμοποιήσουμε email για να σας ειδοποιήσουμε για την κατάσταση της διαδικασίας κατασκευής.


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

Στο αρχείο καταγραφής θα ελέγξουμε ότι όλα είναι εντάξει με το config και ότι όλα λειτουργούν κανονικά. Όλοι οι εργαζόμενοί μας θα πρέπει τώρα να συνδεθούν, κάτι που θα αναφέρεται ευχαρίστως στο αρχείο καταγραφής »»'/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

Αυτό ολοκληρώνει τη διαδικασία εγκατάστασης. Μπορείτε να δείτε την τρέχουσα κατάσταση μέσω της διεπαφής web. Όπου μπορείτε επίσης να δείτε σφάλματα κατασκευής, να ξεκινήσετε μια παγωμένη διαδικασία εάν κάτι πήγε στραβά κ.λπ.

Αμέσως μετά την κυκλοφορία, μπορείτε να δείτε τους σκληρά εργαζόμενους μέσω του μενού "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

Προσθέστε ένα σχόλιο