Как стать автором
Обновить

Комментарии 48

Вы же бинарники компилируете? Не веб-сервисы?

У нас раз в 1000 меньше кода, разработчиков и пул реквестов. Но мы деплоим в веб. И мы ушли от монорепо. Еще не до конца, ибо распиливаем. Но новые сервисы в новых рипо по доменам. Не суть.

Одна из главных причин ухода от монорепо это ожидание своей очереди мержа в мастер и последующего деплоя.

То есть:

  1. Ты создал пиар

  2. Запустились тесты и если все хороше можешь мержить

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

  4. Делаешь апдейт мастера в свой бранч и ждешь опять пока все тесты пробегут

  5. Пытаешь опять замержить в мастер - а там опять кто то успел свой бранч запихнуть.

Надоело... Почему я должен ждать всех если изменения у меня в моем небольшом сервисе?

Понятно что можно автоматизировать. Но все равно придется ждать всех. А мы стартап. И так много проблем а тут еще и деплой ждать чтобы потом проверить все ли там норм.

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

Сколько у вас разработчик ждет от нажатия кнопки "деплой" (не уверен что это слово подходит в вашем случае) до нотификации - готово?

Я так понимаю в ваших масштабах билды как в интеле могут бежать от нескольких часов до суток и ожидание каких-то пару часов мержа вообще не проблема?

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

Так а какая в сущности разница? Билды по конкретному замерженному коммиту добегут, протестируются и автоматизация подхватит его и пушнет на тестовый сервер. Все будут точно знать что вот этот конкретный коммит прошел все тесты и билдится нормально и с него можно разливать в staging и прод впоследствии.

А то что где-то там параллельно другие билды бегут — так и хорошо, и пусть бегут.

Один разработчик переименовал метод, другой использовал старое имя в новом месте. Параллельно оба билда проходят но при методе пулл реквестовт мастер перестал собираться

Это ведь проблема не спецефичная для монореп.

Но в малой репе сильно легче отличить коммиты, которые наверняка не конфликтуют — они будут в разных репах :)

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

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

Уже говорилось, что для этого нужно одно маленькое, но очень важное условие: чтобы при каждом коммите (или голове цепочки коммитов если так делают в конкретном подходе) проверялось всё, что зависит от этой библиотеки. А в большой репе это значит или всё перепроверять на каждый коммит (очень дорого), или каким-то образом находить компоненты, что зависят от этой библиотеки. Но если кто-то умеет искать такие компоненты, то что ему мешает точно так же искать это и в разных репах?


В немонорепе (при условии отдельного хранения либы, скажем, над ней работает отдельная команда) проблема вылезет только на этапе интеграционных тестов.

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


В правильно приготовленной монорепе обычно очень чистый и понятный граф зависимостей,

В правильном сетапе множества реп — точно так же. А в неправильном — и в монорепе чёрт-те что. Один коллега рассказывал, как он участвовал в написании кода телевизора одного великого корейского концерна. Из полсотни гиг вполне себе монорепы половина тупо не использовалась, была артефактом каких-то древних состояний, но выкинуть их было категорически запрещено (несмотря на то, что история бы сохранилась). И почему я должен предполагать, что монорепа будет использована как положено, а не как свалка, в которой уже всем пофиг, что за пределами его каталога?

Запустились тесты и если все хороше можешь мержить


На этом этапе можно ставить «automerge». То есть, PR, его рецензия, дальше прогоняются тесты и как только они прошли, идёт merge автоматом. То есть, если вы ушли пить чай, то вы не пропустили окно.

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


В идеале, что monorepo, что много разных должны быть одинаковы в этом аспекте. Ведь, по-факту, тесты должны проверять только то, что вы меняли (и зависящие от ваших изменений компоненты). То есть, когда появляются два независимых PR, при правильно настроенной системе тестирования они будут совершенно независимы — никакого merge conflict, никаких пересечений по тестам. И, соответственно, прекрасно сольются.

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


В микрорепозитариях, на первый взгляд нет конфликтов. Но только на первый взгляд. Если в с коллегой модифицируете две работающие в синергии библиотеки libA и libB из разных репозитариев, то при правильно настроенной системе тестирования вы должны получить конфликт, если ваши изменения несогласованы. Значит, ваши тесты вашего PR в репозитарии libA должны перезапускаться из-за слияния PR в репозитарии libB! То есть, в чистом виде ситуация монорепо!

