Настройка непрерывной интеграции в Buildbot в Ubuntu 16.04

Buildbot – это система непрерывной интеграции на основе Python, которая может автоматизировать сборку, тестирование и релиз программ. Ранее вы узнали, как установить Buildbot, создать Unit-файл для этого сервиса и настроить Nginx как обратный прокси-сервер Buildbot.

Этот мануал научит настраивать непрерывную интеграцию Buildbot. Для примера здесь используется простое приложение Node.js. чтобы изолировать приложение от хост-системы, Buildbot использует контейнеры Docker. Мастер-сервер Buildbot будет отслеживать изменения в репозитории GitHub и автоматически тестировать новый код.

Требования

  • Сервер Ubuntu 16.04, 1 Гб оперативки минимум.
  • Пользователь sudo, настроенный брандмауэр. Все инструкции – здесь.

Кроме того, нужно выполнить следующие руководства, чтобы подготовить среду:

Форк репозитория проекта с GitHub

Для начала скопируйте репозиторий тестового проекта.

Откройте в браузере эту страницу. Этот репозиторий можно использовать для тестирования. Это простое приложение «hello world», написанное в фреймворке hapi.

Примечание: Поскольку этот пример можно отладить под множество систем непрерывной интеграции, вы можете заменить некоторые файлы конвейеров.

Buildbot будет выполнять сборку на сервере, а не в репозитории.

Затем можно настроить вебхуки Buildbot в репозитории, чтобы любое изменение автоматически запускало тестирование.

Нажмите Fork в правом верхнем углу.

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

Выбрав аккаунт или организацию, вы получите копию репозитория.

URL-адрес этого форка нужно использовать в конфигурации Buildbot. Теперь можно начать настройку Buildbot.

Настройка Docker для поддержки Buildbot

Начните с настройки Docker, чтобы система Buildbot использовала его в сборке. Сначала нужно настроить доступ между Docker и Buildbot, а затем создать образ Docker для использования в контейнерах.

Взаимодействие между Docker и Buildbot

Docker и Buildbot должны иметь несколько уровней доступа.

Убедитесь, что процесс Buildbot имеет доступ к демону Docker. Для этого добавьте пользователя buildbot в группу docker:

sudo usermod -aG docker buildbot

Buildbot получит доступ к группе после перезагрузки мастера Buildbot.

Также Buildbot должен знать, как взаимодействовать с Docker. Поскольку система Buildbot написана в Python, она использует пакет docker-py вместо простых команд Docker.

Установите docker-py:

sudo -H pip install docker-py

Теперь нужно открыть доступ из контейнеров к хост-системе и интернету. Для этого разблокируйте интерфейс docker0 в брандмауэре.

sudo ufw allow in on docker0

Создание образа Docker для воркера Buildbot

Затем нужно создать Docker-контейнер, который будет работать как воркер Buildbot для запуска тестов. Buildbot может динамически запускать контейнеры Docker, но для этого контейнеры нужно собрать с использованием компонентов воркеров Buildbot.

Buildbot предоставляет базовый образ воркера, который содержит все необходимое. Просто используйте этот образ как основу и установите в нем зависимости проекта.

В данном случае используется приложение Node.js, потому в образ нужно добавить Node.js.

Чтобы определить образ, откройте:

nano ~/Dockerfile

Здесь вы можете импортировать образ Buildbot. Для этого нужно добавить строку FROM buildbot/buildbot-worker:master.

Затем нужно переключиться в сессию root и установить Node.js, а потом вернуться в сессию пользователя buildbot.

FROM buildbot/buildbot-worker:master
USER root
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -
RUN apt-get install -y nodejs
USER buildbot

Сохраните и закройте файл.

Создав Dockerfile, вы можете собрать из него образ. Чтобы сообщить об установленных зависимостях, назовите образ npm-worker.

docker build -t npm-worker - < ~/Dockerfile

Docker создаст образ на основе команд, описанных в Dockerfile. Он загрузит базовый образ и его зависимости, установит Node.js, а затем сохранит полученную среду для образа npm-worker.

Настройка мастера Buildbot

Поскольку сейчас нужно определить совершенно новый процесс сборки, начните конфигурацию мастер-сервера с нуля. Чтобы не потерять текущие параметры, переместите исходный файл в резервный файл.

sudo mv /home/buildbot/master/master.cfg /home/buildbot/master/master.cfg.bak

Отобразите конфигурацию резервного файла, чтобы скопировать несколько значений для нового конфигурационного файла:

sudo cat /home/buildbot/master/master.cfg.bak

