Пример реализации Continuous Integration с помощью BuildBot

от автора

BuildBot пробная конфигурация
(Image by Computerizer from Pixabay)

Привет!

Меня зовут Евгений Черкин, я программист команды разработчиков в горнодобывающей компании Polymetal.

Приступая к любому крупному проекту начинаешь задумываться: «Какой же софт лучше использовать для его обслуживания?». IT-проект перед выпуском очередной версии проходит ряд этапов. Хорошо, когда цепочка этих этапов автоматизирована. Сам по себе автоматизированный процесс выпуска новой версии IT-проекта называется Continuous Integration. BuildBot для нас оказался хорошим помощником, реализующим этот процесс.

В этой статье я решил представить обзор возможностей BuildBot. На что способен этот софт? Как к нему подступиться и как выстроить с ним нормальные ЭФФЕКТИВНЫЕ РАБОЧИЕ ОТНОШЕНИЯ? Наш опыт вы можете применить и у себя, создав на своей машине рабочий сервис сборки и тестирования вашего проекта.

1. Почему BuildBot?


Ранее на habr-e я встречал статьи о реализации Continuous Integration с использованием BuildBot. К примеру, вот эта показалась мне наиболее информативной. Есть другой пример — попроще. Данные статьи можно приправить примером с мануала, а это вдогоночку, на английском языке. В купе получается неплохая отправная точка. Прочитав эти статьи, вы наверняка сразу захотите что-нибудь на BuildBot сделать.

Стоп! А кто-то вообще использовал его в своих проектах? Оказывается да, многие применили его в своих задачах. Можно найти примеры использования BuildBot и в архивах кодов Google.

Так какова же логика людей, использующих Buildbot? Ведь есть другие инструменты: CruiseControl и Jenkins. Отвечу так. Для большинства задач Jenkins и правда будет достаточно. В свою очередь, BuildBot — более адаптивный, при этом задачи там решаются так же просто, как и в Jenkins. Выбирать вам. Но раз уж мы ищем инструмент для развивающегося целевого проекта, то почему бы не выбрать тот, который позволит, отталкиваясь от простых шагов, получить систему сборки, имеющую интерактивность и уникальный интерфейс.

У тех, чей целевой проект написан на python, возникает вопрос: «Почему бы не выбрать систему интегрирования, в которой есть понятный интерфейс с точки зрения языка, используемого в проекте?». И тут самое время представить преимущества BuildBot.

Итак, наш «инструментальный квартет». Для себя я определил четверку особенностей BuildBot:

  1. Это framework c открытым исходным кодом под лицензией GPL
  2. Это использование python как инструмент конфигурирования и описания требуемых действий
  3. Это возможность получать ответ со стороны машины, на которой происходит сборка
  4. Это, наконец, минимальные требования к Хосту. Для развертывания требуется python и twisted, и не требуется виртуальная машина и java-машина.

2. Концепция во главе с BuildMaster


BuildBot BuildMaster

Центральное место в архитектуре распределения задач занимает BuildMaster. Он представляет из себя сервис, который:

  • отслеживает изменения в дереве исходников проекта
  • посылает команды, которые следует выполнить сервису Worker для построения проекта и его тестирования
  • уведомляет пользователей о результатах выполненных действий

BuildMaster конфигурируется через файл master.cfg. Это файл лежит в корне BuildMaster. Позже я покажу, как этот корень создается. Сам по себе файл master.cfg содержит в себе python — скрипт, использующий вызовы BuildBot.

Следующий наиболее важный объект BuildBot имеет название Worker. Этот сервис может быть запущен на другом хосте c другой OS, а может и на том, где BuildMaster. Также он может существовать в специально заготовленной виртуальной среде со своими пакетами и переменными. Данные виртуальные среды могут быть приготовлены при помощи python-утилит вроде vertualenv, venv.

BuildMaster транслирует команды каждому Worker-у, а тот, в свою очередь, их выполняет. То есть получается, что процесс построения и тестирования проекта может идти на Worker-е под управлением Windows и на другом Worker-е под управлением linux.

Сheckout исходных кодов проекта происходит на каждом Worker-е.

3. Установка


Итак, поехали. В качестве хоста я буду использовать Ubuntu 18.04. На нем я размещу одного BuildMaster-a и одного Worker-a. Но сначала потребуется установить python3.7:

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

