Przykład implementacji Continuous Integration z użyciem BuildBot

Przykład implementacji Continuous Integration z użyciem BuildBot
(Obraz autorstwa Computerizer od Pixabay)

Cześć!

Nazywam się Eugeniusz CzERKin, jestem programistą zespołu deweloperskiego w firmie zajmującej się górnictwem Polymetal.

Rozpoczynając jakikolwiek duży projekt, zaczynasz się zastanawiać: „Jakie oprogramowanie najlepiej wykorzystać do jego obsługi?”. Projekt IT przed wydaniem kolejnej wersji przechodzi przez szereg etapów. Dobrze, gdy łańcuch tych etapów jest zautomatyzowany. Sam proces automatycznego wydania nowej wersji projektu IT nosi nazwę i pozwala uprościć przygotowanie kodu do wdrożenia.. BuildBot okazał się dla nas dobrym pomocnikiem, realizującym ten proces.

W tym artykule postanowiłem przedstawić przegląd możliwości BuildBot. Na co stać to oprogramowanie? Jak się do niego zabrać i jak nawiązać z nim normalne EFEKTYWNE RELACJE ROBOCZE? Nasze doświadczenie możesz wykorzystać i u siebie, tworząc na swoim komputerze serwis do budowy i testowania swojego projektu.

Spis treści

Spis treści

1. Dlaczego BuildBot?
2. Koncepcja z BuildMasterem na czoła
3. Instalacja
4. Pierwsze kroki

5. Konfiguracja. Krok po kroku przepis

5.1 BuildmasterConfig
5.2 pracownicy
5.3 change_source
5.4 schedulers

5.5 BuildFactory
5.6 budowniczy

6. Przykład własnej konfiguracji

6.1 W drodze do swojego master.cfg
6.2 Praca z svn
6.3 Otrzymujesz e-mail: reporters są upoważnieni do zgłaszania

Udało nam się! Moje gratulacje

1. Dlaczego BuildBot?

Wcześniej na habr-e spotkałem artykuły na temat realizacji i pozwala uprościć przygotowanie kodu do wdrożenia. z użyciem BuildBot. Na przykład, ten wydawał mi się najbardziej informacyjny. Jest inny przykład — trochę prostszy. Te artykuły można uzupełnić przykładem z podręcznika, a to w przy następnej okazji, w języku angielskim. W sumie to całkiem niezły punkt wyjścia. Przeczytawszy te artykuły, z pewnością od razu zechcesz coś na BuildBot zrobić.

Stop! A czy ktoś w ogóle używał go w swoich projektach? Okazuje się, że tak, wielu zastosowało go w swoich zadaniach. Można znaleźć przykłady używania BuildBot i w archiwach kodów Google.

Jak więc wygląda logika ludzi używających Buildbot? Ведь есть другие инструменты: CruiseControl i Jenkins. Odpowiem tak. Dla większości zadań Jenkins rzeczywiście wystarczy. Z drugiej strony, BuildBot — jest bardziej elastyczny, przy tym zadania są tam rozwiązywane równie łatwo, jak w Jenkins. Wybór należy do Ciebie. Ale skoro szukamy narzędzia dla rozwijającego się projektu, dlaczego nie wybrać tego, które pozwala, opierając się na prostych krokach, uzyskać system budowy, mający interaktywność i unikalny interfejs.

Dla tych, których projekt docelowy jest napisany w Pythonie, pojawia się pytanie: „Dlaczego nie wybrać systemu integracji, który ma zrozumiały interfejs z perspektywy języka używanego w projekcie?”. W tym momencie warto przedstawić zalety. BuildBot.

A więc nasz „instrumentalny kwartet”. Określiłem cztery cechy. BuildBot:

  1. To framework o otwartym kodzie źródłowym na licencji GPL.
  2. To wykorzystanie Pythona jako narzędzia do konfiguracji oraz opisu wymaganych działań.
  3. To możliwość uzyskania odpowiedzi od maszyny, na której odbywa się kompilacja.
  4. To wreszcie minimalne wymagania dla hosta. Do rozwoju wymaga Pythona i Twisted, a nie wymaga maszyny wirtualnej ani maszyny Java.

2. Koncepcja z BuildMasterem na czoła

Przykład implementacji Continuous Integration z użyciem BuildBot