Таким образом, при правильно настроенной системе тестирования компонент различие между monorepo и большим кол-вом мелких репозитариев несущественна. Но, блин, очень сложно эту систему правильно настроить и поддерживать.

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

Да, если возможно в монорепо сделать так что реально тестируется только код который изменился и только сервисы использующие эти тесты то по идее нужно будет только ждать тесты при создании пиара (при условии что другие команды реально коммитят только в свои файлики и они не затронут тебя и не затриггерят твои тесты). Тогда придется ждать только мерж который в принципе быстрый. Вот только это сложно сделать в монорепо с монолитом + отдельные сервисы + shared dependencies и т.д. Ну и nodejs в придачу =))

Рально не знаешь где выстрелит. Поэтому приходится прогонять все тесты и билдить все и вся внутри :/

Решили что отдельные репы будет быстрее организовать. Хотя да, не очень удобно для разработчика. Когда все стянул с одного репо и у тебя все в одной папочке, удобнее. Но вроде привыкли уже. Но самое главное что боль уходит и теперь свои фичеры можно задеплоить за 5 минут.

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

з.ы.

Возможно это только я замечаю, но мне кажется что отдельные репо тоже могут стать боттлнеком который в конце концо перевесит боттлнеки монорепо. Возможно при 200+ репо лучше подождать монорепо. Поэтому сейчас мы не делаем репо пер сервис а что-то вроде репо пер домейн где в своем домене можно шерить код, и там находятся свои воркеры, скедулеры и хттп сервисы. Но мы не ентерпрайз, еще стартап. Что будет лет через 5? Кто знает... Просто не первый раз читаю статьи о возвращении к монорепо но вот четкие метрики по которым можно принять решение не вижу.

Вот только это сложно сделать в монорепо с монолитом + отдельные сервисы + shared dependencies и т.д. Ну и nodejs в придачу =))


Кмк, тут разница в том, что в монорепо вы делаете «интеграционные тесты» по-умолчанию, а в отдельных репо вы их по-умолчанию не делаете. И то, и то плохо.

Еще отдельная боль как результат того что билдится все и вся в монорепо — со временем появились тесты которые падают рендомно и никто не знает как их чинить.


Они и в другом случае появятся. То есть, я не вижу причины, почему они не должны появиться. Просто там тесты прогоняются реже, поэтому эта проблема скрыта. Но не является ли она индикатором нарушения каких-то контрактов кода? Может быть они бы в каком-то мелком репо давно падают, просто вы их уже пол года не запускали?
Есть чудесная статья blog.ffwll.ch/2017/08/github-why-cant-host-the-kernel.html

В ней рассказывается, что наши инструменты (git/GitHub) недостаточны для управления огромными проектами вроде ядра Linux. Ещё аналогичное, видимо, можно написать по системам сборки. Кмк, в этом и ключ проблемы монорепо/мульти-репо.

Насколько я понял, у вас валидационная политика "протухает" при каждом коммите в мастер.

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

Рабочий trade-off в данном случае -- более умная экспирация политики. TFS, например, из коробки умеет в покоммитное протухание (как у вас было) и в экпирацию по времени. В статье указано, что сейчас экспирация политики составляет 24 часа, что позволяет разработчикам планово закатывать свои изменения в мастер. Минусом является возможность внесения ломающих изменений в мастер, но она довольно тривиально решается автоматическим мониторингом и ревертом ломающих коммитов.

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

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

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

А как "один продукт — один репозиторий" в корне отличается от "один продукт — одна папка" в монорепо?

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

И одновременно отсутствием возможности делать «транзакции» PR, когда код нескольких компонент одновременно синхронно меняется без сохранения обратной совместимости. Грубо говоря, меняете библиотечную функцию и все три места, в которых она используется в одном изменении.

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

Есть ещё ряд минусов мелких репозитариев, но они не так существены, кмк.

В общем, как обычно, нужно смотреть по месту. Серебряной пули нет.

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

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

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

И в результате у каждого из 100500 репозиториев получается своя собственная структура, свои соглашения, различные настройки, хуки, настройки доступа, что приносит свои собственные трудности

Знаете, есть странность с антипаттернами. Я вот совсем недавно перешёл из проекта которому 10 лет, из которых 6 лет я его наблюдал рядом и 4 плотно в нём варился. В нём нарушено множество паттернов. Много кода мы считали убогим 8 лет назад(через 2 года после старта проекта). И знаете что? Проект развивается, по фичам, по арту, по всему. И ниразу нам ни God Object ни множество Синглтонов не мешали. И моё мнение о паттернах и антипаттернах сильно уменьшилось. Есть вещи которые работают хорошо, а есть вещи которые работают дерьмово. Так вот по ходу жизни проекта я множество раз наблюдал как мы открывали абстракции нижележащих слоёв просто потому что абстракции текут всегда. Этот проект пережил две смены рендер движка целиком. При каждой смене выделялся слой разреза и подмены, и да, это требовало создать на месте правильный «водораздел» на интерфейсах и правильно внедрить зависимости. Но вот чего я ни разу в жизни не видел, так это то, как кто-то заложил «гибкую» архитектуру в проект, а потом спустя пять лет кто-то пришёл и легко подменил половину проекта. Есть плохой код, есть хороший. Но опыт показал что это не определяется наличием или отсутствием паттернов.

В итоге с момента введения этой метрики в октябре 2019 года мы добились того, что к февралю 2021 года количество проходящих билдов по расписанию увеличилось с 55.31% до 81.1%

Вот это жесть.

А жесть в чём? Вообще хороший результат для большого репо, над которым работают сотни или тысячи человек.

Жесть в том, что ребята затеяли переезд, а потом героически в течение двух лет пытаются это все заставить работать. На кой он такой монорепо нужен вообще? Выглядит как карго-культ с гугла.
Когда мы затевали переезд в монорепу, мы осознавали профиты, которые она нам принесет, и зачем мы это делаем. Но помимо этого, изначально осознавали и риски возникновения проблем. В результате мы эти риски приняли, как своеобразную плату за профит, который получаем. И мы видим, что получаемый от монорепо профит больше, чем описанные трудности.

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


На мой взгляд — и монорепо, и одно (а иногда и два-три) репо на каждый мелкий микросервис — это крайности, которые создают кучу проблем. А вот собрать несколько десятков микросервисов написанных на одном языке (в моём случае — Go) в общем репо, навязать им общий набор инструментов (линтеры, кодогенераторы, etc.) и структуру — очень сильно упрощает жизнь всем (как разработчикам так и админам). Скорее всего истина где-то тут, нужно избегать крайностей моно-/собственного репо, но собирать похожие проекты в общем репо смысл имеет. Но, боюсь, эта рекомендация однозначно подходит для Go (во многом потому, что у него очень быстрая компиляция и идеально работающее кеширование результатов компиляции и тестов, так что и без отвратительно сложного bazel компилируется и тестируется только то, что изменилось), а насчёт других языков всё может быть не так радужно.

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

Я полностью согласен, только вот у ЛК вряд ли количество кода сравнимо с перечисленными Вами компаниями. Монорепо действительно может быть верным решением для реально гигантских компаний, но вот для просто больших оно пока так же малополезно, как и для средних и маленьких. У больших компаний, в отличие от средних/мелких, уже появляются ресурсы чтобы играть в монорепо (что и описано в статье), но вот реальной пользы от этого крупным компаниями IMHO заметно меньше, чем вреда. А заниматься этим "на вырост", из соображений "ещё чуть-чуть и мы дорастём до размеров гугла" — ну, такое… абсолютное большинство не дорастает.

Мне кажется что в больших компаниях процессы в принципе настолько медленные что ожидание билда от нескольких часов до нескольких дней это норма.

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

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

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

Я так и не понял че такое монорепо... Гитхаб это монорепо или нет с вашей точки зрения? И почему, кстати, не гитхаб ынтерпрайс?

Комментарии как и ожидалось. А авторы вызывают только уважение. Сегодня есть только один правильный(tm) способ делать что-то и любой, кто включил свой личный мозг и выбрал для себя или своей компании не мейнстрим подход подвергается остракизму. Таково веяние времени.

Теперь по делу. Безусловно зависит от количества и размера продуктов, но работать с продуктом, к которому подцеплено много сабреп очень неудобно, особенно когда у сабреп есть свои сабрепы. Поиск и навигация по коду, когда он порезан на репы также затрудняется. У меня сейчас в корпструктуре доступно 200 реп, и быстренько найти нужные вещи не всегда возможно. Хотя я к монорепо не стремлюсь. Забавно наблюдать как многие крупные компании используют монорепы, а многие разработчики, которые не видели проектов хотябы на 10-15 человеколет, рассказывают как надо строит системы, на несколько порядков большие.

