- Зачем ?
- Инструменты и способы ораганизации
- Сравнение инструментов
- Примеры
- Полезные ссылки
Монорепозиторий это способ организации когда, когда все разрабатываемые пакети и приложения находятся в единственном репозитории. В чем преимущества перед обычной стратегией manyrepos ?
- Все процессы и изменения в репозиторий являются централизоваными.
- Тестирование и разработка связных компонентов приложения упрощается в разы.
- Упрощается настройка ci и тестов для репозитория т.к их нужно настроить только один раз.
- Упрощается процесс код ревью.
- При изменениях которые задевают несколько компонентов нужно создавать и ревьювить только один пул реквест.
- Комплексное тестирование на ci значително упрощается.
Из минусов можно вынести:
- Размер репоозитория очень быстро вырастает.
- История изменений может быть весьма запутанной.
- Если в монорепозитории находятся конечные приложения, то способ деплой может быть своеобразным
Что же даст переход на монорепозиторий ?
- Упрощение вокрфлоу,
- ускорения работы в постоянном меняющейся базе кода
- уменьшение количества файлов и зависимостей для разработки (prettier,eslint, husky .etc)
Самый базовый случай использования монорепозитория это просто создать папку pacakges и при деплое приложения скачаевается вся папка, а зависимости подтягиваются с это папки.
Сначала рассмотрим 1 вариант. У вас все пакеты находятся в одном репозитории и модификация модулей происходит только с монорепозитория. В таком случае для управления пакетами следует присмотреться к таким тулзам как lerna, yarn workspaces, bolt, oao, rush(). Эти инстурменты упрощают работу с множеством модулей, в особенности такие процессы как линкование зависимостей между модулями, уставновка дополнительных пакетов для модулей, массовые действия с пакетами.
Так же у вас может быть, что в монорепозитории вы развиваете библиотеку компонентов, которую потом используют ваши приложения в данном случае вам нужно делать publish компонентов в npm registry или свой собственный, а в зависящих приложениях модули уже будут скачиваться с помощью npm. C релизом и паблишем пакетов может помочь lerna, которая упрощает процес паблишинга модулей и апдейта зависимостей между модулями.
Более сложный вариант, когда работа с модулем идет в две стороны как с монорепозитория, так и с отдельного репозитория для этого модуля. Пример, вы создали библиотеку которую активно развивали в контексте вашего приватного монорепозитория, но потом сделали ее опенсорсной и вам нужно синхронизировать код между гитхабом и вашим монорепозиторием.
apps/
app1/ --> git/remotes/app1.git
app2/ --> git/remotes/app2.git
app3/ --> git/remotes/app3.git
app4/ --> git/remotes/app4.git
components/
comp1/
comp2/
comp3/
Апликейшины и компоненты находятся в одном репозитории и не имеют вложенных репозиториев. Компоненты не имеют никаких признаков самостоятельных репозиториев, в них лежат только нужные для них файлы т.е (Readme.md, package.json, тесты и код компонента).
В руте репозитория находятся файлы которые проверяют код стайл и прекомит хуки. Прекоммит хуки находятся в scripts/hooks. К вспомагательным файлам относятся .prettierrc, eslintrc, .npmrc, .env, lerna.json - эти файлы одни и относятся ко всем апликейшинам и компонентам.
Апликейшины в свою очередь являются полусамостоятельными репозиториями в которых есть ci для тестов (тесты запускаются при пуше в монорепозиторий или при пуше в отдельный репозиторий апликейшина) и все зависимости которые надо для апликейшинов. Репозитории апликейшинов являются read-only и если там происходят какие-то изменения, то синхронизация происходит вручную.
Установка зависимостей для всех апликейшинов работает через yarn workspaces, которые находятся в package.json, проперти workspaces. Проперти packages это массив glob, который указывает где находятся наши пакеты. Проперти nohoist это тоже набор glob, который отвечает за то, какие пакеты не надо поднимать в рутовый package json. Т.е если указать nohoist: ["**/webpack"], то в каждом пакете где указан вебпак, он не будет подниматься в рутовые node_modules
Для всех пакетов настроен ci, при пуше со своей ветке определяются компоненты которые изменились и для них запускаются тесты. Делается это через lerna updated, лерна находит для каждого пакета последню метку с версией и сравнивает были ли изменения, которые касались этого пакета после этого. Если на отдельной ветке были изменения все компонентов, то все последующие пуши в эту ветку будут тригерить запуск тестов во всех компонентах.
При мерже ветки в ветку мастер вызывается паблиш компонентов которые поменялись. Для компонентов это паблиш в npm registry, а для всех пакетов с private:true происходит пуш в собственный репозиторий этого апликейшина.
С помощью технологии git subtree split (или более быстрой версии splitsh/lite) происходит разбор гитовой истории и создание новой истории которая относится только к определенной подпапке апликейшина. т.е при мерже в мастер, мы делаем сплит истории для апликейшинов и пушим их в отельный репозиторий или можем выделить в отдельную ветку, но при этом у нас там будут файлы которые относятся, только к апликейшину и никакой инфы про монорепозиторий.
- нужно запаблишить пакеты с приставкой альфа
lerna publish --beta --force-publish="*"
- в ручную запушить апликейшин на свою ветку через git-split --prefix "./apps/alto-base" --target="refs/heads/branch-name"
- выбрать эту ветку на ci и задеплоить
пишем команду
lerna publish --force-publish="*" --exact --repo-version <current>.<version>.0 --skip-git --skip-npm
сurrent - мажорная версия текущего пакета varsion - максимальная минорная версия среди всех пакетов + 1 например версия пакета А - 2.4, версия И - 2.7 то версия с которой надо исправлять 2.8