Centralne miejsce w architekturze rozdzielania zadań zajmuje BuildMaster.Jest to usługa, która:

  • śledzi zmiany w drzewie źródłowym projektu.
  • wysyła polecenia, które należy wykonać przez usługę Worker w celu zbudowania projektu i przetestowania go.
  • powiadamia użytkowników o wynikach wykonanych działań.

BuildMaster. konfiguruje się za pomocą pliku master.cfg. Ten plik znajduje się w katalogu głównym BuildMaster.. Później pokażę, jak ten katalog główny jest tworzony. Sam plik master.cfg zawiera skrypt Pythona, który używa wywołań BuildBot.

Następnym najważniejszym obiektem BuildBot jest Worker. Ta usługa może być uruchomiona na innym hoście z innym systemem operacyjnym, albo na tym samym, gdzie BuildMaster.. Może również istnieć w specjalnie przygotowanym wirtualnym środowisku z własnymi pakietami i zmiennymi. Takie wirtualne środowiska można przygotować za pomocą narzędzi Pythona, takich jak virtualenv, venv..

BuildMaster. przekazuje polecenia każdemu Workerz nich, a ten z kolei je wykonuje. Oznacza to, że proces budowania i testowania projektu może odbywać się na Worker-ie działającym na Windows oraz na innym Workerze działającym na Linuxie.

Checkout kodów źródłowych projektu odbywa się na każdym Worker-ie.

3. Instalacja

Tak więc, zaczynamy. Jako host będę używał Ubuntu 18.04. Na nim umieszczę jednego BuildMaster.-a oraz jednego Worker-a. Ale najpierw trzeba zainstalować Pythona 3.7:

sudo apt-get update
sudo apt-get install python3.7

Dla tych, którzy potrzebują Pythona 3.7.2 zamiast 3.7.1, można zrobić następujące:


sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt-get install python3.7
sudo ln -fs /usr/bin/python3.7 /usr/bin/python3
pip3 install --upgrade pip

Następnym krokiem jest zainstalowanie Twisted. i BuildBot, a także pakiety umożliwiające korzystanie z dodatkowych funkcji BuildBot-a.


/*Все что под sudo будет установленно для всех пользователей в директорию /usr/local/lib/python3.7/dist-packages*/

#На хосте который производит мониторинг Worker-ов 
sudo pip install twisted #Библиотека twisted
sudo pip install buildbot #BuildMaster
#Дополнительный функционал
pip install pysqlite3 #Устанавливаем базу sqllite в учебных целях
pip install jinja2 #framework наподобие django, для web и для почтовых рассыллок
pip install autobahn #Web cокеты для связи BuildMaster->Worker
pip install sqlalchemy sqlalchemy-migrate #Для отображения схемы базы данных
#Для Web отображения BuildBot-a
pip install buildbot-www buildbot-grid-view buildbot-console-view buildbot-waterfall-view
pip install python-dateutil #Отображение дат в web
#На стороне хоста который непосредственно осуществляет сборку и тестирование 
pip install buildbot-worker #Worker
#Дополнительный функционал
sudo pip install virtualenv #Виртуальная среда 

4. Pierwsze kroki

Czas na utworzenie BuildMaster.. Będzie u nas w folderze /home/habr/master.

mkdir master
buildbot create-master master # Właściwie tutaj go tworzymy

Następny krok. Utworzymy Worker. Będzie u nas w folderze /home/habr/worker.

mkdir worker
buildbot-worker create-worker --umask=0o22 --keepalive=60 worker localhost:4000 yourWorkerName password

Kiedy uruchomisz Worker, domyślnie utworzy on w /home/habr/worker folder z nazwą projektu, który został wskazany w master.cfg. A w folderze o nazwie projektu utworzy katalog build, a następnie będzie w nim tworzyć checkout. Katalogiem roboczym dla Worker-a stanie się katalog /home/habr/yourProject/build.

„Złoty” klucz
A teraz to, dla czego pisałem poprzedni akapit: skrypt, który Master zażąda od Worker-a, aby wykonać coś zdalnie w tym katalogu, nie zostanie wykonany, ponieważ skrypt nie ma uprawnień do uruchomienia. Aby to naprawić, potrzebny będzie klucz —umask=0o22, który wprowadza zakaz zapisu w tym katalogu, ale pozostawia uprawnienia do uruchomienia. A to dokładnie to, czego potrzebujemy.

