Хотели ли вы когда-нибудь увидеть работу всей вашей инженерной организации в визуализации по мере ее выполнения? В этой статье я расскажу вам, как я использовал веб-крючки Github и бессерверные функции Netlify, а также простое веб-приложение Svelte, чтобы сделать именно это в моем новом интерактивном инструменте визуализации.
Графические визуализации — это интересный способ увидеть прогресс и помочь вашим организациям понять, что, хотя техническая работа иногда может казаться незаметной, количество усилий, затраченных на создание программного обеспечения, — это огромная командная работа!
В начале 2000-х годов был создан инструмент, который мог визуализировать историю версий вашего программного обеспечения, под названием Gource. Он был создан для сервера CVS, а затем портирован для работы с Subversion и, наконец, с git. Gource отображает изменения в репозитории в виде анимированной диаграммы дерева сил.
Видео о Gource как инструменте визуализации
Хотя Gource — отличный и мощный инструмент, он работает только локально, вы должны установить программное обеспечение и запустить его. Он анализирует исторические данные журнала фиксации и генерирует видеофайл с визуализацией, используя OpenGL. Он не показывает данные в реальном времени.
Вдохновляясь Gource и пользуясь преимуществом универсальности веба в 2022 году, я решил создать современный инструмент визуализации, работающий в браузере в реальном времени. Я хотел отобразить код, зафиксированный в репозитории GitHub или в организации, по мере его публикации или слияния.
- Что нужно для создания визуализатора GitHub:
- GitHub webhooks на помощь
- Как разместить приложение на Netlify
- Как создать пользовательский интерфейс с помощью Svelte
- Как сделать силовой направленный граф с помощью VisJS
- Как преобразовать данные веб-крючков GitHub в JS-объекты
- Как отобразить данные
- Как проверить данные веб-хука GitHub
- Использование в вашей организации
- Потенциальные расширения
- Другие идеи
Что нужно для создания визуализатора GitHub:
- Отправка сообщения через WebSockets каждый раз, когда происходит фиксация.
- Хостинговая платформа для предоставления URL полезной нагрузки
- Преобразование данных коммита в иерархию файлов/папок.
- Инструмент для отображения данных фиксации в графическом виде.
- Некоторый код для предотвращения сбоя приложения, если оно работает долгое время или получает миллионы сообщений.
GitHub webhooks на помощь
GitHub предлагает webhooks, которые позволяют интеграциям подписываться на события на github.com. При срабатывании события, например, нажатии фиксации, полезная нагрузка HTTP POST будет отправлена на URL, настроенный в вашей учетной записи GitHub. Webhooks можно установить для всей организации или для каждого репозитория, что означает, что я могу получать данные о коммитах в реальном времени по HTTP. Следующей задачей является настройка хостинг-провайдера для приема данных webhook и предоставления обратного вызова.
Как разместить приложение на Netlify
Мой документ-камера GitHub размещен на Netlify. Netlify и другие облачные продукты обеспечивают встроенную поддержку бессерверных функций, которые позволяют нам запускать код на стороне сервера без необходимости самостоятельно управлять сервером. Эти бессерверные функции могут быть привязаны к веб-приложению, контролируются по версиям, создаются и развертываются вместе с остальной частью приложения. Привязав бессерверную функцию к веб-приложению GitHub Visualizer, я могу установить эту функцию в качестве цели веб-крючка GitHub. После получения данных с GitHub я могу опубликовать их в пользовательском интерфейсе с помощью Ably (см. код).
Как создать пользовательский интерфейс с помощью Svelte
Для создания одностраничного веб-приложения, реагирующего на входящие изменения данных, обычно требуется фреймворк. Я решил построить визуализатор GitHub с помощью Svelte из-за его простого подхода к управлению состояниями, удобного синтаксиса, небольшого размера и скорости. Приложение состоит из двух компонентов Svelte: один подписывается на канал Ably и хранит историю коммитов GitHub в виде переменной в приложении, а другой может отображать историю коммитов GitHub в виде «графа, направленного силой».
Когда приходит сообщение от Ably, оно переносится в переменную истории. В Svelte встроена поддержка реактивного назначения переменных, что означает, что когда переменной присваивается новое значение, это изменение будет немедленно отражено в пользовательском интерфейсе. Следующая часть головоломки — визуализация данных.
Как сделать силовой направленный граф с помощью VisJS
Чтобы отобразить данные GitHub в виде графа, я использовал VisJS, библиотеку, специально разработанную для работы с большими объемами динамических данных. Граф отображается в браузере в виде HTML-канавы, что позволяет эффективно показывать сложную анимацию. Сетевой компонент VisJS был именно тем, что мне было нужно для отображения сложной диаграммы «узлов» и соединяющих их линий, называемых «ребрами». Узлы и ребра представлены, например, в JS-объектах:
var nodes = new vis.DataSet([
{id: 1, label: 'Node 1'},
{id: 2, label: 'Node 2'},
{id: 3, label: 'Node 3'},
{id: 4, label: 'Node 4'}
]);
var edges = new vis.DataSet([
{from: 1, to: 3},
{from: 1, to: 2},
{from: 2, to: 4},
]);
Это означает, что данные, которые приложение получает от веб-хука GitHub, должны быть преобразованы в этот формат для отображения.
Как преобразовать данные веб-крючков GitHub в JS-объекты
Когда приходит сообщение, приложение выполняет итерации по коммитам в сообщении. Оно сохраняет имена файлов, которые были созданы, изменены и удалены. Если файл был создан, то приложение разделит каждую часть пути к файлу и создаст «узел», а также «ребро», соединяющее каждый узел с его родительской частью, в конечном счете встречаясь в корне в центре, который является хранилищем. Каждый созданный узел имеет полный путь к этой точке в качестве идентификатора, а каждое ребро получает свой идентификатор, установленный в «{from}=>{to}», чтобы в будущем их можно было найти по пути к файлу.
Пример узла может выглядеть следующим образом:
{
id: "docs/content/tutorials/github-vis.js",
label: "github-vis.js"
group: "docs",
isFile: true,
isRepository: false,
isDirectory: false
}
И пример края:
{
from: "docs/content/tutorials"
to: "docs/content/tutorials/github-vis.js"
id: "docs/content/tutorials/=>docs/content/tutorials/github-vis.js"
}
Для каждого созданного файла создаются новые узлы, а для любого удаленного файла узлы удаляются. Для всех созданных и измененных узлов создаются грани. Приложение также сохраняет очередь (массив «первым пришел — первым ушел») всех созданных узлов, и когда оно достигает максимального количества узлов для отображения, оно удаляет самые старые элементы из верхней части массива. Это позволит приложению не занимать неограниченный объем памяти, если организация очень загружена и поступают миллионы сообщений. Узлы, которые были изменены, удаляются из очереди и помещаются обратно в ее конец, чтобы они не были удалены преждевременно.
Как отобразить данные
Теперь данные находятся в структуре, которая представляет файлы, присутствующие в последних N коммитах (сколько бы вы ни решили хранить). Следующая задача — написать код Svelte, который будет запускаться каждый раз, когда структура данных меняется, и который будет делать следующее:
- Получить отображаемые в данный момент узлы
- Найти все узлы в структуре данных, которые еще не были отображены.
- Добавить эти узлы в граф направленного действия
- Добавить новые ребра в граф, чтобы соединить добавленные узлы
- Удалить все узлы, которые больше не находятся в структуре данных.
VisJS имеет реактивный DataSet, который может быть использован для этого, приложению просто нужно проверить идентификаторы узлов и добавить/удалить узлы, чтобы вызвать повторный рендеринг. Дифференциация набора данных и структуры данных таким образом означает, что мы не будем постоянно воссоздавать все узлы при каждой фиксации. Это также означает, что физика, применяемая VisJS к графу (сила, которая заставляет узлы отталкиваться друг от друга), последовательна, и они не будут прыгать.
Как проверить данные веб-хука GitHub
В этом проекте есть одна последняя загвоздка — необходимо убедиться, что люди не могут просто подставить данные в наш API и сломать приложение. К счастью, GitHub поддерживает подписание webhooks с помощью HMAC-подписи. Вы придумываете пароль и вводите его в поле secret в GitHub при настройке своих webhooks. В бессерверной функции мы используем криптомодуль, встроенный в NodeJS, для проверки HMAC и пересылаем ее по каналам Ably только в том случае, если подписи совпадают с общим секретом.
Использование в вашей организации
- Клонируйте репозиторий: https://github.com/ably-labs/github-commit-visualizer.git.
- Разверните его на Netlify (или другом хостинге/провайдере бессерверных функций), не забыв установить ключ API Ably и секрет GitHub webhooks в качестве переменных окружения.
- Добавьте URL функции в качестве крючка GitHub из вашего орг- или репозитория в развернутое приложение.
- Наблюдайте, как ваши красивые визуализации появляются на свет!
Потенциальные расширения
Существует так много способов расширить этот проект. В полезной нагрузке GitHub возвращается много данных о коммите, поэтому визуализация может быть расширена, чтобы показывать имена пользователей рядом с изменениями файлов.
Другие идеи
- Выделить узлы цветом по последним изменениям, чтобы старые обновления исчезали по мере поступления новых.
- Сделать так, чтобы узлы при нажатии на них ссылались на соответствующий файл в GitHub
- Добавить опцию перемотки, чтобы можно было посмотреть назад во времени.
- Добавить пользовательский интерфейс для выбора максимального количества отображаемых узлов, для тех, у кого маленькие экраны.
Код для этого проекта является открытым и доступен на GitHub, в нашей организации Ably-Labs. Пожалуйста, возьмите его и сделайте его своим. Я очень открыт для PR, и дайте мне знать, если вы обнаружите какие-либо проблемы. Надеюсь, вам понравится визуализация ваших собственных проектов!