Да, количество и размер важны. Но помимо них в статье приведена вполне понятная причина, касаемая связанности:

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

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

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

Так о том и речь, что нужно взять и подумать своей головой, оценить плюсы и минусы, и сделать. И это правильный подход. Тем не менее в индустрии циркулируют стереотипные подходы вида всегда всё дроби и делай максимально гибко. А на самом деле не везде нужно и эффективно ни дробление ни гибкость. Считающим что везде и всюду нужна гибкость рекомендую порезать хлеб резиновым ножом.

Монорепозиторий - это удобно в том случае, если эта идеология органично впысывается в структуру проекта. Вот в моём случае есть проект (десктопное приложение), построенный на модульной архитектуре плагинов. Всего более трёхсот плагинов, на основе которых строится около десятка продуктов. Плагины - они как Лего кубики, что ли. В самом увестистом продукте около 70 плагинов, в небольших - штук 30. Есть плагины, которые используются почти во всех продуктах, а есть и специфические - только в одном-двух. Все плагины совместимы и независимы, у них универсальный инерфейс, работает принцип SOLID, в общем всё по учебнику. Микроядо одинаково для всех продуктов.

Раньше (года этак до 2010) мы хранили код в Microsoft Visual Source Safe. Там был монорепозиторий со всеми плагинами в куче и проекты, в которые были проброшены линки на используемые плагины. Это было офигенно удобно - я мог получить из VSS код, относящийся к конкретному продукту без необходимости получения всего монстр-репозитория, мог изменить код любого плагина в любом продукте и это автоматом распространялось на все продукты, где использовался этот плагин. При этом я мог посмотреть истории изменений по любому продукту - и туда попадало лишь то, что было слинковано. Плюс у продуктов были и специфические файлы, которые хотелось держать в системе контроля версий, но к монорепозиторию они не имели строго никакого отношения. Всё было в порядке и разложено по папочкам.

А потом мы переехали на TFS, который выкатили на замену устаревшему VSS. Мы мигрировали туда, перенеся историю изменений. И вот компания Microsoft за меня решила, что линки мне не нужны (типа они приводят к дупликации кода). Как по мне, так возможность расшарить файлы и папки из монорепозитория в отдельные проекты - это просто само собой разумеется, и для нас это была "киллер-фича". Я офигел настолько, что написал им и даже получил ответ, что линки я могу организовать на уровне файловой системы на компе разработчика, если мне так уж приспичило. Ну спасибо. Теперь монорепозиторий оброс кучей файлов проектов, командных файлов для сборки продуктов и прежнего удобства организации хранения кода, которое давали линки на уровне системы контроля версий, уже нет (и это не единственная фишка, которую не стали переносить из VSS в TFS - там раньше была возможность сделать Pin - "пришпилить" версию, и это тоже выпилили. Мол, нафига, если есть метки?). Хотя, конечно, сравнивать TFS и VSS - это всё равно что Теслу сравнивать с Запорожцем.

Я не готов вернуться на VSS :)

но разработчик не успел закомплитить пулл-реквест за 24 часа, то билд экспайрится

Что уж там, можно так: но если девелопер диднот мэйкнул закомплитить пулл-реквест за 24 аурс, то билд экспайрится. Таймлесс, аффордабл

Проблема: разные движки контроля версий в разных командах, отсутствие унификации CI/CD

Решение: слить все репозитории в один

Сам по себе монорепо - вполне себе рабочий вариант, но мне кажется что в данном случае это больше дань моде, чем непосредственное решение изначальной проблемы. Решением было бы перевести все команды на один движок контроля версий и унифицировать CI/CD

В статье на самом деле описано больше проблем. Например, проблема внесения изменений в несколько репозиториев, а как следствие сложность внесения изменений без сохранения обратной совместимости.
Каждый разработчик тянет локально себе весь репозиторий?
У нас есть адаптированная версия VFSForGit, а также можно использовать sparse-checkout.

Дико извиняюсь, а как решается проблема единой точки отказа? Монорепо упал, и весь Касперский кукует? Просто интересно

Мы строим отказоустойчивые сервисы, чтобы не допускать подобных ситуаций.
Зарегистрируйтесь на Хабре , чтобы оставить комментарий