Для тех кому надо python3.7.2 вместо 3.7.1 можно сделать следующее:

 sudo apt-get update sudo apt-get 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 

Следующим шагом мы устанавливаем Twited и BuildBot, а так же пакеты позволяющие задействовать дополнительный функционал 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-watherfall-view pip install python-dateutil #Отображение дат в web #На стороне хоста который непосредственно осуществляет сборку и тестирование  pip install buildbot-worker #Worker #Дополнительный функционал sudo pip install virtualenv #Виртуальная среда  

4. Первые шаги


Время создать BuildMaster. Он будет у нас в папке /home/habr/master.

mkdir master buildbot create-master master # Собственно сдесь и создаем

Следующий шаг. Создадим Worker. Он будет у нас в папке /home/habr/worker.

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

Когда вы запустите Worker, то по умолчанию он создаст в /home/habr/worker папку с названием проекта, который указан в master.cfg. А в папочке с названием проекта он создаст директорию build, и далее в неё будет делать checkout. Рабочим каталогом для Worker-а станет директория /home/habr/yourProject/build.

«Золотой» ключик
А теперь то, ради чего я писал предыдущий абзац: скрипт, который Master потребует у Worker-а сделать удаленно в этой директории, не будет выполнен, поскольку у скрипта нет прав для запуска. Чтобы исправить ситуацию, потребуется ключик —umask=0o22, который накладывает запрет на запись в эту директорию, но права запуска оставит. А нам только это и нужно.

BuildMaster и Worker устанавливают между собой соединение. Случается, что оно обрывается и Worker некоторое время ожидает ответа от BuildMaster-а. Если ответа не последует, то подключение перезапускается. Ключ —keepalive=60 как раз и нужен для того, чтобы указать время, по прошествии которого connect перезагружается.

5. Конфигурация. Пошаговый рецепт


Конфигурация BuildMaster ведется на стороне машины, где мы выполняли команду create-master. В нашем случае — это каталог /home/habr/master. Конфигурационный файл master.cfg пока еще не существует, однако сама команда уже создала файл master.cmg.sample. Необходимо переименовать его в master.cfg.sample в master.cfg

mv master.cfg.sample master.cfg

Откроем этот master.cfg. И разберем то, из чего он состоит. А после этого попробуем сделать свой конфигурационный файл.

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 — базовый словарь конфигурационного файла. Он должен быть обязательно задействован в конфигурационном файле. Для удобства использования в коде конфигурации вводится его псевдоним «c». Названия ключей в c[«keyFromDist»] являются фиксированными элементами для взаимодействия с BuildMaster. Под каждый ключ в качестве значения подставляется соответствующий объект.

5.2 workers

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

На этот раз мы указываем BuildMaster-у список из Worker-ов. Сам Worker мы создавали выше, указав you-worker-name и password. Теперь их же надо указать вместо example-worker и 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))                 

По ключу change_source словаря c получаем доступ к списку, куда требуется положить объект, опрашивающий репозиторий с исходным кодом проекта. В примере используется Git репозиторий, который опрашивается с некоторой периодичностью.

Первый аргумент является путем к вашему репозиторию.

workdir представляет собой путь к папке, где на стороне Worker-а относительно пути /home/habr/worker/yourProject/build будет git хранить локальную версию репозитория.

branch содержит конкретную ветку в репозитории, за которой следует следить.

pollInterval содержит число секунд, по истечению которых BuildMaster будет опрашивать репозиторий на наличие изменений.

Есть несколько методов отслеживать изменения в репозитории проекта.

Самый простой метод — это Polling, который подразумевает, что BuildMaster периодически опрашивает сервер с репозиторием. В случае, если commit отразил изменения в репозитории, то BuildMaster с некоторой задержкой создаст внутренний объект Change и направит его в обработчик событий Scheduler, который и запустит шаги по сборке и тестированию проекта на Worker-е. Среди эти шагов будет указан update репозитория. Именно на Worker-е создастся локальная копия репозитория. Детали этого процесса будут раскрыты ниже в следующих двух разделах (5.4 и 5.5).

