Семантичне версіонування
Semantic Versioning (SemVer) - договір про те, як номер версії відображає характер змін. Формат: MAJOR. MINOR. PATCH[-PRERELEASE][+BUILD].
Сенс:- MAJOR - несумісні зміни (breaking).
- MINOR - зворотно-сумісні фічі/розширення.
- PATCH - зворотно-сумісні виправлення помилок/безпеки.
Мета: передбачувана еволюція API, подій, схем даних, SDK і конфігів без раптових поломок споживачів.
1) Конвенція номерів
X.Y.Z[-alpha.1 -rc.1][+build.sha]
Pre-release ('-alpha','-beta','-rc') - нестабільні збірки; не обіцяють сумісності.
Build metadata ('+ sha') - не впливає на порядок порівняння, корисно для трасування.
До 1. 0. 0 будь-яка зміна може вважатися breaking (але краще дотримуватися правил з самого старту).
2) Що вважати breaking/minor/patch
PATCH (Z):- Фікси багів і безпеки без зміни контракту.
- Док-апдейти, що не зачіпають контракт.
- Оптимізації без зміни відповідей/подій/схем.
- Додавання нових необов'язкових полів/методів/ендпоінтів.
- Розширення enum значеннями, якщо споживачі терпимі до незнайомих значень.
- Нові індекси БД, колонки nullable з дефолтом, нові події додатково до старих.
- Видалення/перейменування полів, зміна типів, обов'язковості.
- Зміна семантики/статусів/кодів помилок.
- Зміна формату серіалізації, схеми ключів, протоколу транспорту.
- Стиснення/злиття топіків, перенесення сенсу події, зміна схеми партиціонування.
- Міграції БД, що вимагають «двофазного» перемикання без зворотної сумісності.
3) Версіонування за артефактами
3. 1 REST
Варіанти: 'URI/v1/...', заголовки ('Accept: application/vnd. acme. game+json; version = 1'), параметр.
Рекомендація: версія в URI для публічних API; для внутрішніх - через заголовок c negotiation.
MINOR: додавання необов'язкових полів, нових фільтрів/ресурсів; не змінюйте існуючі відповіді.
PATCH: фікси, уточнення описів, стабільні сортування.
3. 2 gRPC
Зміна сигнатур/типів → MAJOR (новий пакет/служба: `acme. wallet. v2`).
Нові поля - з міткою optional; сервер повинен ігнорувати невідомі.
Поля не видаляємо: «деприкейт + зарезервувати номер», видалити - тільки в наступному MAJOR.
3. 3 GraphQL
MINOR: нові поля/типи/query; видалення - через «@deprecated» + вікно міграції, повноцінне видалення - MAJOR.
Зміна nullable→non -nullable - MAJOR.
3. 4 Події та топіки (Kafka/SQS)
Схеми в Schema Registry: еволюція additive (додавати поля з дефолтами).
Нова несумісна версія → новий subject/topic ('bet. settled. v2`).
Ключ партіонування незмінний всередині MAJOR.
3. 5 Схеми БД
«Розширюй, потім згортай»:1. Додати колонку (nullable/c дефолтом) →
2. Заповнити бекфіл →
3. Перекласти читання →
4. Прибрати старе (тільки в MAJOR).
Зміна типу/РК/унікальностей - MAJOR, під фічефлагом і подвійним записом.
3. 6 SDK/CLI
Публічні методи/сигнатури - ті ж правила.
Для автогенерації (OpenAPI/Proto) - версія пакетного імені та артефактів.
4) Політика деприкацій і життєвий цикл
Кожному breaking-зміні передує деприкація (зазвичай 90-180 днів для зовнішніх, 30-60 - для внутрішніх).
Комунікації: changelog, e-mail/вебхукі партнерам, банери в порталі розробника.
Режим dual-run: паралельно тримаємо «v1» і «v2», моніторимо частку трафіку «v1».
Sunset headers (REST): `Sunset: 2026-03-31`, `Link: <url>; rel="deprecation"`.
5) Version negotiation
Клієнт відправляє бажану версію + максимальну підтримувану (наприклад,'Accept-Version: 1,2`).
Сервер відповідає'Content-Version: 2', якщо зміг підвищити.
У двонаправлених протоколах (WebSocket, gRPC) - обмін Hello-фреймами з'supported _ versions'.
6) Інтеграція з адаптерами провайдерів (ACL)
Зовнішній провайдер змінює схему - всередині адаптера тримаємо меппери v1/v2 і випускаємо MINOR для внутрішньої події, зберігаючи наш доменний контракт.
Якщо зовнішні зміни пробиваються всередину - це MAJOR нашої доменної події і новий subject.
7) Changelog і мітки комітів
Слідуємо Keep a Changelog і Conventional Commits:- `feat:...` → MINOR
- `fix:... '/' chore','docs','perf'( без контракту) → PATCH
- `feat!:` / `fix!:` / `refactor!:'або'BREAKING CHANGE:'в тілі → MAJOR
[2.3.0] - 2025-10-31
Added
- GET /v1/games?capabilities=jackpot (optional)
Changed
- GraphQL: field Game.volatility @deprecated, use Game.riskProfile
8) Автоматизація релізів
CI: валідатори схем (OpenAPI/Protobuf/Avro/JSON-Schema), детект breaking-дифів.
SemVer-бот: аналіз Conventional Commits → обчислює bump (major/minor/patch), проставляє тег, генерит changelog.
CD: роздільні deploy і release (фічефлаги/конфіги активують нову версію).
Контроль: не публікуємо'latest'на PRO до успішних canary і узгоджених SLO.
9) Семантика для конфігурацій і політик
Конфіги (YAML/JSON) теж мають версію схеми: `schema_version: 3`.
MINOR - нові необов'язкові поля/правила; MAJOR - зміна структури/обов'язковості.
Підтримка v2/v3 у валідаторі; мігратор конфігів зі звітом несумісностей.
10) Тестування сумісності
Consumer-driven contract tests (Pact): на кожну інтеграцію.
Schema-evolution tests: прогін старих payload'ів на новій схемі і навпаки.
Replay: відтворення прод-трафіку «v1» на «v2» в тіні.
Property-based: стійкість до незнайомих полів/enum.
11) Спостережуваність за версіями
Тегуйте метрики/логи: `api_version`, `schema_version`, `event_version`.
Дашборди міграції: частка трафіку за версіями, помилка/латентність по'v1/v2'.
Алерти: якщо'v1'не знижується за планом; зростання 4xx/5xx після випуску'v2'.
12) Міграційні патерни без простоїв
Expand → Migrate → Contract (БД).
Dual write + порівняння дивергенцій перед перемиканням читання.
Shadow compare для ранжування/правил.
Canary по тенантах/регіонах; feature flags для швидких відкатів.
Read-compat/Write-compat вікна: нова версія читає старі дані, але пише в новому форматі.
13) Анти-патерни
«Версія в кожному полі» замість версіонування ресурсу/події.
Приховані breaking-зміни під MINOR (наприклад, зміна дефолтів).
Видалення деприкейтнутого без вікна і метрик споживання.
«Назавжди v1»: відсутність плану зняття старих версій → техдолг і вразливості.
Змішування бізнес-версії і версії контейнерного образу.
14) Чек-лист політики версіонування
Зафіксовано формат версій і джерела істини (Registry/Portal).
- Затверджено список breaking-критеріїв за артефактами (REST/gRPC/GraphQL/events/DB).
- Процес деприкацій: терміни, комунікації, sunset/банери, dual-run.
- Автоматичний diff-чекер схем і Conventional Commits.
- Дашборди споживання версій і алерти.
- Плейбуки міграції (expand/migrate/contract, dual-write, shadow).
- Конфіги і SDK мають власні версії і регістр.
- Документація «як вибрати версію» для клієнтів і «як підвищувати» для команд.
15) Приклади версіонування (iGaming-кейси)
Подія'BetSettled v1'→'v2': додали'void _ reason'( optional) і'tax. amount` (optional) — MINOR. Переназвали'payout'→'win_amount'- MAJOR, новий subject.
REST `/wallets/transfer`: додали фільтр'? tenant _ id ='- MINOR. Змінили код помилки «409'→'422» - MAJOR.
GraphQL: позначили'Player. age'як'@deprecated'на користь'Player. ageGroup'- випуск в MINOR, видалення в MAJOR після періоду X.
БД: додали колонку'bonus _ wager _ left'nullable - MINOR. Зробили non-null і видалили'bonus _ left'- MAJOR (через expand/contract).
Висновок
Семантичне версіонування - це не про цифри, а про довіру і передбачуваність. Чіткі правила, автоматичні перевірки, контрольовані деприкації і прозора телеметрія дозволяють еволюціонувати API, події і схеми без болю для інтеграцій - і випускати зміни часто, безпечно і осмислено.