BuildMaster. i Worker nawiązują ze sobą połączenie. Czasami zdarza się, że zostaje przerwane i Worker przez jakiś czas oczekuje na odpowiedź od BuildMaster.-a. Jeśli odpowiedź nie nadejdzie, połączenie jest restartowane. Klucz —keepalive=60 jest właśnie potrzebny, aby określić czas, po którym połącz jest ponownie uruchamiane.

5. Konfiguracja. Krok po kroku przepis

Konfiguracja BuildMaster. jest wykonywane po stronie maszyny, na której wykonaliśmy polecenie create-master. W naszym przypadku — to katalog /home/habr/master. Plik konfiguracyjny master.cfg jeszcze nie istnieje, jednak sama komenda już utworzyła plik master.cmg.sample. Należy go zmienić na master.cfg.sample do master.cfg

mv master.cfg.sample master.cfg

Otwórzmy ten master.cfg. I przeanalizujmy, z czego się składa. A potem spróbujemy stworzyć swój plik konfiguracyjny.

master.cfg

c['change_source'] = []
c['change_source'].append(changes.GitPoller(
    'git://github.com/buildbot/hello-world.git',
         workdir='gitpoller-workdir', branch='master',
         pollInterval=300))
                        
c['schedulers'] = []
c['schedulers'].append(schedulers.SingleBranchScheduler(
        name="all",
        change_filter=util.ChangeFilter(branch='master'),
        treeStableTimer=None,
        builderNames=["runtests"]))
c['schedulers'].append(schedulers.ForceScheduler(
        name="force",
        builderNames=["runtests"]))
                        
factory = util.BuildFactory()
                        
factory.addStep(steps.Git(repourl='git://github.com/buildbot/hello-world.git', mode='incremental'))
factory.addStep(steps.ShellCommand(command=["trial", "hello"],
                                   env={"PYTHONPATH": "."}))
                        
c['builders'] = []
c['builders'].append(
    util.BuilderConfig(name="runtests",
    workernames=["example-worker"],
    factory=factory))
                         
c['services'] = []
                        
c['title'] = "Hello World CI"
c['titleURL'] = "https://buildbot.github.io/hello-world/"
                        
                        
c['buildbotURL'] = "http://localhost:8010/"
                        
c['www'] = dict(port=8010,
                plugins=dict(waterfall_view={}, console_view={}, grid_view={}))
                        
c['db'] = {
    'db_url' : "sqlite:////state.sqlite",
}

5.1 BuildmasterConfig

c = BuildmasterConfig = {} 

BuildmasterConfig — to podstawowy słownik pliku konfiguracyjnego. Musi być koniecznie użyty w pliku konfiguracyjnym. Dla wygody w kodzie konfiguracyjnym wprowadzono jego alias „c”. Nazwy kluczy do c[«keyFromDist»] są stałymi elementami do interakcji z BuildMaster.. Dla każdego klucza jako wartość podstawiany jest odpowiedni obiekt.

5.2 pracownicy

c['workers'] = [worker.Worker("example-worker", "pass")]

Tym razem podajemy BuildMaster.- listę z Worker-ów. Sam Worker tworzyliśmy powyżej, podając you-worker-name i hasło. Teraz musimy wskazać je zamiast example-worker i pass .

5.3 change_source

c['change_source'] = []
c['change_source'].append(changes.GitPoller(
                            'git://github.com/buildbot/hello-world.git',
                             workdir='gitpoller-workdir', branch='master',
                             pollInterval=300))                

Po kluczu change_source słownika c uzyskujemy dostęp do listy, do której musimy dodać obiekt, który będzie sondował repozytorium z kodem źródłowym projektu. W przykładzie użyto repozytorium Git, które jest sondowane w pewnych odstępach.

Pierwszy argument to ścieżka do Twojego repozytorium.

workdir reprezentuje ścieżkę do folderu, w którym po stronie Worker-a w odniesieniu do ścieżki /home/habr/worker/yourProject/build git będzie przechowywać lokalną wersję repozytorium.

branch zawiera konkretną gałąź w repozytorium, którą należy monitorować.

pollInterval zawiera liczbę sekund, po upływie których BuildMaster. będzie sondować repozytorium w poszukiwaniu zmian.

Istnieje kilka metod śledzenia zmian w repozytorium projektu.