Еще более изящным методом отслеживания изменений в репозитории является прямая отправка сообщений от сервера, на котором он размещен, к BuildMaster-у об изменении исходных кодов проекта. В этом случае, как только разработчик сделает commit, сервер с репозиторием проекта пошлет сообщение BuildMaster-у. А тот, в свою очередь, его перехватит создав объект PBChangeSource. Далее этот объект будет передан в Scheduler, который и активирует шаги по сборке проекта и его тестированию. Важная часть этого способа эта работа с hook-скриптами сервера в репозитории. В скрипте hook-а, отвечающего за обработку действий при commit-е, необходимо вызвать утилиту sendchange и указать сетевой адрес BuildMaster-а. Указать нужно и сетевой порт, который будет слушать PBChangeSource. PBChangeSource, кстати, является частью BuildMaster-а. Это метод потребует права admin-a на сервере, где расположен репозиторий проекта. Предварительно потребуется сделать backup репозитория.

5.4 shedulers

 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 – это элемент, который выступает триггером, запускающим всю цепочку сборки и тестирования проекта.
BuildBot Shedulers

Те изменения, которые были зафиксированы change_source, преобразовались в процессе работы BuildBot-a в объект Change и теперь каждое Sheduler на их основе строит запросы на запуск процесса сборки проекта. Однако он определяет и то, когда эти запросы передать дальше в очередь. Объект Builder хранит у себя очередь запросов и отслеживает состояние текущей сборки на отдельном Worker-e. Builder существует и на BuildMaster-e и на Worker-e. Он же посылает с BuildMaster-а на Worker-а уже конкретный build — серию шагов, которую следует выполнить.
Мы видим, что в текущем примере таких schedulers создается 2 штуки. Причем, каждая имеет свой тип.

SingleBranchScheduler – один из самых популярных классов расписания. Он наблюдает за одной веткой и срабатывает по зафиксированному изменению в ней. Когда он видит изменения, то может отложить отправку запроса на построение (отложить на период, указанный в специальном параметре treeStableTimer). В name задается имя расписания, которое будет отображаться в BuildBot-web-интерфейсе. В ChangeFilter задается фильтр, пройдя который изменения в ветке побуждают расписание послать запрос на построение. В builderNames указывается имя builder-a, которое мы зададим чуть позже. Имя в нашем случае будет то же, что и имя проекта: yourProject.

ForceScheduler весьма простая штука. Этот вид расписания срабатывает по щелчку мыши через BuildBot-web-интерфейс. Параметры имеют ту же суть, что и в SingleBranchScheduler.

P.S. №3. Вдруг пригодится
Periodic — это расписание, которое срабатывает с определенной фиксированной по времени периодичностью. Выглядит вызов его примерно так

 from buildbot.plugins import schedulers nightly = schedulers.Periodic(name="daily",                               builderNames=["full-solaris"],                               periodicBuildTimer=24*60*60) c['schedulers'] = [nightly]                     

5.5 BuildFactory

 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": "."})) 

periodicBuildTimer задает время этой периодичности в секундах.

BuildFactory создает конкретный build, который потом builder отсылает на Worker. В BuildFactory указываются шаги, которые следует выполнить Worker-у. Шаги добавляются при помощи вызова метода addStep

Первый добавленный шаг в этом примере — git clean -d -f -f –x, затем git checkout. Эти действия заложены в параметре method, который наглядно не указан, но подразумевает значение по умолчанию fresh. Параметр mode=’incremental’ говорит о том, что файлы из директории, куда делается chechout, при этом отсутствующие в репозитории, остаются нетронутыми.

Второй добавленный шаг — это вызов скрипта trial c параметром hello на стороне Worker-а из директории /home/habr/worker/yourProject/build c переменной окружения PATHONPATH=… Таким образом, вы можете писать свои скрипты и выполнять их на стороне Worker-a через шаг util.ShellCommand. Данные скрипты можно положить прямо в репозиторий. Тогда при chechout-е они будут попадать в /home/habr/worker/yourProject/build. Однако тогда есть два «но»:

  1. Worker должен быть создан с ключем —umask для того, чтобы он не блокировал права на выполнения после checkout-a.
  2. При git push-е этих скриптов необходимо указать свойство exacutable, чтобы потом при chechout-e права на выполнение скрипта Git не потерял.

5.6 builders

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

