Семантичне версіонування
Семантичне версіонування
1) Що таке SemVer і навіщо він потрібен
SemVer задає передбачувані правила присвоєння версій артефактам (бібліотекам, API, сервісам, схемам), щоб споживачі розуміли, чого очікувати від оновлення:- MAJOR - несумісні зміни (breaking changes).
- MINOR - нова функціональність, сумісна з API.
- PATCH - оборотно-сумісні виправлення дефектів.
Мета: домовитися про стабільність контрактів і знизити вартість оновлень.
2) Формат версії
Базовий формат:- `MAJOR. MINOR. PATCH[-PRERELEASE][+BUILD]`
`1. 4. 7'- стабільний реліз.
`1. 5. 0-rc. 2'- пре-реліз (release candidate № 2).
`2. 0. 0+linux. arm64'- build-метадані (не впливають на порівняння версій).
1. Спочатку порівнюються «MAJOR», потім «MINOR», потім «PATCH».
2. Пре-релізи менше відповідної стабільної версії: `1. 2. 0-rc. 1 < 1. 2. 0`.
3. Build-метадані («+...») на порядок не впливають: `1. 2. 0+001 == 1. 2. 0`.
3) Що вважається breaking change
Breaking change - будь-яка зміна, що вимагає дій споживача:- Видалення/перейменування/зміна сигнатури публічних методів/ендпоінтів.
- Зміна формату входу/виходу (JSON-схема, типи).
- Зміна контрактів помилок (коди/структури).
- Зміна side-effects/SLAs (наприклад, суворі ліміти або нові обов'язкові поля).
Не breaking (при коректній реалізації): додавання необов'язкових полів, розширення enum новими значеннями (якщо клієнт їх ігнорує), нові ендпоінти, нові прапори з дефолтами, що не впливають на поточні виклики.
4) Пре-релізи і канальні стратегії
Пре-релізи дозволяють тестувати без порушення SemVer-обіцянок:- Мітки: `alpha`, `beta`, `rc`. Приклад: `2. 3. 0-beta. 3`.
- Канали: nightly → alpha → beta → rc → stable.
- Політика: пре-релізи не повинні потрапляти як транзитивні залежності для прод-збірок за замовчуванням.
5) Діапазони версій і точність залежностей
У реальних екосистемах використовуються вирази діапазонів:5. 1 Node/npm (SemVer за замовчуванням)
`^1. 4. 2` ≈ `>=1. 4. 2 <2. 0. 0'( дозволяє MINOR/PATCH, фіксує MAJOR).
`~1. 4. 2` ≈ `>=1. 4. 2 <1. 5. 0'( дозволяє PATCH в межах MINOR).
`1. 4. x'- будь-яка заплатка в 1. 4.
Точний пін: `1. 4. 2`.
5. 2 Python (PEP 440, pip)
`~=1. 4. 2` ≈ `>=1. 4. 2,==1. 4.`.
`>=1. 4,<2. 0'- явні межі.
5. 3 Maven/Gradle (Java)
`[1. 4,2. 0)'- включно/виключно.
Рекомендується суворе пінування для прод-критичних артефактів.
5. 4 Go modules
Завжди повні теги'vMAJOR. MINOR. PATCH';'v2 +'вимагає суфікс модуля '/v2'.
Рекомендація: для додатків - точні піни (reproducible builds). Для бібліотек - caret-діапазони (полегшити оновлення без ломок).
6) CHANGELOG и Conventional Commits
Структурований журнал змін підвищує прозорість.
Conventional Commits:
feat(payments): add PIX refund endpoint fix(api): correct 400 → 422 on invalid payload perf(cache): reduce p99 by 20%
refactor(core): extract rule engine docs: update API usage examples chore(deps): bump lodash to 4. 17. 21 feat!: remove legacy webhook v1 (BREAKING CHANGE:...)
Типи: `feat`, `fix`, `perf`, `docs`, `refactor`, `chore` и т. д.
Знак оклику або блок'BREAKING CHANGE'оголошує підвищення MAJOR.
CHANGELOG генерується з історії комітів (release-notes ботами).
7) Політика версіонування для API
Публічні API: строге SemVer; breaking → MAJOR.
HTTP/REST: версіонування за URL/заголовком: '/v1/...', '/v2/...'або'Accept: application/vnd. org. service. v2+json`.
JSON-схеми: мінорні розширення - нові необов'язкові поля; major - видалення/зміна обов'язкових.
gRPC/Protobuf: додавайте нові поля з новими номерами; не перевикориставайте номери полів; видалення → deprecate, а не «ламати» існуючі.
8) Схеми даних та міграції
Міграції БД синхронізуються з версіями програми: `app@1. 8. 0'вимагає'schema @ 1. 8. x`.
Для breaking змін схеми - фази: expand (додати), migrate, contract (видалити). Версію підвищуйте до MAJOR тільки коли видаляєте старий контракт.
Підтримуйте подвійний запис/читання на час міграції.
9) Монорепо і мікросервіси
Multi-package: кожному пакету свій'MAJOR. MINOR. PATCH`; загальний кореневий цикл релізів тільки для мета-артефактів.
Варіюйте стратегії:- Independent versions (Lerna/Changesets) - підсилює ізоляцію.
- Lock-step - простіше комунікація, але більше помилкових MAJOR-ів.
- Для мікросервісів фіксуйте контракти (OpenAPI/Protobuf) з окремою версією: `contract@2. 1. 0', сервіс слід їй.
10) Автоматизація релізів в CI/CD
Автообчислення версії на основі Conventional Commits:- `fix` → `PATCH`, `feat` → `MINOR`, `!`/`BREAKING` → `MAJOR`.
yaml
Pseudo-workflow steps:
- run: npx semantic-release
- run: git tag v$NEW_VERSION && git push --tags
- run: cosign sign ghcr. io/org/app:v$NEW_VERSION
Генерація CHANGELOG, публікація реліз-ноутів, оновлення залежностей в GitOps-репо, перевірка, що'main'завжди вказує на останній стабільний тег.
11) Політика депривацій (deprecation policy)
Оголошення: позначайте функціонал як deprecated в MINOR-релізі, давайте термін EOL (наприклад, 90 днів).
Спостережуваність: логуйте використання застарілих ендпоінтів з user/tenant-контекстом.
Видалення: у наступному MAJOR. Документуйте шлях міграції.
12) Приклади та шаблони
12. 1 Регулярний вираз валідації SemVer
regex
^(0 [1-9]\d)\.(0 [1-9]\d)\.(0 [1-9]\d)(?--([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)))? (?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)))?$
12. 2 Приклади порівнянь
`1. 2. 3` < `1. 10. 0'( порівняння за MINOR).
`2. 0. 0-rc. 1` < `2. 0. 0`.
`1. 2. 3+build. 5` == `1. 2. 3`.
12. 3 Політика залежностей (приклад YAML)
yaml policy:
libraries:
default_range: "^MAJOR. MINOR. PATCH"
pin_security_critical: true services:
pin_exact: true allow_prerelease_in_nonprod: true api_contract:
require_same_minor: true forbid_major_mismatch: true
13) Анти-патерни
Використання «latest »/плаваючих тегів в проде.
Підвищення MAJOR без реальних ломок («маркетингові версії»).
Приховані breaking-зміни під виглядом'PATCH'.
Пре-релізи в транзитивних залежностях прод-додатків.
Змінювати артефакт без нового тегу (мутабельні версії).
Неузгоджені версії коду і схеми БД.
14) Чек-лист впровадження (0-45 днів)
0-10 днів
Прийміть SemVer як обов'язковий стандарт, затвердіть критерії ломок.
Увімкніть Conventional Commits і шаблон PR з полем'BREAKING CHANGE'.
11-25 днів
Підключіть semantic-release/changesets, автогенерацію CHANGELOG.
Налаштуйте підпис і публікацію артефактів за тегом'vX. Y.Z`.
26-45 днів
Введіть deprecation policy і телеметрію використання застарілих API.
Синхронізуйте версії контрактів (OpenAPI/Proto) і сервісів.
Забороните'latest'і мутабельні теги на рівні політики (ОРА/регламенти CI).
15) Метрики зрілості
% артефактів, що видаються тільки за тегом SemVer.
Середній час міграції між MINOR-версіями.
Кількість інцидентів через приховані breaking-змін.
Покриття Conventional Commits в репозиторіях (> 95%).
Частка залежностей без плаваючих діапазонів в проді (> 90%).
16) Коли SemVer не потрібен
Внутрішні швидкі прототипи без зовнішніх споживачів (підійде датоване версіонування).
Дані/моделі з експериментальними фічами (краще Model/Schema Versioning з сумісністю на рівні конвертерів).
Контент-пакети без стабільного публічного API.
17) Висновок
SemVer - це контракт довіри між виробником і споживачем. Чітко визначайте, що ламає сумісність, автоматизуйте розпізнавання типів релізів і публікацію артефактів, ведіть прозорий CHANGELOG і дотримуйтесь політики депривацій. Тоді оновлення стануть рутинними, прогнозованими і безпечними - а інфраструктура і API будуть розвиватися без шоків для бізнесу.