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

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

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

Спасибо за вопросы. Bazel мы не рассматривали как инструмент. Сам о таком инструменте не слышал. Но поизучав документацию, понял, что он не подходит для решения наших проблем. Bazel и Lerna по-разному работают с зависимостями. Lerna создает связь между пакетами (на подобии npm link), благодаря чему изменения, внесенные в зависимом пакете, сразу видны при разработке пакета. Эти изменения могут быть как исполняемым кодом (тогда при разработке сразу будут видны все изменения), а могут быть и изменением версии пакета. Благодаря этому, Lerna позволяет проводить процесс синхронизации зависимостей без участия разработчика по всему дереву зависимостей. Bazel же работает по большей части с node_modules папкой и исходниками, что в ней хранятся. При этом ссылочных связей между пакетами не создается. Bazel позволит решить проблему с неявным описанием зависимостей, но, в отличие от Lerna, не позволит решить проблему с синхронизацией, так как она все еще остается на плечах разработчика. Плюс для Bazel нужна более сложная инфраструктура, чтобы он использовал свои преимущества по полной.

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

Мы пришли к коллаборативным PR, когда в один PR коммитит много людей. Но размер нашего репозитория очень большой. Вот мне и интересно стало, использует ли кто-нибудь ещё коллаборативные PR.


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


А с вашим случаем помогите до конца разобраться, потому что не понял в чем описанная проблема.
Сразу скажу, что в Lerna не шарю, но про Bazel могу сказать, что он совершенно точно синхронизирует все зависимости без участия разработчика. Если на пальцах:
1) Вы подсовываете Bazel один package.json или вообще lock-файл, в котором описаны все внешние зависимости монорепы, дальше происходит магия и внешние зависимости становятся доступны системе сборки как если бы они лежали локально в монорепе. После этого вы начинаете жить в герметичном мире, где все внешние пакеты нужных версий зафиксированы и живут рядом с вашими внутренними пакетами.
2) Ваши внутренние пакеты описываются BUILD.bazel файлами. В них указываются зависимости внутреннего пакета от других пакетов, внутренних и импортированных в п.1 внешних. Цель сборки в синтаксисе Bazel выглядит как-то так, немного упрощенно:


js_library(
    name = "my-shiny-component",
    srcs = "*.js",
    deps = [
        "//monorepa/components/another-shiny-component",
        "//monorepa/components/not-so-shiny-one",
        "@npm//sass-loader",
        "@npm//vue",
    ],
)

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

Ответил отдельным комментарием, так как ошибся в способе добавления комментария.
Мы не используем практику коллаборативных пул-реквестов. Для понимания масштаба, наш монорепозиторий сейчас насчитывает 37 npm-пакетов. У нас бывают два типа обновлений зависимостей: обновление зависимости, которая лежит внутри монорепозитория, и внешняя для монорепозитория. В первом случае мы поддерживаем актуальные версии зависимостей внутри монорепозитория, то есть во всех пакетах latest-версии всех внутренних к монорепозиторию зависимостей (это еще нужно, чтобы Lerna работала с пакетами). Поэтому тесты если ломаются, то уже из-за изменений, которые внес разработчик. В таком случае разработчик либо правит код, либо правит тест. Внешние зависимости обновляются чаще всего нашей командой и в случае поломок при обновлении, сами правим тесты и код.

Если я правильно понял, то Bazel — это инструмент для синхронизации и сборки проектов, и работает Bazel в основном как раз с собранными проектом. Сборка проектов в нашем репозитории идет от внутреннего инструмента для бойлерплейтинга (вот здесь можно подробнее о нем узнать ) и этот инструмент учитывает особенности сборки основного монолита. Поэтому нам нужен был инструмент только для синхронизации версий. Lerna работает таким образом, что зависимости внешние могут быть вынесены на корневой уровень монорепозитория, а внутренние зависимости связаны через ссылки. Благодаря такому механизму нам удалось в какой-то момент избавиться от package-lock файлов в наших пакетах, оставив только один lock файл в корне. Плюс, кроме синхронизации, Lerna позволяет автоматизировать работу именно с изменением версий пакетов. Так, к примеру, с помощью двух команд можно узнать какие пакеты были изменены, где и как необходимо изменить версии (поднять патч, минорную или мажорную версию), а затем опубликовать пакеты. И в данном случае синхронизация позволила решить проблему построения явного дерева зависимостей, которое может быть автоматически измененно, а автоматизация упростила работу с монорепозитрием, сведя до работы с небольшим набором команд. Если я правильно понимаю, то в Bazel нет механизма для автоматизации работы именно с версиями пакетов. Кроме того, отмечу что наш монорепозитрой нужен для разработки без сборки, так как пакеты из него еще нужны в основной кодовой базе монолита, в которой настроена и работает своя сборка проекта.

Кажется понял, у вас есть непреодолимая необходимость выкладывать npm-пакеты именно как npm-пакеты, поэтому с базелем будут проблемы — он больше для деплоя жирными монобинарями подходит.
Спасибо!

Как с lerna решаете проблему когда нужно сделать minor бамп единственного пакета, а у остальных бампить patch?

Также, смотрели rushjs? Если да, почему выбрали lerna? Мы думаем сбежать с lerna в rush.
Мы не разделяем сейчас бампы пакетов. То есть если в каком-то пакете необходимо поднять patch версию, то во всех зависимых пакетах будет поднята patch версия. Это связано с тем, что наш самописный скрипт не умеет разделять версии, и в юните приняли решение, что сейчас нет необходимости в этом.

Rush выглядит интересным решением. Когда только обсуждали решение о внедрении Lerna, Rush не рассматривали. Сейчас выглядит так, что то, что решает наш скрипт для поднятия версий, уже решено в Rush. Сам не пользовался этим инструментом, но он выглядит интересным
Зарегистрируйтесь на Хабре, чтобы оставить комментарий