Больше производительности и меньше времени ожидания

Настроить Monorepo было сложно… до 2020 года

Monorepo относится к стратегии размещения всех подпроектов в одном репозитории. В отличие от полирепо, каждый подпроект имеет собственное хранилище.

Monorepo дает множество преимуществ, в том числе лучшее сотрудничество и совместную ответственность. Есть много интересных статей, в которых обсуждаются плюсы и минусы монорепозитория. Один из моих любимых - Monorepo: пожалуйста! Автор Адам Джейкоб.

Всего несколько лет назад настройка проекта monorepo была сложной из-за несовместимости фреймворков. Например, многие менеджеры пакетов, такие как NPM, не были дружественными к монорепозиториям, а инфраструктуры, подобные Heroku, делают предположения о корне проекта, которые не верны для проектов с монорепозиторием.

К счастью, инструменты и платформы эволюционировали настолько, что создание проектов монорепозиториев стало намного проще.

CI для Monorepo по-прежнему неоптимален

Однако для создания простой в использовании инфраструктуры CI для проекта monorepo по-прежнему требуется несколько уловок.

В частности, в отличие от проекта polyrepo, где весь CI выполняется независимо от изменения, в проекте monorepo постоянный запуск всего CI, независимо от того, какой подпроект изменен, отнимает много времени и снижает производительность.

Например, проект monorepo может содержать сервер и несколько клиентов (например, мобильное приложение, веб-сайт и интерфейс командной строки), и все они имеют свои задачи CI. Чтобы поддерживать работоспособность кода, проекты часто требуют прохождения проверок CI перед объединением изменений, но это быстро становится обузой, когда разработчикам приходится ждать завершения всех этих тестов, просто чтобы исправить опечатку в документации.

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

Это возможно исправить с помощью самостоятельного решения

Для приведенного выше примера было бы замечательно, если бы мы могли динамически определять (на основе затронутых подпроектов) коллекцию задач CI, которые необходимы для проверки изменения кода, и только запускать и проверять их на наличие запросов на вытягивание.

Мы можем абстрагировать предложенное выше решение на две части: выборочный запуск и проверка задач CI.

Выборочно запускать задачи CI

Чтобы выборочно запускать задачи CI, мы можем использовать запуск по пути GitHub Actions (подробнее см. Синтаксис рабочего процесса для GitHub Actions).

У GitHub Actions есть уникальная функция, позволяющая нам указывать условия срабатывания, включая путь к файлу.

Например, следующая конфигурация рабочего процесса будет выполняться только в том случае, если какие-либо файлы в каталоге clients/app изменяются в запросе push или pull:

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

Вот пример конфигурации рабочего процесса для этого:

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

Выборочно проверять результаты CI

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

Собственный подход GitHub к контролю качества - это «защищенная ветвь», которая позволяет владельцам репозиториев определять статические требования (одинаковые для всех запросов на вытягивание) для объединения запросов на включение, включая проверки CI, обзоры кода и многое другое.

Он хорошо работает для проектов polyrepo, поскольку все аспекты проектов polyrepo связаны с самим проектом, поэтому имеет смысл проверять все результаты CI независимо от того, что это за изменение.

Однако для проектов monorepo, которые содержат несколько относительно независимых подпроектов, всегда проверять полный набор результатов CI излишне.

Чтобы преобразовать динамически составленный список результатов CI в статический набор результатов CI, нам нужен слой «прокладки», который собирает список необходимых CI и объединяет их в один результат CI (который является статическим).

Для этого нам нужна небольшая помощь от интеграции GitHub, Check Group, которая позволяет нам определять требования CI на уровне подпроекта и объединять их в одну проверку CI для запросов на вытягивание.

Когда все требования объединены в один (что-то вроде слоя прокладки), мы можем затем настроить правило «защищенной ветви», чтобы полагаться исключительно на эту единственную комбинированную проверку CI.

Чтобы определить требования CI для каждого подпроекта, мы можем использовать файл конфигурации, который выглядит следующим образом:

После настройки Check Group теперь объединит все требования подпроекта в одно, которое выглядит следующим образом:

Теперь у нас есть настройка CI, которая может определять требования CI на основе подпроектов.

Спасибо за чтение и удачного взлома с вашим следующим монорепроектом!