Najprostszą metodą jest Polling, który oznacza, że BuildMaster. okresowo pyta serwer z repozytorium. W przypadku, gdy commit odzwierciedli zmiany w repozytorium, to BuildMaster. z pewnym opóźnieniem utworzy wewnętrzny obiekt Change i przekaże go do obsługi zdarzeń Scheduler, która uruchomi proces budowania i testowania projektu na Worker-ie. Wśród tych kroków będzie wskazane update repozytorium. Właśnie na Worker-ie powstanie lokalna kopia repozytorium. Szczegóły tego procesu zostaną omówione poniżej w następnych dwóch sekcjach (5.4 i 5.5).

Jeszcze bardziej elegancką metodą śledzenia zmian w repozytorium jest bezpośrednie wysyłanie powiadomień z serwera, na którym jest on hostowany, do BuildMaster.-u o zmianie kodu źródłowego projektu. W takim przypadku, gdy tylko programista wprowadzi commit, serwer z repozytorium projektu wyśle wiadomość BuildMaster.-u. A ten z kolei przechwyci ją, tworząc obiekt PBChangeSource. Następnie ten obiekt zostanie przekazany do Scheduler, który zainicjuje kroki związane z budowaniem projektu i jego testowaniem. Ważną częścią tej metody jest praca z hook-skryptami serwera w repozytorium. W skrypcie hook-a, odpowiadającym za obsługę działań przy commit-ie, należy wywołać narzędzie sendchange i wskazać adres sieciowy BuildMaster.-a. Należy również wskazać port sieciowy, który będzie nasłuchiwał PBChangeSource. PBChangeSource, który zresztą jest częścią BuildMaster.-a. Ta metoda wymaga uprawnień admin-a na serwerze, na którym znajduje się repozytorium projektu. Najpierw należy wykonać kopię zapasową repozytorium.

5.4 schedulers


c['schedulers'] = []
c['schedulers'].append(schedulers.SingleBranchScheduler(
        name="all",
        change_filter=util.ChangeFilter(branch='master'),
        treeStableTimer=None,
        builderNames=["runtests"]))
c['schedulers'].append(schedulers.ForceScheduler(
        name="force",
        builderNames=["runtests"]))

schedulers – to element, który działa jako wyzwalacz, uruchamiający całą sekwencję budowania i testowania projektu.
Przykład implementacji Continuous Integration z użyciem BuildBot

Te zmiany, które zostały zarejestrowane change_source, przekształciły się w trakcie działania BuildBot-a w obiekt Change i teraz każdy Sheduler na ich podstawie tworzy zapytania o uruchomienie procesu budowy projektu. Określa również, kiedy te zapytania przekazać dalej do kolejki. Obiekt Builder przechowuje w sobie kolejkę zapytań i śledzi stan bieżącego budowania na oddzielnym Worker-e. Builder istnieje również na BuildMaster.-e i na Worker-e. On także wysyła z BuildMaster.-a do Worker-a już konkretną build — serię kroków, które należy wykonać.
Widzimy, że w obecnym przykładzie takich schedulers tworzy się 2 sztuki. Przy czym każda ma swój typ.

SingleBranchScheduler – jedna z najpopularniejszych klas harmonogramów. Obserwuje jedną gałąź i reaguje na zarejestrowaną w niej zmianę. Kiedy dostrzega zmiany, może odroczyć wysłanie zapytania o budowę (odroczenie na okres podany w specjalnym parametrze treeStableTimer). W name ustawiane jest imię harmonogramu, które będzie wyświetlane w BuildBot-interfejsie webowym. W ChangeFilter ustawiony jest filtr, przez który zmiany w gałęzi skłaniają harmonogram do wysłania zapytania o budowę. W builderNames wskazuje nazwę buildera, którą zadamy nieco później. Nazwa w naszym przypadku będzie taka sama, jak nazwa projektu:yourProject ForceScheduler.

to dość prosta rzecz. Ten rodzaj harmonogramu uruchamia się po kliknięciu myszą przez -interfejs webowy. Parametry mają tę samą istotę, co w BuildBotP.S. nr 3. Może się przydać SingleBranchScheduler.

Periodic
— to harmonogram, który uruchamia się w określonych, stałych odstępach czasowych. Wywołanie go wygląda mniej więcej tak: from buildbot.plugins import schedulers nightly = schedulers.Periodic(name="daily", builderNames=["full-solaris"], periodicBuildTimer=24*60*60) c['schedulers'] = [nightly]


factory = util.BuildFactory()
                        
