Непрерывная интеграция с помощью Jabber. Изобретаем велосипед?

в 13:37, , рубрики: continuous integration, jabber, Блог компании Positive Technologies, Программирование, метки: ,

Непрерывная интеграция с помощью Jabber. Изобретаем велосипед?
В любом серьезном проекте в определенный момент встает вопрос организации процесса CI и, следовательно, вопрос о выборе средства для его автоматизации из широкого ряда представленных сейчас на рынке. Часто бывает, что при всем богатстве выбора найти подходящий вариант непросто, а иногда готовое решение является попросту слишком сложным, и выделять ресурсы на его поддержку нет ни желания, ни возможности. Кроме того, не хочется класть все яйца в одну корзину и иметь единственный сервер для сборки, тестирования, хранения дистрибутивов…

В нашей компании родилась идея — поддержать мировую тенденцию децентрализации и разделить CI-сервер на несколько машин, связав их между собой универсальным протоколом, доступным и машине, и человеку. Похоже на изобретение велосипеда? Вовсе нет.

На роль подобного средства общения отлично подошел протокол XMPP, он же Jabber, который являлся стандартом внутренней коммуникации компании, и следовательно, каждый разработчик, тестировщик и любой другой участник CI имел на своем рабочем месте IM с поддержкой Jabber. Соответственно, и любое готовое CI-решение, имеющее поддержку Jabber-плагина (а таковой сейчас имеют чуть ли не все серверы непрерывной интеграции), — легко вписывается в общую схему.

Для реализации этой идеи мы сделали следующее.

• Зарегистрировали в ростере Jabber учетные записи серверов buildserver, testserver, deployserver, hudson, создали для каждого группы, которым доступны для общения данные «пользователи», наполнили эти группы, определив таким образом список реальных пользователей, которым будет доступен тот или иной функционал.

Написали язык общения (на первое время — с минимальным набором команд), способный расширяться для реализации новых задач и простой в освоении для конечного пользователя. Команды: build, test, deploy, kill, ban, approve, help. Для всех этих команд в процессе внедрения CI добавлялись параметры, позволявшие существенно расширить их функциональность.

• Разработали шаблон элемента CI, использующего библиотеку jabber-net.dll, содержащего обработчики входящих команд и осуществляющего отсылку исходящих по результатам выполнения данных обработчиков.

Примерный шаблон на C#:

using System;

namespace Jabber
{
public class Jabberclnt : IDisposable
{
private jabber.client.JabberClient clnt = null;

~Jabberclnt()
{
Dispose(false);
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

public void Dispose(bool disposing)
{
if (clnt != null)
{
clnt.Close();
clnt.Dispose();
clnt = null;
}
}

public void Init(string user, string pwd)
{
clnt = new jabber.client.JabberClient ();
clnt.PlaintextAuth = true;
clnt.Server = "pt.int";
clnt.NetworkHost = "jabber.ptsecurity.ru";
clnt.Port = 5222;
clnt.User = user;
clnt.Password = pwd;
clnt.AutoLogin = false;
clnt.OnMessage += clnt_OnMessage;
clnt.Connect ();
}

void clnt_OnMessage (object sender, jabber.protocol.client.Message msg)
{
if (null == msg.Body)
return;
Console.WriteLine(string.Format("[{0}] {1}:{2}", DateTime.Now.ToString(), msg.From.User, msg.Body));
//обработчик сообщения
}

public bool SendMessage(string user, string msg)
{
bool res = true;
try
{
var jabberuser =new jabber.JID(user);
var jabberMessage = new jabber.protocol.client.Message(clnt.Document)
{
Body = msg,
To = jabberuser
};

clnt.Write(jabberMessage);
}
catch (System.Exception ex)
{
res = false;
}
return res;
}
}

class Program
{
static void Main(string[] args)
{
Jabberclnt clnt = new Jabberclnt();
clnt.Init("username", "password");

System.Threading.Thread.Sleep(1000);

clnt.SendMessage("buildserver@pt.int", "test");
System.Threading.Thread.Sleep(1000);
}
}
}

• Подняли сервер Hudson с плагинами im и jabber — для возможности общения с остальными участниками.

Реализовав эту идею, мы получили такую схему:

Непрерывная интеграция с помощью Jabber. Изобретаем велосипед?

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

Как я уже отметил, разработчик получает в виде IM c Jabber (у нас это Miranda) готовое средство управления и нотификации любого сервера — с учетом, конечно, наличия прав доступа к нему, прописанных в ростере Jabber.

Схема взаимодействия участников этой цепочки при полном цикле выглядит следующим образом.
Разработчик инициирует процесс.

Непрерывная интеграция с помощью Jabber. Изобретаем велосипед?

BuildServer сообщает об успешности и передает управление TestServer.

Непрерывная интеграция с помощью Jabber. Изобретаем велосипед?

После прогона тестов также следует сообщение об успешности, и управление передается на сервер развертывания.

Непрерывная интеграция с помощью Jabber. Изобретаем велосипед?

При завершении цикла оповещаются тот, кто запустил процесс, — и список заинтересованных лиц.

Непрерывная интеграция с помощью Jabber. Изобретаем велосипед?

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

Непрерывная интеграция с помощью Jabber. Изобретаем велосипед?

Итак, данная схема помогает решить следующий ряд вопросов.

• Нет ограничения в выборе готового CI в различных проектах и подразделениях: они легко интегрируются в общую структуру компании.
• Разделение ресурсов: загруженность buildserver не влияет на задачи тестирования и развертывания.
• Готовое средство управления (нотификации, автоматизации) при использовании библиотеки jabber CI становится доступным из любого приложения, библиотеки или сценария.
• Единый формат команд позволяет видеть полную картину того, что происходит сейчас в CI, и дает возможность пользователю вмещаться в любой стадии, имитируя любой сервер и таким образом сохраняя чистоту процесса.

Приглашаем обсудить достоинства и недостатки данного подхода. Если интересны подробности — задавайте вопросы: поделимся опытом :)

P.S. Доклад на эту тему был представлен на Application Developer Days (презентация и видео).

Автор: ptsecurity


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js