Несмотря на то, что монорепозитории позволяют делать атомарные изменения кода, многие команды всё ещё тратят часы вручную на обновление версий каждого компонента. Это особенно заметно в проектах, где код написан на разных языках: JavaScript, Python, Rust и т.д. В таких условиях традиционные инструменты версионирования, заточенные под одну экосистему, становятся узким местом.
Эволюция подходов к версионированию в монорепо началась с простых тегов Git, затем появились лерна и стандарт-версион, которые автоматизировали процесс для JavaScript-пакетов. Однако их зависимость от npm‑механизмов делает их непригодными для чисто нативных проектов. Появившись как инструмент для управления changeset‑файлами, changesets предложил более гибкую модель: каждый разработчик фиксирует небольшой файл, описывающий, какие пакеты должны получить повышение версии и какие записи попадут в changelog. Эта модель не привязана к конкретному менеджеру пакетов, что открывает путь к использованию в полиглотных репозиториях.
Техническая архитектура
В корне репозитория создаётся директория .changeset с файлом config.json, где указываются базовая ветка, стратегия обновления внутренних зависимостей и доступ к приватным пакетам.
Для каждого языка добавляется «прокси»‑файл package.json, содержащий только имя и версию. Changesets работает с этими файлами, обновляя версии при выполнении «npx @changesets/cli version«.
После этого требуется синхронно перенести полученные номера в нативные манифесты: Cargo.toml для Rust, pyproject.toml для Python и т.д.
Эта задача решается небольшим скриптом (например, на Python с использованием uv), который читает обновлённые package.json, парсит соответствующие TOML‑файлы и заменяет строку версии.
После обновления манифестов скрипт может запускать команды обновления lock‑файлов (cargo lock, poetry lock и т.п.), обеспечивая согласованность зависимостей по всему репозиторию.
Сравнение с альтернативами
| Критерий | changesets | Lerna | Standard Version |
|---|---|---|---|
| Поддержка мультиязыковых пакетов | Да, через прокси‑файлы и скрипты | Нет, ориентирован на npm/pnpm | Нет, работает только с npm‑пакетами |
| Необходимость дополнительных файлов | Прокси package.json для каждого пакета | Нет, использует существующие package.json | Нет, использует package.json |
| Автоматическое формирование changelog | Да, через выбранный адаптер (changelog‑git) | Да, основан на коммитах | Да, основан на конвенциональных коммитах |
| Гибкость скриптов версии и публикации | Высокая, через кастомные команды в GitHub Action | Средняя, ограничена скриптами lerna | Низкая, фиксированный процесс |
| Сложность настройки | Средняя, требует initial скрипта синхронизации | Низкая для чистых JS‑проектов | Низкая для JS‑проектов |
Практические советы — начните с небольшого набора пакетов, добавьте changeset‑файлы вручную, убедитесь, что скрипт синхронизации корректно обновляет все манифесты. Настройте CI‑ workflow, который запускает changesets/action только при пуш в основную ветку, чтобы избежать лишних триггеров при множестве тегов. При работе с приватным репозиторием установите доступ «restricted» в конфиге, чтобы ограничить публикацию только доверенными ветками.
Подведём итог
Changesets предоставляет нейтральную основу для версионирования, которую можно адаптировать под любой язык за счёт простых скриптов синхронизации. По мере роста сообщества появляются обсуждения о нативной поддержке полиглотных монорепо, что может избавить от необходимости прокси‑файлов.
Пока же сочетание changesets, гибкого GitHub Action и небольшого утилитного скрипта остаётся практичным решением для средних команд, стремящихся к автоматическому и надёжному релизу кода на разных языках.