factory.addStep(steps.Git(repourl='git://github.com/buildbot/hello-world.git', mode='incremental'))
factory.addStep(steps.ShellCommand(command=["trial", "hello"],
                                   env={"PYTHONPATH": "."}))                    

5.5 BuildFactory


periodicBuildTimer

ustawia czas tych odstępów w sekundach. BuildFactory

tworzy konkretną , która potem buildwysyła do buildera, którą zadamy nieco później. Nazwa w naszym przypadku będzie taka sama, jak nazwa projektu: określają kroki, które należy wykonać Worker. W tworzy konkretną -u. Kroki dodawane są za pomocą wywołania metody WorkeraddStep Pierwszym dodanym krokiem w tym przykładzie jest

git clean -d -f -f –x . Te działania zostały ujęte w parametrze, następnie git checkoutmethod , który nie jest widoczny, ale sugeruje domyślną wartośćfresh mode='incremental'. Parametr informuje, że pliki z katalogu, do którego przeprowadzany jest chechout , przy tym nieobecne w repozytorium pozostają nietknięte.Drugim dodanym krokiem jest wywołanie skryptu

trial z parametrem hello po stronie -a z katalogu Workerc zmienną środowiskową PATHONPATH=… W ten sposób możesz pisać własne skrypty i wykonywać je po stronie /home/habr/worker/yourProject/build -a przez krok Workerutil.ShellCommand . Te skrypty można umieścić bezpośrednio w repozytorium. Wtedy podczas-e będą trafiać do , przy tym nieobecne w repozytorium pozostają nietknięte.. Jednak wtedy są dwa „ale”: /home/habr/worker/yourProject/buildmusi być stworzony z kluczem

  1. Worker —umask aby nie blokował praw do wykonania po -e tych skryptów należy określić właściwość checkout-a.
  2. Przy git pushexacutable , aby przy-e nie utracić praw do wykonania skryptu Git. , przy tym nieobecne w repozytorium pozostają nietknięte.-e nie stracił prawa do wykonywania skryptu Git.

5.6 budowniczy


c['builders'] = []
c['builders'].append(util.BuilderConfig(name="runtests",
                                        workernames=["example-worker"],
                                        factory=factory))

O tym, co to jest Builder zostało opowiedziane tutaj. Teraz opowiem szczegółowo, jak to stworzyć. BuilderConfig jest konstruktorem buildera, którą zadamy nieco później. Nazwa w naszym przypadku będzie taka sama, jak nazwa projektu:. Takich konstruktorów w c[‘builders’] można zdefiniować kilka, ponieważ jest to lista obiektów buildera, którą zadamy nieco później. Nazwa w naszym przypadku będzie taka sama, jak nazwa projektu: tego typu. Teraz trochę przepiszemy przykład od BuildBot, przybliżając go do naszego zadania.


c['builders'] = []
c['builders'].append(util.BuilderConfig(name="yourProject",
                                            workernames=["yourWorkerName"],
                                            factory=factory))

Teraz opowiem o parametrach BuilderConfig.

name definiuje nazwę buildera, którą zadamy nieco później. Nazwa w naszym przypadku będzie taka sama, jak nazwa projektu:-a. Tutaj nazwaliśmy go ForceScheduler. Oznacza to, że na Worker-e zostanie utworzona ta ścieżka /home/habr/worker/yourProject/build. Sheduler znajduje buildera, którą zadamy nieco później. Nazwa w naszym przypadku będzie taka sama, jak nazwa projektu: dokładnie po tej nazwie.

workernames zawiera listę Worker-ów. Każdy z nich musi być dodany do c[‘workers’].

factory — konkretny build, z którym jest skojarzony buildera, którą zadamy nieco później. Nazwa w naszym przypadku będzie taka sama, jak nazwa projektu:. Wyśle on obiekt build na Worker do wykonania wszystkich kroków, wchodzących w skład tego build-a.

6. Przykład własnej konfiguracji

Oto architektura przykładowego projektu, którą proponuję zrealizować przez BuildBot
.

Jako system kontroli wersji będziemy używać svn. Sam repozytorium będzie znajdować się w pewnej chmurze. Oto adres tej chmury svn.host/svn/yourProject/trunk. W chmurze pod svn jest konto użytkownika: użytkownik, hasło: hasło. Skrypty, które stanowią kroki build-a będą także leżeć w gałęzi svn, w osobnym folderze buildbot/worker_linux. Te skrypty znajdują się w repozytorium z zachowanym właściwością executable.

BuildMaster. i Worker działają na jednym hoście project.host .BuildMaster. przechowuje swoje pliki w folderze /home/habr/master. Worker także przechowuje pod następującą ścieżką /home/habr/worker. Komunikacja procesów BuildMaster.-a i Worker-a odbywa się przez port 4000 za pomocą protokołu BuildBot-a, czyli ‘pb’ protokół.

Docelowy projekt w całości napisany jest w pythonie. Zadanie to śledzenie jego zmian, stworzenie pliku wykonywalnego, wygenerowanie dokumentacji, przeprowadzenie testów. W przypadku błędu, należy wysłać wiadomość do wszystkich programistów na e-mail o tym, że wystąpiła nieudana akcja.

Webowe wyświetlanie BuildBot podłączymy na porcie 80 dla project.host. Apatch nie jest konieczny. W składzie biblioteki twisted już znajduje się serwer webowy, BuildBot którego używa.

Do przechowywania informacji wewnętrznych będziemy używać BuildBot będziemy używać sqlite.

Do wysyłania wiadomości e-mail potrzebny jest host smtp.your.domain — na nim dozwolone jest wysyłanie wiadomości z adresu projectHost@your.domain bez autoryzacji. Również na hoście ‘smtp ‘ protokół nasłuchuje na porcie 1025.

Zaangażowanych w proces jest dwóch: admin i użytkownik. admin zarządza BuildBot. user jest osobą, która wykonuje commit-y.

Plik wykonywalny generowany jest przez pyinstaller. Dokumentacja jest generowana przez doxygen.

Dla tej architektury napisałem coś takiego master.cfg:

master.cfg


import os, re
from buildbot.plugins import steps, util, schedulers, worker, changes, reporters

c = BuildmasterConfig ={}

c['workers'] = [ worker.Worker('yourWorkerName', 'password') ]
c['protocols'] = {'pb': {'port': 4000}} 


svn_poller = changes.SVNPoller(repourl="https://svn.host/svn/yourProject/trunk",
                                svnuser="user",
                                svnpasswd="password",
                                pollinterval=60,
				split_file=util.svn.split_file_alwaystrunk
                                )

c['change_source'] =  svn_poller

hourlyscheduler = schedulers.SingleBranchScheduler(
                                name="your-project-schedulers",
				change_filter=util.ChangeFilter(branch=None),
                                builderNames=["yourProject"],
				properties = {'owner': 'admin'}
                                )

c['schedulers'] = [hourlyscheduler]

checkout = steps.SVN(repourl='https://svn.host/svn/yourProject/trunk',
                        mode='full',
                        method='fresh',
                        username="user",
                        password="password",
                        haltOnFailure=True)

	
projectHost_build = util.BuildFactory()  


cleanProject = steps.ShellCommand(name="Clean",
                 command=["buildbot/worker_linux/pyinstaller_project", "clean"]
                                )
buildProject = steps.ShellCommand(name="Build",
                 command=["buildbot/worker_linux/pyinstaller_project", "build"]
                                )
doxyProject = steps.ShellCommand(name="Update Docs",
                                command=["buildbot/worker_linux/gendoc", []]
                                )
testProject = steps.ShellCommand(name="Tests",
                                command=["python","tests/utest.py"],
                                env={'PYTHONPATH': '.'}
                                )

projectHost_build.addStep(checkout)
projectHost_build.addStep(cleanProject)
projectHost_build.addStep(buildProject)
projectHost_build.addStep(doxyProject)
projectHost_build.addStep(testProject)


c['builders'] = [
        util.BuilderConfig(name="yourProject", workername='yourWorkerName', factory=projectHost_build)
]


template_html=u'''
<h4>Status zbudowanej wersji: {{ summary }}</h4>
<p>Używana usługa do budowy: {{ workername }}</p>
<p>Projekt: {{ projects }}</p>
<p>Aby zobaczyć interfejs zarządzania, przejdź pod link: {{ buildbot_url }}</p>
<p>Aby zobaczyć wynik budowy, przejdź pod link: {{ build_url }}</p>
<p>Korzystając z WinSCP, możesz połączyć się z serwerem o ip: xxx.xx.xxx.xx. Logując się pod habr/password, pobierz zbudowany plik wykonywalny z katalogu ~/worker/yourProject/build/dist.</p>
<p><b>Budowanie zostało przeprowadzone za pomocą Buildbota</b></p>
'''

