# Координация версий моделей

Координация версий моделей по всей вашей mesh — это критически важная часть процесса версионирования моделей. Это руководство проведёт вас через безопасные best practices по координации производителей и потребителей при внедрении версий моделей.

[Версии моделей](https://docs.getdbt.tech/docs/mesh/govern/model-versions.md) — важная часть рабочего процесса dbt Mesh. Они позволяют эффективнее управлять моделями данных и крайне важны, когда несколько команд совместно используют модели в разных проектах.

Безопасный выпуск новой версии модели требует координации между производителями моделей (теми, кто их создаёт) и потребителями моделей (теми, кто от них зависит).

В этом руководстве рассматриваются следующие темы:

* [Как производители безопасно вводят новые версии моделей](#best-practices-for-producers)
* [Как потребители оценивают и мигрируют на новые версии](#best-practices-for-consumers)

Подробнее о том, как версионирование работает на техническом уровне (структура YAML, контракты, алиасы), см. [версии моделей](https://docs.getdbt.tech/docs/mesh/govern/model-versions.md).

## Лучшие практики для производителей

Производители отвечают за создание, развёртывание, коммуникацию и вывод из эксплуатации версий моделей. Ниже описаны шаги, которые следует выполнить при внедрении новой версии модели.

* [Шаг 1: Определите, когда изменение требует новой версии](#step-1-decide-when-a-change-needs-a-new-version)

  * [Шаг 2: Безопасно создайте новую версию](#step-2-create-the-new-version-safely)
  * [Шаг 3: Добавьте дату вывода версии из эксплуатации](#step-3-add-a-deprecation-date)
  * [Шаг 4: Сообщите о новой версии](#step-4-communicate-the-new-version)
  * [Шаг 5: Назначьте новую версию последней](#step-5-set-the-new-latest-version)
  * [Шаг 6: Удалите устаревшие версии](#step-6-clean-up-deprecated-versions)

#### Шаг 1: Определить, когда изменение требует новой версии

При создании исходной версии модели используйте [контракты моделей](https://docs.getdbt.tech/docs/mesh/govern/model-contracts.md), чтобы изменения, нарушающие обратную совместимость, вызывали ошибки во время разработки. Контракт модели гарантирует, что вы, как её поставщик, не изменяете структуру или типы данных выходной модели. Если изменение нарушает контракт, например при удалении столбца или изменении его типа, создайте новую версию модели с обновлённым контрактом вместо того, чтобы изменять существующую версию на месте.

Примеры разрушающих изменений, которые могут потребовать новую версию:

* Удаление столбца
* Переименование столбца
* Изменение типа столбца

Примеры неразрушающих изменений:

* Добавление нового столбца
* Исправление ошибки в существующем столбце

Примеры изменений, которые могут быть разрушающими в зависимости от бизнес-логики:

* Изменение логики метрики
* Изменение гранулярности
* Модификация фильтров
* Переписывание `CASE`-выражений

#### Шаг 2: Безопасно создать новую версию

После того как вы решили, что изменение требует новой [версии](https://docs.getdbt.tech/reference/resource-properties/versions.md), выполните следующие шаги, чтобы создать её без нарушения существующих рабочих процессов. Допустим, вы удаляете столбец:

1. Создайте новый файл модели для новой версии. Например, `fishtown_analytics_orders_v2.sql`. У каждой версии модели должен быть свой SQL-файл.

2. Оставьте версию по умолчанию стабильной. В файле `properties.yml` модели:

   * Укажите [`versions`](https://docs.getdbt.tech/reference/resource-properties/versions.md), включив старую и новую версии: `- v: 1` и `- v: 2` соответственно.
   * Установите [`latest_version:`](https://docs.getdbt.tech/reference/resource-properties/latest_version.md) в `latest_version: 1`.

   Это гарантирует, что downstream‑потребители, использующие `ref(...)`, не начнут случайно использовать v2. Если этого не сделать, по умолчанию будет выбрана версия с наибольшим номером, что может привести к разрушающим изменениям для потребителей.

3. Настройте [alias](https://docs.getdbt.tech/reference/resource-configs/alias.md) или создайте представление (view) поверх последней версии модели. Это гарантирует, что `fishtown_analytics_orders` (без суффикса версии) всегда существует как объект в хранилище и указывает на последнюю версию. Это также защищает внешние инструменты и BI‑дашборды.

#### Шаг 3: Добавить дату депрекейта

1. В файле `properties.yml` модели задайте [`deprecation_date`](https://docs.getdbt.tech/reference/resource-properties/deprecation_date.md) для старой версии модели. `deprecation_date` — это дата в будущем, которая указывает, когда старая версия будет удалена.

Это уведомляет пользователей нижестоящих моделей и отображается в логах `dbt run` как предупреждение о том, что старая версия скоро будет выведена из эксплуатации и пользователям потребуется [перейти](#best-practices-for-consumers) на новую версию.

к сведению

Если для вашей модели [принудительно применяется контракт](https://docs.getdbt.tech/docs/mesh/govern/model-contracts.md), вы не сможете удалить её до наступления `deprecation_date`. dbt не позволяет удалять модели с принудительно применяемыми контрактами до наступления их `deprecation_date`, чтобы защитить потребителей, зависящих от этих моделей.

Если вы попытаетесь удалить версионируемую модель до наступления её `deprecation_date`, dbt выдаст ошибку при запусках в среде разработки, а задания завершатся с ошибкой.

models/properties.yml

```yaml
models:
  - name: fishtown_analytics_orders
    latest_version: 1
    columns:
      - name: column_to_remove
      - name: column_to_keep

    versions:
      - v: 1                 # старая версия (использует все столбцы верхнего уровня)
        deprecation_date: "2025-12-31"
      - v: 2                 # новая версия
        columns:
          - include: all
            exclude: [column_to_remove]   # столбцы, удалённые в v2
```

2. Вмержите новую версию в основную ветку.
3. Запустите джобу для сборки новой версии.
4. Убедитесь, что новая версия успешно собирается.
5. Проверьте, что дата депрекейта корректно отображается в логах `dbt run`.

Если вы попытаетесь ссылаться на модели (например, `{{ ref('upstream_project', 'model_name', v=1) }}`) с аргументом `v=1` после наступления даты депрекейта, вызов `ref` завершится ошибкой после того, как проект‑производитель удалит версию `v1`.

#### Шаг 4: Сообщить о новой версии

После создания новой версии и установки даты депрекейта для старой версии сообщите об этом downstream‑потребителям. Дайте им знать, что:

* Доступна новая версия и определён таймлайн депрекейта.
* Потребители могут протестировать новую версию и [мигрировать](#best-practices-for-consumers) на неё.
* Для тестирования новой версии можно использовать `v=2` при обращении к модели. Например: `{{ ref('upstream_project', 'model_name', v=2) }}`.

#### Шаг 5: Назначьте новую версию последней

После того как потребители перейдут на новую версию, назначьте её последней версией. v1 остаётся в проекте до завершения [шага 6](#step-6-clean-up-deprecated-versions).

models/properties.yml

```yaml
models:
  - name: fishtown_analytics_orders
    latest_version: 2 # обновляем с 1 на 2, чтобы сделать новую версию версией по умолчанию
    versions:
          - v: 1 # старая версия
      - v: 2 # новая версия
```

Это обновит `ref` по умолчанию на новую версию. Например, `{{ ref('upstream_project', 'fishtown_analytics_orders') }}` теперь будет указывать на модель `fishtown_analytics_orders_v2` в проекте `upstream_project`. Если потребителям всё ещё нужна старая версия, они могут использовать `v=1`: `{{ ref('upstream_project', 'fishtown_analytics_orders', v=1) }}`.

#### Шаг 6: Очистить депрекейтнутые версии

После того как все потребители [перейдут](#best-practices-for-consumers) на новую версию, можно удалить устаревшую версию. Вы можете выбрать «жёсткое удаление» всех старых версий или «мягкое удаление», чтобы сохранить преемственность.

к сведению

Перед удалением или переименованием версионируемой модели с принудительно применяемым контрактом сначала объявите устаревшей версию, которую планируете вывести из эксплуатации.

Задайте `deprecation_date` для выводимой из эксплуатации версии. Если вы удаляете её немедленно, укажите дату в прошлом. Выполните слияние этого изменения и запустите задание в производственной среде, чтобы [CI с учётом состояния](https://docs.getdbt.tech/docs/deploy/ci-jobs.md) зафиксировал объявление версии устаревшей. В следующем изменении удалите или переименуйте модель, например переименуйте `fishtown_analytics_orders_v2.sql` в `fishtown_analytics_orders.sql`.

Если пропустить этот промежуточный шаг, dbt может расценить удаление как неожиданное изменение контракта, нарушающее совместимость, что приведёт к сбою CI. При необходимости посмотрите [видео с пошаговым разбором удаления версионируемой модели с принудительно применяемым контрактом](https://www.youtube.com/watch?v=FQ905Zj5C1o).

### Жёсткое удаление (самый чистый вариант)

«Физическое удаление» старых версий — самый аккуратный подход. Оно удаляет артефакты версий из проекта и хранилища данных.

Если для модели принудительно применяется контракт, сначала выполните действия из информационного блока выше. Затем в рамках отдельного изменения:

1. Удалите SQL-файл устаревшей версии (например, `fishtown_analytics_orders_v1.sql`).
2. Если вы полностью отказываетесь от версионирования, переименуйте файл последней версии, присвоив ему базовое имя (например, `fishtown_analytics_orders_v2.sql` в `fishtown_analytics_orders.sql`).
3. Удалите все спецификации версий из файла `.yml`.
4. Удалите объекты устаревших версий из хранилища данных с помощью скрипта, запускаемого вручную, или макроса очистки.

### Мягкое удаление (с сохранением непрерывности)

«Мягкое удаление» старых версий сохраняет все их артефакты, чтобы избежать путаницы, если в будущем появятся новые версии модели, и обеспечить преемственность. Помните, что ваша платформа контроля версий также хранит историю всех этих изменений.

Если для модели принудительно применяется контракт, сначала выполните действия из блока выше. Затем внесите отдельное изменение:

1. Перенаправьте алиас `fishtown_analytics_orders` на файл последней версии (например, `fishtown_analytics_orders_v2`) или создайте представление поверх последней версии модели.

2. Используйте [параметр конфигурации](https://docs.getdbt.tech/reference/resource-configs/enabled.md) `enabled`, чтобы отключить устаревшую версию модели: тогда она не будет запускаться в заданиях dbt и на неё нельзя будет ссылаться через межпроектный ref. Например:

   models/properties.yml

   ```yaml
   models:
     - name: fishtown_analytics_orders
       latest_version: 2
       columns:
         - name: column_to_remove
         - name: column_to_keep

       versions:
         - v: 1                 # старая версия (использует все столбцы верхнего уровня)
           deprecation_date: "2025-12-31"
           config:
             enabled: false  # отключаем депрекейтнутую версию, чтобы она больше не запускалась
         - v: 2                 # новая версия
           columns:
             - include: all
               exclude: [column_to_remove]   # столбцы, удалённые в v2
   ```

3. Удалите объект `fishtown_analytics_orders_v1` из хранилища вручную, через соответствующий процесс или с помощью cleanup‑макроса.

... и это всё! Вы добавили новую версию модели и завершили очистку на стороне производителя. Следующий раздел предназначен для потребителей: в нём описано, как оценить новые версии и перейти на них.

## Лучшие практики для потребителей

Потребители зависят от upstream‑моделей и должны убедиться, что переходы между версиями не приводят к непреднамеренным поломкам. Используйте следующие шаги для миграции на новую версию:

1. Начните с создания межпроектной ссылки, чтобы использовать публичную модель из другого проекта. В данном случае — `{{ ref('upstream_project', 'fishtown_analytics_orders') }}`.
2. Когда появятся предупреждения об устаревании, протестируйте последнюю версию модели, явно указав её в вызове `ref`. Например, `{{ ref('upstream_project', 'fishtown_analytics_orders', v=2) }}`. Проверьте, нарушает ли новая версия совместимость с вашим проектом и не приводит ли она к непредвиденным последствиям.
   * Если это так, рассмотрите возможность явно «закрепить» текущую рабочую версию модели, прежде чем новая версия станет версией по умолчанию: `{{ ref('upstream_project', 'fishtown_analytics_orders', v=1) }}`. Помните, что вам потребуется перейти на новую версию до даты прекращения поддержки устаревшей версии.
3. До даты прекращения поддержки устаревшей версии вы можете перейти на новую версию модели, удалив указание версии из межпроектной ссылки: `{{ ref('upstream_project', 'fishtown_analytics_orders') }}`. Внесите необходимые изменения в логику зависимых моделей, чтобы обеспечить совместимость с новой версией.

Потребителям следует планировать миграции с учётом собственных циклов релизов команды.

## Связанная документация

* [Версии моделей](https://docs.getdbt.tech/docs/mesh/govern/model-versions.md)
* [Контракты моделей](https://docs.getdbt.tech/docs/mesh/govern/model-contracts.md)
* [`deprecation_date`](https://docs.getdbt.tech/reference/resource-properties/deprecation_date.md)
* [Задания CI](https://docs.getdbt.tech/docs/deploy/ci-jobs.md)
* [Зависимости проектов](https://docs.getdbt.tech/docs/mesh/govern/project-dependencies.md)
* [Быстрый старт с Mesh](https://docs.getdbt.tech/guides/mesh-qs.md)