О том, что такое Builder было рассказано здесь. Сейчас я поподробнее расскажу о том, как его создать. BuilderConfig является конструктором builder. Таких конструкторов в c[‘builders’] можно задать несколько, поскольку это лист объектов builder типа. Сейчас чуть перепишем пример от BuildBot, приблизив его к нашей задаче.

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

Теперь раскажу о параметрах BuilderConfig.

name задает имя builder-a. Здесь мы назвали его yourProject. Это значит, что на Worker-е будет создан этот самый путь /home/habr/worker/yourProject/build. Sheduler отыскивает builder как раз по этому имени.

workernames содержит лист Worker-ов. Каждый из которых должен быть добавленн в c[‘workers’].

factory — конкретный build, с которым ассоциирован builder. Он пошлет объект build на Worker для выполнения всех шагов, входящих в состав этого build-a.

6. Пример собственной конфигурации


Вот архитектура примера проекта, которую я предлагаю реализовать через BuildBot
.

В качестве системы контроля версиями будем использовать svn. Сам репозиторий будет находится в некоем облаке. Вот адрес этого облака svn.host/svn/yourProject/trunk. В облаке под svn есть учётка username: user, passwd: password. Скрипты, которые представляют из себя шаги build-a будут также лежать в ветке svn, в отдельной папке buildbot/worker_linux. Эти скрипты лежат в репозитории с сохраненным свойством executable.

BuildMaster и Worker работают на одном хосте project.host .BuildMaster хранит свои файлы в папке /home/habr/master. Worker же хранит по следующему пути /home/habr/worker. Связь процессов BuildMaster-а и Worker-а ведется через 4000 порт по протоколу BuildBot-a, то есть ‘pb’ протокол.

Целевой проект целиком написан на python-е. Задача отследить его изменения, создать executable файл, сгенерировать документацию, провести тестирование. В случае failure нужно всем разработчикам отослать сообщение на почту о том, что есть неудачно выполненное действие.

Web отображение BuildBot мы подключим на 80 порт для project.host. Apatch ставить не обязательно. В составе библиотеки twisted уже присутствует web сервер, BuildBot его использует.

Для хранения информации внутреннего назначения для BuildBot будем использовать sqlite.

Для почтовой рассылки нужен хост smtp.your.domain — на нем разрешена отправка писем с почты projectHost@your.domain без аутентификации. Так же на хосте ‘smtp ‘ протокол слушается на посту 1025.

Задействованных лиц в процессе двое: admin и user. admin администрирует BuildBot. user является лицом, совершающим commit-ы.

Exacutable файл генерируется через pyinstaller. Документация генерируется через doxygen.

Для данной архитектуры я написал вот такой 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>Статус построенного релиза: {{ summary }}</h4> <p>Используемый сервис для постраения: {{ workername }}</p> <p>Проект: {{ projects }}</p> <p>Для того что бы посмотреть интерфейс управления пройдите по ссылке: {{ buildbot_url }}</p> <p>Для того что бы посмотреть результат сборки пройдите по ссылке: {{ build_url }}</p> <p>Используя WinSCP можно подключиться к серверу c ip:xxx.xx.xxx.xx. Войдя под habr/password, забрать собранный executable файл с директории ~/worker/yourProject/build/dist.</p> <p><b>Построение было произведено через Buildbot</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'] = "The process of bulding" 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" } 

Для начала необходимо создать BuildMaster-а и Worker-a. Затем вставить этот файл master.cfg в /home/habr/master.

Следующим шагом требуется запустить службу BuildMaster

 sudo buildbot start /home/habr/master 

Затем запустить службу Worker-a

 buildbot-worker start /home/habr/worker 

Готово! Теперь Buildbot будет отслеживать изменения и срабатывать по commit-у в svn, выполняя шаги сборки и тестирования проекта с вышеуказанной архитектурой.

Ниже я распишу некоторые особенности вышеуказанного master.cfg.

6.1 На пути к своему master.cfg


Во время написания своего master.cfg будет совершено немало ошибок, потому потребуется чтение log-файла. Он храниться как на BuildMaster-e c абсолютным путем /home/habr/master/twistd.log, так и на стороне Worker-a с абсолютным путем /home/habr/worker/twistd.log. По мере чтения ошибки и ее исправления потребуется перезагрузка службы BuildMaster-a. Вот как это делается:

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