sendMessageToAll = reporters.MailNotifier(fromaddr="projectHost@your.domain",
					sendToInterestedUsers=True,
					lookup="your.domain",
					relayhost="smtp.your.domain",
					smtpPort=1025,
					mode="warnings",
					extraRecipients=['user@your.domain'],
              messageFormatter=reporters.MessageFormatter(
						template=template_html,
						template_type='html',
						wantProperties=True, 
                                                wantSteps=True)
					)
c['services'] = [sendMessageToAll]

c['title'] = "Proces budowy"
c['titleURL'] = "http://project.host:80/"

c['buildbotURL'] = "http://project.host"

c['www'] = dict(port=80,
                plugins=dict(waterfall_view={}, console_view={}, grid_view={}))


c['db'] = {
    'db_url' : "sqlite:////state.sqlite"
}

Na początek należy stworzyć BuildMaster.-a i Worker-a. Następnie wstaw ten plik master.cfg do /home/habr/master.

Kolejnym krokiem jest uruchomienie usługi BuildMaster.-a


sudo buildbot start /home/habr/master

Następnie uruchom usługę Worker-a


buildbot-worker start /home/habr/worker

Gotowe! Teraz Buildbot będzie śledzić zmiany i reagować na commit-u w svn, wykonując kroki kompilacji i testowania projektu z powyższej architektury.

Poniżej opiszę kilka cech powyższego master.cfg.

6.1 W drodze do swojego master.cfg


Podczas pisania swojego master.cfg pojawi się wiele błędów, dlatego konieczne będzie odczytanie pliku dziennika. Jest on przechowywany zarówno na BuildMaster.-e c z absolutną ścieżką /home/habr/master/twistd.log, jak i po stronie Worker-a z absolutną ścieżką /home/habr/worker/twistd.log. W miarę odczytywania błędów i ich naprawy konieczne będzie ponowne uruchomienie usługi BuildMaster.-a. Oto jak to zrobić:


sudo buildbot stop /home/habr/master
sudo buildbot upgrade-master /home/habr/master
sudo buildbot start /home/habr/master

6.2 Praca z svn


svn_poller = changes.SVNPoller(repourl="https://svn.host/svn/yourProject/trunk",
                               svnuser="user",
                               svnpasswd="password",
                               pollinterval=60,
                               split_file=util.svn.split_file_alwaystrunk
                        )

c['change_source'] =  svn_poller

hourlyscheduler = schedulers.SingleBranchScheduler(
                            name="your-project-schedulers",
                            change_filter=util.ChangeFilter(branch=None),
                            builderNames=["yourProject"],
                            properties = {'owner': 'admin'}
                        )

c['schedulers'] = [hourlyscheduler]

checkout = steps.SVN(repourl='https://svn.host/svn/yourProject/trunk',
                     mode='full',
                     method='fresh',
                     username="user",
                     password="password",
                     haltOnFailure=True)

Na początek przyjrzyjmy się svn_poller. To ten sam interfejs, który regularnie sprawdza repozytorium co minutę. W tym przypadku svn_poller odnosi się tylko do gałęzi trunk.Tajemniczy parametr split_file=util.svn.split_file_alwaystrunk określa zasady: jak dzielić strukturę katalogów svn na gałęzie. On również dostarcza im względne ścieżki. W zamian split_file_alwaystrunk upraszcza proces, informując, że w repozytorium tylko trunk..

W Schedulers jest określany ChangeFilter, który widzi Brak i łączy z nim gałąź trunk. poprzez określoną asocjację przez split_file_alwaystrunk. Reagując na zmiany w trunk., uruchamia buildera, którą zadamy nieco później. Nazwa w naszym przypadku będzie taka sama, jak nazwa projektu: c o nazwie ForceScheduler.

properties jest potrzebny, aby administrator otrzymywał powiadomienia o wynikach kompilacji i testów jako właściciel procesu.

Krok build-a checkout jest w stanie całkowicie usunąć jakiekolwiek pliki znajdujące się w lokalnej wersji repozytorium Worker-a. A następnie wykonać pełne svn update.Tryb jest ustawiony przez parametr mode=full, method=fresh. Parametr haltOnTailure mówi o tym, że jeśli svn update. wystąpi błąd, cały proces budowy i testowania powinien zostać wstrzymany, ponieważ dalsze działania nie mają sensu.