В новый файл нужно скопировать учетные данные и права пользователя. Найдите разделы, которые начинаются с c[‘www’][‘authz’] и c[‘www’][‘auth’].

. . .
c['www']['authz'] = util.Authz(
allowRules = [
util.AnyEndpointMatcher(role="admins")
],
roleMatchers = [
util.RolesFromUsername(roles=['admins'], usernames=['8host'])
]
)
c['www']['auth'] = util.UserPasswordAuth({'8host': 'Password'})
. . .

Скопируйте эти строки, чтобы использовать их в настройках. Добавьте эти данные в новую конфигурацию мастера Buildbot.

Теперь создайте новый файл master.cfg, где можно переопределить поведение экземпляра Buildbot.

sudo nano /home/buildbot/master/master.cfg

Базовые параметры проекта

Файл конфигурации Buildbot – это по сути модуль Python, гибкий, но немного сложный.

Начните с базовых параметров. Добавьте в файл:

# -*- python -*-
# ex: set filetype=python:
from buildbot.plugins import *
c = BuildmasterConfig = {}
# Basic config
c['buildbotNetUsageData'] = None
c['title'] = "Hello Hapi"
c['titleURL'] = "https://github.com/your_github_name/hello_hapi"
c['buildbotURL'] = "https://buildmaster_domain_name/"
c['protocols'] = {'pb': {'port': 9989}}

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

Вся конфигурация Buildbot определяется словарем BuildmasterConfig. Добавьте эту переменную в пустой словарь.

Чтобы уменьшить объем ввода, можно сократить переменную до с.

Некоторые моменты, которые следует учитывать в конфигурации:

  • buildbotNetUsageData имеет значение None. Чтобы передавать данные об использовании разработчикам, замените его на basic.
  • title и titleURL должны содержать имя проекта и ссылку на репозиторий GitHub соответственно. Укажите ссылку на свой форк.
  • buildbotURL содержит доменное имя мастера Buildbot с поддержкой шифрования SSL. Начните эту строку с https://.
  • Определение protocol ен привязано к localhost. Разрешите подключения из контейнеров Docker к интерфейсу docker0.

Настройка воркера Docker

Теперь нужно добавить настройки воркера Docker. Buildbot будет использовать Docker для создания воркеров по мере необходимости. Для этого Buildbot необходимо знать, как подключиться к Docker и какой образ использовать.

Вставьте следующий код в файл:

. . .
# Workers
c['workers'] = []
c['workers'].append(worker.DockerLatentWorker("npm-docker-worker", None,
docker_host='unix://var/run/docker.sock',
image='npm-worker',
masterFQDN='buildmaster_domain_name'))

Строка c[‘workers’] = [] демонстрирует базовое соглашение, которое мы будем использовать при написании конфигурации. Строка присваивает ключу в словаре  пустой список. Затем можно добавить  элементы в этот список. Это позволяет позже добавить элементы.

Чтобы определить воркер, создайте и вставьте экземпляр worker.DockerLatentWorker в список worker. Этот воркер будет называться npm-docker-worker, чтобы на него было просто ссылаться в дальнейшем. В docker_host укажите местонахождение сокета Docker и имя образа (npm-worker). В masterFQDN укажите домен мастера Buildbot.

Настройка планировщика

Затем нужно определить планировщик. Buildbot использует планировщики, чтобы решить, когда и как запускать сборку на основе полученных изменений.

Вставьте в конец файла:

. . .
# Schedulers
c['schedulers'] = []
c['schedulers'].append(schedulers.SingleBranchScheduler(
name="hello_hapi",
change_filter=util.ChangeFilter(project='your_github_name/hello_hapi', branch='master'),
treeStableTimer=3,
builderNames=["npm"]))

Опять можно применить метод добавления настроек в пустой список. Теперь вставьте экземпляр schedulers.SingleBranchScheduler, это позволит просматривать ветку в репозитории, что упрощает настройку.

Планировщик будет называться hello_hapi. Затем определите фильтр. Планировщик может получать множество изменений из разных источников. Фильтры изменений устанавливают критерии, которые определяют, должно ли данное изменение обрабатываться этим конкретным планировщиком. В этом случае фильтр будет работать на основе названия проекта и ветки.

Затем нужно определить treeStableTimer, что определяет интервал времени, в течение которого программа ждет обновления. Установите значение 3 секунды. Оно поможет предотвратить запуск нескольких небольших сборок для тесно связанных друг с другом изменений. В конце укажите имя сборщиков.

Настройка build factory для проекта Node.js

Теперь нужно настроить build factory для обработки проекта Node.js. Этот компонент отвечает за определение действий, которые необходимо предпринять для создания или тестирования проекта. Для этого нужно определить экземпляр util.BuildFactory, а затем добавить последовательные действия.

Вставьте в конец файла:

. . .
# Build Factories
npm_f = util.BuildFactory()
npm_f.addStep(steps.GitHub(repourl='git://github.com/your_github_name/hello_hapi.git', mode='full', method='clobber'))
npm_f.addStep(steps.ShellCommand(command=["npm", "install"]))
npm_f.addStep(steps.ShellCommand(command=["npm", "test"]))

Сначала определяется build factory по имени npm_f. Первое действие – это экземпляр steps.GitHub. здесь нужно установить репозиторий, который нужно загрузить сборщику. В mode нужно установить значение full, а в method — значение clobber, чтобы полностью сбрасывать репозиторий при загрузке нового кода.

Второе и третье действие – это steps.ShellCommand, которые определяют команды оболочки, которые будут запущены внутри репозитория во время сборки. В данном случае нужно запустить npm install для сбора зависимостей проекта, а затем npm test для запуска тестирования. Определение команд в виде списка ([«npm», «install»])  рекомендуется использовать в большинстве случаев.

Настройка сборщика

После build factory нужно определить настройки сборщика (builder). Он собирает ранее добавленные элементы и определяет процесс выполнения сборки.

Вставьте в файл:

. . .
# Builders
c['builders'] = []
c['builders'].append(
util.BuilderConfig(name="npm",
workernames=["npm-docker-worker"],
factory=npm_f))

Теперь в списке builders есть объект util.BuilderConfig. Помните, что build factory называется npm_f, воркер Docker – npm-docker-worker, а планировщик будет передавать задачи воркеру npm.

Сборщик определяет взаимосвязь между этими элементами, так что изменения планировщика запустят действия build factory в рабочем документе Docker.

Настройка базы данных и веб-интерфейса

Теперь нужно добавить настройки БД и веб-интерфейса. В отличие от многих предыдущих элементов, эти два параметра определяются как словари, а не как списки. Словарь db просто указывает на файл state.sqlite, который уже есть в /home/buildbot/master. Словарь www содержит много дополнительных параметров.

Вставьте следующий код в конец файла:

. . .
# Database
c['db'] = { 'db_url': "sqlite:///state.sqlite",}
# Web Interface
c['www'] = dict(port=8010, plugins=dict(waterfall_view={}, console_view={}))
# Auth info copied from the original configuration
c['www']['authz'] = util.Authz(
allowRules = [
util.AnyEndpointMatcher(role="admins")
],
roleMatchers = [
util.RolesFromUsername(roles=['admins'], usernames=['8host'])
]
)
c['www']['auth'] = util.UserPasswordAuth({'8host': 'Password'})
# End of auth info copied from the original configuration
# GitHub webhook receiver
c['www']['change_hook_dialects'] = {
'github': {
'secret': 'your_secret_value',
'strict': True,
}
}

Примечание: Укажите здесь учетные данные, которые вы скопировали из исходной конфигурации Buildbot.

После параметров базы данных создается словарь www, который начинается с определения порта для и видов, которые необходимо включить в веб-интерфейс. Затем нужно настроить аутентификацию с помощью данных из предыдущего файла конфигурации Buildbot.

В конце файла в словаре www определяется словарь change_hook_dialects. В нем можно определить хук GitHub, который будет прослушивать сообщения вебхука GitHub. В secret нужно указать надежную парольную фразу, которую GitHub будет использовать для аутентификации отправляемых сообщений.

Перезапуск мастера Buildbot

Теперь нужно перезапустить мастер Buildbot, чтобы обновить параметры.

Но сначала очень важно проверить синтаксис файла на ошибки. Для этого можно использовать команду:

sudo buildbot checkconfig /home/buildbot/master

Команда сообщит о любых обнаруженных ошибках. Если ошибок не обнаружено, вы получите сообщение, которое выглядит так:

Config file is good!

Если команда нашла ошибки, ознакомьтесь с сообщениями, чтобы понять, что не так. Откройте файл конфигурации и исправьте все ошибки.

Если ошибок нет, можно перезапустить мастер Buildbot.

sudo systemctl restart buildbot-master

Убедитесь, что операция прошла успешно:

sudo systemctl status buildbot-master
buildbot-master.service - BuildBot master service
Loaded: loaded (/etc/systemd/system/buildbot-master.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2017-06-27 19:24:07 UTC; 2s ago
Main PID: 8298 (buildbot)
Tasks: 2
Memory: 51.7M
CPU: 1.782s
CGroup: /system.slice/buildbot-master.service
└─8298 /usr/bin/python /usr/local/bin/buildbot start --nodaemon
Jun 27 19:24:07 bb5 systemd[1]: Started BuildBot master service

Создание вебхука GitHub

Теперь Buildbot может принимать сообщения вебхука GitHub. Нужно создать вебхук для вашего форка.

Перейдите к своему форку в веб-браузере.

https://github.com/your_github_user/hello_hapi

Кликните Settings, чтобы открыть настройки проекта. В меню слева нажмите Webhooks. При этом GitHub может запросить пароль.

Нажмите Add webhook, чтобы добавить новый вебхук.

Следующая страница будет содержать форму для определения вебхука. В поле Payload URL добавьте URL-адрес конечной точки хука GitHub. Он начинается с протокола https://, за которым следует доменное имя мастера Buildbot и /change_hook/github.

В Content type оставьте application/x-www-form-urlencoded. В поле Secret введите парольную фразу, указанную в конфигурационном файле мастера Buildbot.

Затем нажмите Add webhook.

После этого вы вернетесь на исходную страницу, где появится новый вебхук. Обновите страницу несколько раз, и рядом с вебхуком появится зеленый значок галочки – это значит, что сообщение было успешно передано.

Если же вы видите красный значок Х, кликните по вебхуку и найдите раздел Recent Deliveries. Дополнительную информацию об ошибке можно получить, кликнув по значку.

Тестирование вебхука

Теперь нужно убедиться, что Buildbot получает сообщения об обновлениях репозитория, запускает сборку в Docker и может выполнить тест.

На главной странице форка GitHub нажмите кнопку Create new file слева от зеленой кнопки Clone or download.

Создайте файл dummy_file.

Нажмите Commit new file.

Затем посетите веб-интерфейс Buildbot (при необходимости пройдите аутентификацию).

В зависимости от того, сколько времени прошло с момента создания файла dummy_file, вы можете увидеть процесс сборки.

Если сборка завершена, вы найдете ее в разделе recent builds.

Имя сборщика (npm) используется как метка сборки. Также здесь можно увидеть данные о предыдущих запусках сборщика.

Независимо от прогресса, щелкните по имени сборщика и перейдите на страницу сведений о сборке. Здесь содержится информация о выполненной сборке. Каждый шаг, который был добавлен в build factory, будет отображаться в специальном разделе.

Если вы нажмете на какой-либо шаг, отобразится вывод команды. Это может помочь при отладке.

Если при сборке произошла ошибка, вы можете проверить другие вкладки на странице сведений о сборке, а также файл /home/buildbot/master/twistd.log.

Настройка сервисов Buildbot

Теперь нужно внести несколько изменений в сервисы Buildbot.

На данный момент сервис buildbot-worker больше не нужен (воркер Docker запускается автоматически). Остановите и отключите старый воркер.

Для этого используйте команды:

sudo systemctl stop buildbot-worker
sudo systemctl disable buildbot-worker
Removed symlink /etc/systemd/system/buildbot-master.service.wants/buildbot-worker.service.

Вышеприведенный вывод указывает на то, что воркер был удален из автозагрузки. Чтобы убедиться, что сервис больше не запустится, введите:

sudo systemctl status buildbot-worker
buildbot-worker.service - BuildBot worker service
Loaded: loaded (/etc/systemd/system/buildbot-worker.service; disabled; vendor preset: enabled)
Active: inactive (dead)
Jun 27 21:12:48 bb6 systemd[1]: Started BuildBot worker service.
Jun 27 21:55:51 bb6 systemd[1]: Stopping BuildBot worker service...
Jun 27 21:55:51 bb6 systemd[1]: Stopped BuildBot worker service.

Последнее, что нужно сделать, — установить зависимость между мастером Buildbot и демоном Docker, поскольку сервис мастера Buildbot не сможет предоставить новых воркеров без Docker.

Откройте файл buildbot-master.service в каталоге /etc/systemd/system.

sudo nano /etc/systemd/system/buildbot-master.service

В раздел [Unit] добавьте docker.service в директиву After после элемента network.target. Добавьте директиву Wants и укажите в ней docker.service.

[Unit]
Description=BuildBot master service
After=network.target docker.service
Wants=docker.service
[Service]
User=buildbot
Group=buildbot
WorkingDirectory=/home/buildbot/master
ExecStart=/usr/local/bin/buildbot start --nodaemon
[Install]
WantedBy=multi-user.target

Сохраните и закройте файл.

Перезапустите systemd и мастер Buildbot.

sudo systemctl daemon-reload
sudo systemctl restart buildbot-master

Теперь мастер Buildbot будет запускаться после того, как будет доступен Docker.

Tags: , , , ,