Короткий ответ
Нужен единый источник истины для контракта (OpenAPI/Protobuf-схема), версионируемый в репозитории и проверяемый автоматически (линтинг на breaking changes, contract-тесты типа consumer-driven contracts), который команда-провайдер не может изменить несовместимым образом без согласования с командами-потребителями; конкретный уровень строгости процесса зависит от числа потребителей и частоты релизов.
Как это работает подробнее
schema-first подход означает, что изменения в API сначала описываются в схеме (и проходят ревью/автоматическую проверку на совместимость), и только после этого реализуются в коде — это даёт явную точку контроля перед тем, как несовместимое изменение попадёт в production. Contract-тесты (например, по модели consumer-driven contracts) позволяют потребителю зафиксировать ожидания от API провайдера в виде тестов, которые провайдер прогоняет в своём CI перед релизом, узнавая о поломке контракта до деплоя, а не после.
Пример кода
# Фрагмент OpenAPI-схемы, версионируемой в репозитории и проверяемой в CI на breaking changes
paths:
/orders/{orderId}:
get:
operationId: getOrder
responses:
"200":
content:
application/json:
schema:
type: object
required: [id, status, total]
properties:
id: { type: integer }
status: { type: string }
total: { type: number }Что использовать на практике
- Рекомендация. автоматическая проверка схемы на breaking changes (например, сравнение текущей и предыдущей версии OpenAPI-спеки в CI) эффективна для явных нарушений (удалённое поле, изменённый тип), но не ловит все семантические несовместимости (например, изменение бизнес-смысла поля при сохранении типа) — для этого нужны дополнительные contract-тесты с реальными сценариями использования. Процесс нужно соразмерять с реальным масштабом: для двух команд с редкими релизами формальный consumer-driven contract framework может быть избыточен, для десятков команд с частыми независимыми деплоями — обязателен. Компромисс: строгий процесс (consumer-driven contract-тесты для каждого потребителя, обязательный gate в CI провайдера) даёт сильную защиту от поломок между релизами, но требует инфраструктурных инвестиций (поддержка framework для контрактных тестов, договорённости о том, кто их пишет и поддерживает) и может замедлять релизы провайдера, если потребители медленно обновляют свои контрактные тесты; более лёгкий процесс (только линтинг схемы на явные breaking changes без полноценных contract-тестов) быстрее внедряется и не замедляет релизы так сильно, но не ловит все классы несовместимостей, особенно семантические. Критерий выбора — число и критичность потребителей, частота изменений контракта и готовность команд инвестировать в тестовую инфраструктуру.
Подводные камни
- Риски. вести схему API "неофициально" в виде устной договорённости или устаревающей вики-страницы вместо версионируемого артефакта, который реально проверяется в CI; разрешать провайдеру мержить изменения в контракт без явного шага оповещения/проверки совместимости для известных потребителей, полагаясь только на "ревью кода" без автоматизации.