6.3 Otrzymujesz e-mail: reporters są upoważnieni do zgłaszania


reporterzy to serwis do wysyłania powiadomień na pocztę.


template_html=u'''
<h4>Status zbudowanej wersji: {{ summary }}</h4>
<p>Używana usługa do budowy: {{ workername }}</p>
<p>Projekt: {{ projects }}</p>
<p>Aby zobaczyć interfejs zarządzania, przejdź pod link: {{ buildbot_url }}</p>
<p>Aby zobaczyć wynik budowy, przejdź pod link: {{ build_url }}</p>
<p>Korzystając z WinSCP, możesz połączyć się z serwerem o ip: xxx.xx.xxx.xx. Logując się pod habr/password, pobierz zbudowany plik wykonywalny z katalogu ~/worker/yourProject/build/dist.</p>
<p><b>Budowanie zostało przeprowadzone za pomocą Buildbota</b></p>
'''
                        
sendMessageToAll = reporters.MailNotifier(fromaddr="projectHost@your.domain",
                                          sendToInterestedUsers=True,
                                          lookup="your.domain",
                                          relayhost="smtp.your.domain",
                                          smtpPort=1025,
                                          mode="warnings",
                                          extraRecipients=['user@your.domain'],
                                    messageFormatter=reporters.MessageFormatter(
                                                    template=template_html,
                                                    template_type='html',
                                                    wantProperties=True, 
                                                    wantSteps=True)
                                        )
c['services'] = [sendMessageToAll]

Może wysyłać wiadomości na różne sposoby.

MailNotifier wykorzystuje pocztę do wysyłania powiadomień.

template_html określa szablon tekstu do wysyłki. Do tworzenia struktury używany jest HTML. Jest zmodyfikowany przez silnik jinja2 (można porównać z django). BuildBot posiada zestaw zmiennych, których wartości są wstawiane w szablon podczas tworzenia tekstu wiadomości. Te zmienne są umieszczone w {{ podwójnych klamrach }}. Na przykład, summary wyświetla status wykonanych operacji, czyli success lub failure. A projects zostanie wyświetlone ForceScheduler. Tak, za pomocą poleceń kontrolnych w jinja2, zmiennych BuildBot-a oraz narzędzi formatowania łańcuchów Python można stworzyć całkiem informacyjną wiadomość.

MailNotifier zawiera następujące argumenty.

fromaddr – adres, z którego będą wysyłane powiadomienia.

sendToInterestedUsers=True wysyła wiadomość do właściciela oraz do użytkownika, który wykonał commit.

lookup — sufiks, który należy dodać do nazw użytkowników otrzymujących powiadomienia. Tak admin że użytkownik otrzyma powiadomienie na adres admin@your.domain.

relayhost określa nazwę hosta, na którym otwarty jest serwer smtp, a smptPort określa numer portu, który nasłuchuje smtp serwer.

mode=«warning» mówi, że wysyłka powinna odbywać się tylko w przypadku obecności przynajmniej jednego kroku build-a, który zakończył się statusem failure lub warning. W przypadku success wysyłka nie jest wymagana.

extraRecipients zawiera listę osób, które powinny otrzymać powiadomienia oprócz właściciela i osoby, która to wykonała. commit.

messageFormatter jest obiektem, który określa format wiadomości, jej szablon i zestaw zmiennych dostępnych z jinja2. Takie parametry jak wantProperties=True i wantSteps=True określają ten zestaw dostępnych zmiennych.

s[‘services’]=[sendMessageToAll] zapewnia listę usług, wśród których będzie nasz reporter..

Udało nam się! Moje gratulacje

Stworzyliśmy własną konfigurację i zobaczyliśmy funkcjonalność, jaką posiada BuildBot. Myślę, że to wystarczające, aby zrozumieć, czy to narzędzie jest potrzebne do realizacji Twojego projektu. Interesuje Cię? Przyda Ci się? Wygodnie się z nim pracuje? W takim razie pisałem ten artykuł nie na próżno.

I jeszcze jedno. Chciałbym, aby społeczność zawodowa, która korzysta z BuildBot, stało się szersze, podręczniki były tłumaczone, a przykładów było coraz więcej.

Dziękuję wszystkim za uwagę. Powodzenia.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster