Перейти к содержимому

Ревизии и версии

Правка блока ничего не перезаписывает: каждое изменение содержимого создаёт новую ревизию, а прежние остаются в истории. Страницы при этом не меняются сами — они закреплены за той версией, которая на них стоит.

Ревизия — снимок содержимого блока:

Поле
template, css, js шаблон, стили, скрипт
schema_content схема полей
changelog описание изменений, которое вы вводите при сохранении
revision_number сквозной номер ревизии внутри блока: 1, 2, 3…
version_major, version_minor версия вида 1.3
автор и дата кто и когда сохранил

Первая ревизия любого блока — 1.0, revision_number = 1.

Метаданные блока (имя, описание, docs, теги, обложка) в ревизию не входят — их правка версию не меняет.

При сохранении блок сравнивается с текущей ревизией, и результат — один из трёх:

Bump Когда Что происходит
none шаблон, стили, скрипт и схема совпадают с текущими новая ревизия не создаётся
minor содержимое изменилось, но ни одно поле схемы не исчезло 1.21.3
major из схемы удалено поле 1.22.0

Правило major одно и очень конкретное: сравниваются имена полей старой и новой схемы, включая вложенные (card.title, slides.caption). Пропало хотя бы одно — это ломающее изменение.

Отсюда следствия, которые стоит держать в голове:

  • переименование поля = удаление + добавление → major;
  • добавление полей, смена label, default, options, порядка, вкладок → minor;
  • любая правка шаблона, CSS или JS без правки схемы → minor;
  • смена типа поля при том же имени → minor, хотя данные могут перестать подходить. Автоматика этого не ловит — предупредите пользователей в changelog.

Прежде чем сохранять, можно спросить систему, во что выльется правка:

POST /api/blocks/{id}/version-check
{ "template": "…", "css": "…", "js": "…", "schema_content": { … } }

Ответ ничего не сохраняет:

{
"bump": "major",
"is_breaking": true,
"removed_fields": ["subtitle"],
"current_version": "1.2",
"next_version": "2.0"
}

Те же три поля приходят и в ответе на обычное обновление блока — в объекте version_bump. Так что о ломающем изменении вы узнаёте в момент, когда оно произошло, а не когда пожалуются пользователи.

Экземпляр блока на странице хранит:

  • ссылку на конкретную ревизию, с которой он был добавлен;
  • закреплённую версию major.minor;
  • снимок схемы на момент добавления.

Публикация страницы рендерит именно эту ревизию. Вы можете выпустить хоть десять новых версий блока — опубликованные страницы не изменятся, пока их явно не обновят. Как обновлять — Устаревание и апгрейды.

Для каждого экземпляра система считает статус обновления:

Статус Значение
up_to_date стоит актуальная версия
minor_available вышла совместимая версия, обновляется одним нажатием
major_blocked вышла несовместимая версия, нужна ручная миграция

GET /api/blocks/{id}/revisions возвращает историю блока: номера ревизий, версии, changelog, автора и дату.

  • Форк копирует версию источника: форкнули блок 2.3 — у копии тоже 2.3, но revision_number начинается с 1 и changelog фиксирует происхождение. Дальше версии блоков расходятся: между оригиналом и форком связи по версиям нет.
  • Импорт ZIP в свой же блок создаёт новую ревизию по общим правилам (то есть может дать major, если в архиве меньше полей). Импорт чужого архива создаёт новый блок с первой ревизией.
  1. Не удаляйте и не переименовывайте поля. Добавьте новое поле, а старое оставьте — даже если шаблон его больше не использует. Схема с лишним полем стоит дешевле, чем major у всех, кто поставил блок.
  2. Пишите changelog. Это единственный текст, который увидит человек, решающий, обновляться ли ему.
  3. Задавайте default новым полям. Тогда minor-обновление у пользователей пройдёт без пустых мест на странице.
  4. Проверяйте version-check перед сохранением, если правите схему заметно.

Источники: backend/src/Service/BlockVersionService.php, backend/src/Entity/BlockRevision.php, backend/src/Service/Block/{CreateBlockService,UpdateBlockService,ForkBlockService,ImportBlockService}.php, backend/src/Controller/Block/{CheckBlockVersionAction,ListBlockRevisionsAction}.php, backend/src/Service/Page/UpgradePageBlockService.php.