Комментарии 48
Вы же бинарники компилируете? Не веб-сервисы?
У нас раз в 1000 меньше кода, разработчиков и пул реквестов. Но мы деплоим в веб. И мы ушли от монорепо. Еще не до конца, ибо распиливаем. Но новые сервисы в новых рипо по доменам. Не суть.
Одна из главных причин ухода от монорепо это ожидание своей очереди мержа в мастер и последующего деплоя.
То есть:
Ты создал пиар
Запустились тесты и если все хороше можешь мержить
Но пока твои билды бежали кто то уже замержил свой бранч в мастер, и там соответственно опять пробегаются тесты, билд и т.д.
Делаешь апдейт мастера в свой бранч и ждешь опять пока все тесты пробегут
Пытаешь опять замержить в мастер - а там опять кто то успел свой бранч запихнуть.
Надоело... Почему я должен ждать всех если изменения у меня в моем небольшом сервисе?
Понятно что можно автоматизировать. Но все равно придется ждать всех. А мы стартап. И так много проблем а тут еще и деплой ждать чтобы потом проверить все ли там норм.
С отдельными репо, небольшими, ты не зависишь от других команд и разработчиков.
Сколько у вас разработчик ждет от нажатия кнопки "деплой" (не уверен что это слово подходит в вашем случае) до нотификации - готово?
Я так понимаю в ваших масштабах билды как в интеле могут бежать от нескольких часов до суток и ожидание каких-то пару часов мержа вообще не проблема?
Соответственно, разработчики, которые разрабатывают код за пределами этого подмножества, могут все делать как обычно, как будто вы ничего не мержили.
Так а какая в сущности разница? Билды по конкретному замерженному коммиту добегут, протестируются и автоматизация подхватит его и пушнет на тестовый сервер. Все будут точно знать что вот этот конкретный коммит прошел все тесты и билдится нормально и с него можно разливать в staging и прод впоследствии.
А то что где-то там параллельно другие билды бегут — так и хорошо, и пусть бегут.
Один разработчик переименовал метод, другой использовал старое имя в новом месте. Параллельно оба билда проходят но при методе пулл реквестовт мастер перестал собираться
Это ведь проблема не спецефичная для монореп.
Но в малой репе сильно легче отличить коммиты, которые наверняка не конфликтуют — они будут в разных репах :)
В правильно приготовленной монорепе обычно очень чистый и понятный граф зависимостей, и отличить неконфликтующие коммиты также довольно просто - если графы не пересекаются, конфликта точно нет. Плюс в монорепе вы не сможете даже закоммитать ломающий чейндж в какую-нибудь либу, которая в случае не монорепы будет с некоторой долей вероятности лежать в отдельном репозитории. В монорепе просто сломается билд. В немонорепе (при условии отдельного хранения либы, скажем, над ней работает отдельная команда) проблема вылезет только на этапе интеграционных тестов.
Плюс в монорепе вы не сможете даже закоммитать ломающий чейндж в какую-нибудь либу, которая в случае не монорепы будет с некоторой долей вероятности лежать в отдельном репозитории. В монорепе просто сломается билд.
Уже говорилось, что для этого нужно одно маленькое, но очень важное условие: чтобы при каждом коммите (или голове цепочки коммитов если так делают в конкретном подходе) проверялось всё, что зависит от этой библиотеки. А в большой репе это значит или всё перепроверять на каждый коммит (очень дорого), или каким-то образом находить компоненты, что зависят от этой библиотеки. Но если кто-то умеет искать такие компоненты, то что ему мешает точно так же искать это и в разных репах?
В немонорепе (при условии отдельного хранения либы, скажем, над ней работает отдельная команда) проблема вылезет только на этапе интеграционных тестов.
Что вы называете тут "интеграционными тестами" и почему оно не применяется по-вашему в случае монорепы? Проверка зависящих от этой библиотеки — это интеграционные тесты или нет? Почему это определение может зависеть от того, одна репа или несколько?
В правильно приготовленной монорепе обычно очень чистый и понятный граф зависимостей,
В правильном сетапе множества реп — точно так же. А в неправильном — и в монорепе чёрт-те что. Один коллега рассказывал, как он участвовал в написании кода телевизора одного великого корейского концерна. Из полсотни гиг вполне себе монорепы половина тупо не использовалась, была артефактом каких-то древних состояний, но выкинуть их было категорически запрещено (несмотря на то, что история бы сохранилась). И почему я должен предполагать, что монорепа будет использована как положено, а не как свалка, в которой уже всем пофиг, что за пределами его каталога?
Запустились тесты и если все хороше можешь мержить
На этом этапе можно ставить «automerge». То есть, PR, его рецензия, дальше прогоняются тесты и как только они прошли, идёт merge автоматом. То есть, если вы ушли пить чай, то вы не пропустили окно.
С отдельными репо, небольшими, ты не зависишь от других команд и разработчиков.
В идеале, что monorepo, что много разных должны быть одинаковы в этом аспекте. Ведь, по-факту, тесты должны проверять только то, что вы меняли (и зависящие от ваших изменений компоненты). То есть, когда появляются два независимых PR, при правильно настроенной системе тестирования они будут совершенно независимы — никакого merge conflict, никаких пересечений по тестам. И, соответственно, прекрасно сольются.
С отдельными репо, небольшими, ты не зависишь от других команд и разработчиков.
В микрорепозитариях, на первый взгляд нет конфликтов. Но только на первый взгляд. Если в с коллегой модифицируете две работающие в синергии библиотеки libA и libB из разных репозитариев, то при правильно настроенной системе тестирования вы должны получить конфликт, если ваши изменения несогласованы. Значит, ваши тесты вашего PR в репозитарии libA должны перезапускаться из-за слияния PR в репозитарии libB! То есть, в чистом виде ситуация монорепо!
Таким образом, при правильно настроенной системе тестирования компонент различие между monorepo и большим кол-вом мелких репозитариев несущественна. Но, блин, очень сложно эту систему правильно настроить и поддерживать.
Понятно что с микро-репозиториями свои проблемы и сложности. Но там они возникают в конкретных случая и как бы выше на уровне шеред стафф и интерфейсов взаимодействия.
Да, если возможно в монорепо сделать так что реально тестируется только код который изменился и только сервисы использующие эти тесты то по идее нужно будет только ждать тесты при создании пиара (при условии что другие команды реально коммитят только в свои файлики и они не затронут тебя и не затриггерят твои тесты). Тогда придется ждать только мерж который в принципе быстрый. Вот только это сложно сделать в монорепо с монолитом + отдельные сервисы + shared dependencies и т.д. Ну и nodejs в придачу =))
Рально не знаешь где выстрелит. Поэтому приходится прогонять все тесты и билдить все и вся внутри :/
Решили что отдельные репы будет быстрее организовать. Хотя да, не очень удобно для разработчика. Когда все стянул с одного репо и у тебя все в одной папочке, удобнее. Но вроде привыкли уже. Но самое главное что боль уходит и теперь свои фичеры можно задеплоить за 5 минут.
Еще отдельная боль как результат того что билдится все и вся в монорепо - со временем появились тесты которые падают рендомно и никто не знает как их чинить. А те кто их писал уже не работают тут. Бывает задеплоить одну строчку кода берет пол дня потому что оно падает а ответственного за этот код хрен найдешь.
з.ы.
Возможно это только я замечаю, но мне кажется что отдельные репо тоже могут стать боттлнеком который в конце концо перевесит боттлнеки монорепо. Возможно при 200+ репо лучше подождать монорепо. Поэтому сейчас мы не делаем репо пер сервис а что-то вроде репо пер домейн где в своем домене можно шерить код, и там находятся свои воркеры, скедулеры и хттп сервисы. Но мы не ентерпрайз, еще стартап. Что будет лет через 5? Кто знает... Просто не первый раз читаю статьи о возвращении к монорепо но вот четкие метрики по которым можно принять решение не вижу.
Вот только это сложно сделать в монорепо с монолитом + отдельные сервисы + shared dependencies и т.д. Ну и nodejs в придачу =))
Кмк, тут разница в том, что в монорепо вы делаете «интеграционные тесты» по-умолчанию, а в отдельных репо вы их по-умолчанию не делаете. И то, и то плохо.
Еще отдельная боль как результат того что билдится все и вся в монорепо — со временем появились тесты которые падают рендомно и никто не знает как их чинить.
Они и в другом случае появятся. То есть, я не вижу причины, почему они не должны появиться. Просто там тесты прогоняются реже, поэтому эта проблема скрыта. Но не является ли она индикатором нарушения каких-то контрактов кода? Может быть они бы в каком-то мелком репо давно падают, просто вы их уже пол года не запускали?
В ней рассказывается, что наши инструменты (git/GitHub) недостаточны для управления огромными проектами вроде ядра Linux. Ещё аналогичное, видимо, можно написать по системам сборки. Кмк, в этом и ключ проблемы монорепо/мульти-репо.
Насколько я понял, у вас валидационная политика "протухает" при каждом коммите в мастер.
В идеале, конечно, так и нужно, но в реальности в крупных репозиториях возникают проблемы с толпой разработчиков, пытающихся протолкнуть свой PR в мастер.
Рабочий trade-off в данном случае -- более умная экспирация политики. TFS, например, из коробки умеет в покоммитное протухание (как у вас было) и в экпирацию по времени. В статье указано, что сейчас экспирация политики составляет 24 часа, что позволяет разработчикам планово закатывать свои изменения в мастер. Минусом является возможность внесения ломающих изменений в мастер, но она довольно тривиально решается автоматическим мониторингом и ревертом ломающих коммитов.
Один продукт - один репозиторий. А вы судя по статье из одной крайности с кучей различных систем контроля версий бросились в другую элементарно сделав один гигантский репозиторий, набросав туда всего до кучи.
В принципе вы облегчили жизнь программисту , который, захотев уйти из компании, сможет скопировать одним приседом все продукты компании (при условии что другие меры безопасности не соблюдены).
А как "один продукт — один репозиторий" в корне отличается от "один продукт — одна папка" в монорепо?
Отсутствием необходимости в bazel и сложных правилах чтобы понять что собирать, тестировать и выкатывать для текущего PR. Меньшим количеством потенциальных конфликтов и очередей между разными PR.
Да, правила, чтобы понять, что собирать, тестировать и т.д. всё равно понадобятся. Просто это будут зависимости между крупными блоками, или репозитариями.
Есть ещё ряд минусов мелких репозитариев, но они не так существены, кмк.
В общем, как обычно, нужно смотреть по месту. Серебряной пули нет.
Ну вот я это обычно решаю собирая в одном репо несколько типовых микросервисов написанных на одном языке. Обычно такие PR меняющие сразу группу разных проектов нужны именно для схожих проектов написанных на одном языке. В результате такого подхода получается более сбалансированная комбинация достоинств и недостатков относительно и одного монорепо на всю компанию и отдельных репо на каждый проект.
Так же как логический раздел диска отличается от папки. Команда работающая над продуктом может использовать свои собственные соглашение по работе с системой контроля версий. Репозитории могут иметь различные настройки, хуки. Политика безопасности в конце концов. Один гигантский репозиторий такой же антипатерн как и God object.
И в результате у каждого из 100500 репозиториев получается своя собственная структура, свои соглашения, различные настройки, хуки, настройки доступа, что приносит свои собственные трудности
В итоге с момента введения этой метрики в октябре 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 - это всё равно что Теслу сравнивать с Запорожцем.
но разработчик не успел закомплитить пулл-реквест за 24 часа, то билд экспайрится
Что уж там, можно так: но если девелопер диднот мэйкнул закомплитить пулл-реквест за 24 аурс, то билд экспайрится. Таймлесс, аффордабл
Проблема: разные движки контроля версий в разных командах, отсутствие унификации CI/CD
Решение: слить все репозитории в один
Сам по себе монорепо - вполне себе рабочий вариант, но мне кажется что в данном случае это больше дань моде, чем непосредственное решение изначальной проблемы. Решением было бы перевести все команды на один движок контроля версий и унифицировать CI/CD
Дико извиняюсь, а как решается проблема единой точки отказа? Монорепо упал, и весь Касперский кукует? Просто интересно
Как монорепозиторий изменил жизнь разработчиков «Лаборатории Касперского»?