Семантическое версионирование
Семантическое версионирование (SemVer, от англ. Semantic Versioning) — это формальная система правил присвоения и увеличения номеров версий программного обеспечения, предназначенная для передачи смысла изменений между разработчиками и пользователями. Основная цель семантического версионирования — устранение неоднозначности при обновлении зависимостей, позволяя автоматически определять совместимость версий на основе их номера. Спецификация была предложена Томом Престон-Вернером в 2013 году и получила широкое распространение в экосистемах пакетных менеджеров (npm, Cargo, Packagist, NuGet и других).
История
Проблема управления версиями существовала задолго до появления SemVer. В ранних проектах номера версий часто присваивались произвольно, что приводило к конфликтам зависимостей и «аду зависимостей» (dependency hell). В 2013 году Том Престон-Вернер, работая над проектом npm, опубликовал черновик спецификации SemVer 2.0.0, который быстро стал де-факто стандартом в сообществе JavaScript и затем распространился на другие языки и платформы. В 2014 году спецификация была доработана до версии 2.0.0-rc1, а окончательная версия 2.0.0 вышла в 2015 году. С тех пор SemVer поддерживается сообществом через репозиторий на GitHub.
Основные правила
Спецификация SemVer 2.0.0 определяет формат номера версии как MAJOR.MINOR.PATCH (основная.дополнительная.исправление), где каждый компонент увеличивается в строго определённых случаях:
- MAJOR (основная версия) — увеличивается при внесении несовместимых изменений в API. Пример: переход с 1.x.x на 2.0.0 означает, что код, написанный для версии 1.x, может перестать работать.
- MINOR (дополнительная версия) — увеличивается при добавлении новой функциональности, которая сохраняет обратную совместимость с предыдущими версиями. Также может включать пометку о том, что API устарел (deprecated).
- PATCH (исправление) — увеличивается при внесении исправлений ошибок (bug fixes), которые не нарушают обратную совместимость.
Пре-релизные и метаданные
Кроме трёх основных чисел, версия может содержать суффиксы:
- Пре-релизная метка (pre-release) — добавляется через дефис после PATCH (например,
1.0.0-alpha.1,2.0.0-rc.2). Такие версии имеют меньший приоритет, чем обычные, и не считаются стабильными. - Метаданные сборки (build metadata) — добавляются через плюс (например,
1.0.0+build.123). Они игнорируются при сравнении версий и служат только для идентификации конкретной сборки.
Диапазоны и операторы
В экосистемах пакетных менеджеров принято задавать диапазоны допустимых версий зависимостей с помощью операторов:
- Каретка (^) — разрешает обновления, не изменяющие первую ненулевую цифру слева. Например,
^1.2.3допускает версии от1.2.3до2.0.0(не включая).^0.2.3допускает от0.2.3до0.3.0. - Тильда (~) — разрешает обновления только в пределах указанного уровня. Например,
~1.2.3допускает от1.2.3до1.3.0. - Точные версии —
1.2.3— только эта версия. - Диапазоны —
>=1.2.3 <2.0.0.
Применение
Пакетные менеджеры
SemVer является основой для работы большинства современных пакетных менеджеров:
- npm (Node.js) — использует SemVer для всех публикуемых пакетов.
- Cargo (Rust) — требует SemVer для версий пакетов в реестре crates.io.
- Packagist (PHP) — использует SemVer для пакетов Composer.
- NuGet (.NET) — поддерживает SemVer 2.0.0 начиная с NuGet 4.3.0.
- PyPI (Python) — использует собственную схему, но многие проекты следуют SemVer.
Автоматизация и CI/CD
SemVer позволяет автоматизировать процесс публикации новых версий. Например, инструменты вроде semantic-release анализируют коммиты (по соглашению Conventional Commits) и автоматически увеличивают MAJOR, MINOR или PATCH в зависимости от типа изменений. Это снижает риск человеческой ошибки и ускоряет релизный цикл.
Критика и альтернативы
Несмотря на широкое распространение, SemVer имеет ряд недостатков:
- Сложность соблюдения — точное определение, является ли изменение обратно совместимым, требует глубокого понимания API. На практике разработчики часто ошибаются, нарушая обещания SemVer.
- Раздувание MAJOR-версий — частые несовместимые изменения приводят к быстрому росту основной версии (например, 10.0.0, 11.0.0), что может вводить в заблуждение.
- Неприменимость к некоторым проектам — для библиотек с нестабильным API (например, на ранних стадиях разработки) SemVer неэффективен. В таких случаях рекомендуется использовать версию 0.x.x, где любые изменения считаются несовместимыми.
Альтернативные схемы
- CalVer (Calendar Versioning) — версия привязывается к дате выпуска (например,
2024.03.15). Используется в Ubuntu, Python, Blender. - ZeroVer — версия всегда начинается с 0 (например,
0.1.0,0.2.0), что означает, что проект не гарантирует стабильности API. Применяется в экспериментальных проектах. - RomVer (Romantic Versioning) — неформальная схема, где версия выбирается произвольно, без строгих правил.
Интересные факты
- Спецификация SemVer 2.0.0 занимает всего около 10 страниц текста и доступна на официальном сайте semver.org.
- В 2016 году проект npm столкнулся с проблемой «левого сдвига» (left-pad), когда удаление небольшого пакета сломало тысячи проектов. Это привело к усилению требований к стабильности версий.
- Некоторые крупные проекты, такие как Kubernetes и Docker, используют SemVer, но с собственными расширениями (например, Kubernetes добавляет суффикс
-beta).
Источники
- Preston-Werner, T. (2013). Semantic Versioning 2.0.0. semver.org.
- npm Documentation. (2023). About semantic versioning.
- Cargo Documentation. (2024). Specifying dependencies.
- NuGet Documentation. (2023). Semantic Versioning 2.0.0.
- Спецификация Conventional Commits 1.0.0. (2020).
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →