Skip to content

Polyrepo ​

Интерактивный CLI для управления папкой локальных npm-пакетов: бамп версии через pull request, публикация в npm, релизы и отслеживание рассинхронизации зависимостей между пакетами — всё из одного инструмента, и всё можно предварительно проверить через --dry-run, прежде чем что-то реально изменится. Работает с GitHub и GitLab (в том числе self-hosted) — хостинг определяется автоматически для каждого репозитория, папка может свободно смешивать оба. Репозиторий, который сам является pnpm-воркспейсом, определяется автоматически и разворачивается в одну запись на каждого публикуемого участника — версионируется, тегируется и релизится каждый независимо.

Возможности ​

  • setup — добавление, редактирование и удаление директорий с пакетами, которые сканирует CLI, прямо из терминала. Здесь же регистрируется хост self-hosted GitLab (gitlab.com работает без какой-либо настройки).
  • clone — сверяет список репозиториев GitHub-организации (либо, с --provider gitlab, GitLab-группы) с тем, что уже склонировано локально, и клонирует недостающее.
  • list — одна таблица по всем пакетам: локальная версия, ветка, git-статус, версия на основной ветке origin (независимо от того, что сейчас реально выгружено локально), git-тег, статус релиза, версия в npm-реестре и рассинхронизация зависимостей между локальными пакетами. --quick пропускает сетевые проверки ради мгновенного вывода версии/ветки/git-статуса; --output сохраняет ту же таблицу в Markdown, JSON, CSV, HTML или простым текстом.
  • outdated — одна таблица устаревших зависимостей по всем пакетам сразу, сгруппированная по пакетам, с раскраской колонки Latest по тому, насколько версия отстала (major/minor/patch).
  • audit — одна таблица уязвимостей npm по всем пакетам сразу, сгруппированная по пакетам, с раскраской по критичности (critical/high/moderate/low) и отметкой, есть ли готовый фикс.
  • prs — одна таблица всех открытых pull/merge request'ов по всем пакетам.
  • doctor — проверка состояния из семи разделов с несколькими безопасными автофиксами по пути: окружение (Node/git/npm, плюс gh/glab — смотря что реально используют ваши репозитории), дрейф основной ветки от реального состояния на хостинге, устаревшие remote-tracking ссылки, расхождение с origin, состояние detached HEAD, отсутствие защиты ветки и мёртвые ветки после прошлых релизов — проверяются и локально, и на origin, --clean-branches/--clean-remote-branches превращают каждую из них в свою интерактивную чистку.
  • switch-default — подтягивает выбранные репозитории до актуальной основной ветки — какой бы она ни называлась, master, main или как-то иначе (определяется отдельно для каждого репозитория, а не предполагается заранее). --force/--clean — для полного сброса репозитория, когда он действительно нужен.
  • bump — поднимает версию пакета (по умолчанию patch; либо --minor/--major; либо --prerelease/--preid для старта или продвижения пререлиза; либо --custom-version для точной версии) через ветку → PR/MR → merge, затем ставит тег релиза. Безопасно перезапускать, если предыдущая попытка прервалась на середине — процесс продолжается с того места, где остановился. Сам пишет черновик записи в CHANGELOG.md, если у пакета такой файл уже есть. Тег ставится как v<version>, либо <name>@<version> для участника pnpm-воркспейса — так два пакета в одном репозитории, забамленных до одного номера версии, никогда не столкнутся; tag/release следуют той же конвенции. --publish сразу после тега публикует пакет и в npm (без флага в конце просто спросит) — подробнее в publish ниже.
  • publish — запускает npm publish (либо pnpm publish для участника pnpm-воркспейса — так зависимость workspace:* на соседний пакет резолвится корректно) только для тех пакетов, что реально обогнали реестр, предварительно проверяя (и при необходимости обновляя) логин в npm. Приватный пакет никогда не предлагается. Пререлизная версия (например, 2.0.0-beta.0) автоматически публикуется под dist-тегом next вместо принятого в npm по умолчанию latest — --dist-tag переопределяет это для любой версии. Предупреждает (не блокируя), если у выбранного пакета локальная версия отличается от origin, репозиторий не на основной ветке или в нём есть незакоммиченные изменения.
  • tag — ставит тег на текущую версию пакета без повторного бампа, если версия уже была поднята каким-то другим способом. Сначала подтягивает основную ветку до актуального состояния, затем заново читает версию — так тег всегда называет то, что реально тегируется — и предупреждает, если из-за этого имя тега изменилось. Сразу после предлагает создать релиз.
  • release — создаёт релиз из тега, с текстом релиза из соответствующего раздела CHANGELOG.md, если он есть.
  • sync-deps — обратная сторона колонки «Deps» в list/doctor: обновляет диапазон версии на другой локальный пакет в package.json до его текущей версии (сохраняя стиль диапазона — ^, ~ или точную версию) для тех пакетов, что вы выберете. Только правит файлы на диске — без коммита и push.
  • exec — прогоняет любую команду по каждому выбранному пакету, один за другим, с реальным терминалом.
  • commit — коммит того, что npm audit fix, npm update или sync-deps оставили в рабочем дереве, без столкновения с правилами веток: на feature-ветке коммит ложится туда; на основной ветке команда читает правила хостинга и либо коммитит и отправляет, либо создаёт ветку, отправляет её и открывает pull/merge request. Прямой push, который хостинг всё же отклонил, переносится в ветку автоматически.
  • ui — локальный веб-интерфейс для всего перечисленного: одна таблица всех пакетов с выделенными проблемами и монорепозиториями в виде блоков, форма для каждой команды со сводкой (и пробным запуском) перед любым изменением, мастер релиза, запуски в живую с отчётом и логом с поиском, подсказки, что делать после любого исхода (в том числе пошаговое исправление npm audit), история и страница настроек конфига.
  • Любая команда, затрагивающая несколько репозиториев, поддерживает --packages и --yes для полностью неинтерактивного использования в скриптах.

Как это работает ​

Каждая команда читает один и тот же список репозиториев из одного конфиг-файла (roots — папки, каждая подпапка которых является отдельным пакетом; packages — отдельные папки репозиториев; gitlabHosts — хосты self-hosted GitLab). Список настраивается один раз через setup, после чего всё остальное работает с ним же. Хостинг каждого репозитория (GitHub или GitLab) определяется по его origin-удалённому репозиторию, а не задаётся отдельно.

Репозиторий и npm-пакет — не всегда одно и то же: репозиторий-pnpm-воркспейс содержит сразу несколько пакетов. Команды, работающие с отдельными пакетами (list, outdated, audit, bump, publish, tag, release, sync-deps, exec), автоматически разворачивают воркспейс-репозиторий в одну запись на каждого участника; команды, работающие с самим репозиторием (switch-default, clone, prs и большая часть doctor), по-прежнему выполняются один раз на физический репозиторий. Правила определения — в разделе Конфиг и поиск репозиториев.

Read-only проверки (git-статус, теги, релизы, состояние реестра, статус PR) выполняются по всем репозиториям параллельно, поэтому полный list или doctor по многим пакетам работает быстро, а не ждёт каждый репозиторий по очереди. А вот всё, что реально меняет состояние — коммит, push, merge, тег — выполняется по одному репозиторию за раз, с выводом каждого шага по мере его выполнения. bump отдельно отслеживает, как далеко зашла предыдущая попытка (запушена ли ветка? открыт ли PR? смёрджен ли он?), так что повторный запуск после прерывания продолжается с нужного места вместо падения на «ветка уже существует» или создания дублирующего PR.