6.2 Работа с 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) 

Для начала взглянем на svn_poller. Это все тот же интерфейс, регулярно опрашивающий репозиторий раз в минуту. В данном случае svn_poller обращается только к ветке trunk. Загадочный параметр split_file=util.svn.split_file_alwaystrunk задает правила: как разбивать структуру папок svn на ветки. Он же предлагает им относительные пути. В свою очередь split_file_alwaystrunk упрощает процесс, говоря о том, что в репозитории только trunk.

В Schedulers указывается ChangeFilter, который видит None и ассоциирует с ним ветку trunk по заданной ассоциации через split_file_alwaystrunk. Реагируя на изменения в trunk, запускает builder c именем yourProject.

properties здесь нужен для того, чтобы админ получал рассылку у результатах сборки и тестирования как владелец процесса.

Шаг build-a checkout способен делать полное удаление любых файлов, лежащих в локальной версии репозитория Worker-а. A затем делать полный svn update. Режим настроен через параметр mode=full, method=fresh. Параметр haltOnTailure говорит о том, что если svn update будет выполнен с ошибкой, то весь процесс сборки и тестирования следует приостановить, так как дальнейшие действия не имеют смысла.

6.3 Вам письмо: reporters уполномочен заявить


reporters — это сервис рассылки уведомлений на почту.

 template_html=u'''\ <h4>Статус построенного релиза: {{ summary }}</h4> <p>Используемый сервис для постраения: {{ workername }}</p> <p>Проект: {{ projects }}</p> <p>Для того что бы посмотреть интерфейс управления пройдите по ссылке: {{ buildbot_url }}</p> <p>Для того что бы посмотреть результат сборки пройдите по ссылке: {{ build_url }}</p> <p>Используя WinSCP можно подключиться к серверу c ip:xxx.xx.xxx.xx. Войдя под habr/password, забрать собранный executable файл с директории ~/worker/yourProject/build/dist.</p> <p><b>Построение было произведено через Buildbot</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]  

Он может рассылать сообщения разными способами.

MailNotifier использует почту для рассылки уведомлений.

template_html задает шаблон текста для рассылки. Для создания разметки используется html. Он модифицирован движком jinja2 (можно сравнить с django). BuildBot имеет набор переменных, значения которых подставляются в шаблон в процессе формирования текста сообщения. Эти переменные вписаны в {{ двойные фигурные скобки }}. Так, например, summary выводит статус выполненных операций, то есть success или failure. А projects выведет yourProject. Так, при помощи управляющих команд в jinja2, переменных BuildBot-а и средств форматирования строк python можно создать вполне информативное сообщение.

MailNotifier содержит следующие аргументы.

fromaddr – адрес, с которого всем будет приходить рассылка.

sendToInterestedUsers=True отсылает сообщение владельцу и пользователю, который сделал commit.

lookup — суффикс, который надо добавить к именам пользователей, получающим рассылку. Так admin как пользователь получит рассылку по адресу admin@your.domain.

relayhost задает имя хоста, на котором открыт сервер smtp, a smptPort задает номер порта который слушает smtp сервер.

mode=«warning» говорит, что рассылку нужно делать только в случае наличия хотя бы одного шага build-а, который закончился со статусом failure или warning. В случае success рассылку делать не требуется.

extraRecipients содержит список лиц, кому следует сделать рассылку помимо владельца и лица, осуществившего commit.

messageFormatter является объектом, задающим формат сообщения, его шаблон, и набор переменных доступных из jinja2. Такие параметры, как wantProperties=True и wantSteps=True задают этот набор доступных переменных.

с[‘services’]=[sendMessageToAll] предоставляет список сервисов, среди которых и будет наш reporter.

Мы сделали это! Мои поздравления


Мы создали собственную конфигурацию и увидели функционал, на который способен BuildBot. Этого, думаю, достаточно для того, чтобы понять, нужен ли этот инструмент для создания вашего проекта. Он вам интересен? Он вам пригодится? С ним удобно работать? Тогда я писать эту статью не зря.

И еще. Хотелось бы, чтобы профессиональное сообщество, использующее BuildBot, стало шире, мануалы переводились, и примеров становилось еще больше.

Всем спасибо за внимание. Удачи.


ссылка на оригинал статьи https://habr.com/ru/post/460501/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *