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

Релизы и канал предварительных версий

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


Версионирование

Canopy следует принципам Semantic Versioning. Единственным источником истины о текущей версии является файл /VERSION в корне репозитория.

  • Патч (например, 1.0.01.0.1): только исправления ошибок. Всегда безопасно обновлять.
  • Минорный (например, 1.0.01.1.0): новые функции. Обратная совместимость согласно политике совместимости.
  • Мажорный (например, 1.x2.0.0): критические изменения. Примечания по миграции поставляются вместе с выпуском.

Версия обновляется один раз на PR, а не на коммит. Запись CHANGELOG PR использует новую версию в качестве заголовка; CI-задача version-check.yml отклоняет любой PR, который обновляет VERSION без соответствующего заголовка ## [<version>] в CHANGELOG.md.


Теги образов контейнеров

Каждый push в main и каждый тег v*.*.* запускает .github/workflows/docker-publish.yml, который собирает и публикует мультиархитектурные (amd64 + arm64) образы в GHCR.

Для тега релиза, например v1.2.3, публикуемые теги для каждого образа:

ТегУказывает наСтабильность
1.2.3именно этот релизда — закрепляйте в продакшне
1.2последний патч на 1.2.xобновляется при патчах
1последний минор на 1.xобновляется при минорных выпусках
latestпоследний не-предварительный выпускобновляется при каждом выпуске
sha-<short>конкретный коммитда — для отладки / предварительных версий

При push в main (без тега) создаются только теги main и sha-<short> — никогда не latest и никаких semver-тегов.

Все опубликованные манифесты образов подписаны с помощью cosign keyless OIDC. Подробности о верификации и SBOM — в разделе Цепочка поставок.


Канал предварительных версий

Для минорных выпусков, изменяющих компоновку контейнеров, базовые образы, UID по умолчанию, имена томов, порты по умолчанию или схему данных таким образом, что это требует действий оператора, перед финальным тегом публикуется релиз-кандидат.

Соглашения:

  • Теги RC имеют вид vX.Y.0-rc.N — никогда не для патч-релизов, только для минорных выпусков с изменениями, видимыми для оператора.
  • Действие docker/metadata-action в процессе публикации настроено с flavor: latest=auto. Это автоматически исключает теги semver предварительных версий из :latest, :X.Y и :X — RC публикуются только как :X.Y.0-rc.N. Операторы, закрепляющие :latest, не получат RC случайно.
  • Релиз GitHub для тега RC должен быть помечен как предварительный на странице Releases. Текущий процесс github-release.yml всегда создаёт не-предварительный релиз; мейнтейнер вручную переключает флаг предварительного выпуска после завершения рабочего процесса (или редактирует релиз через gh release edit vX.Y.0-rc.N --prerelease).

Период выдержки:

  • RC выдерживается не менее 48–72 часов до продвижения, или пока хотя бы один оператор за пределами мейнтейнеров не сообщит об успешном обновлении — в зависимости от того, что дольше.
  • Отчёты об ошибках для RC выходят как vX.Y.0-rc.N+1, если проблема заслуживает исправления. Предыдущий RC остаётся в GHCR для воспроизводимости.

Продвижение до финальной версии:

  • Финальный тег vX.Y.0 создаётся на том же коммите, что и последний RC. Рабочий процесс публикации пересобирает и перетегирует мультиархитектурные образы; дайджест будет отличаться от RC, хотя исходный код идентичен (входные данные сборки включают временные метки).
  • Теги :X.Y, :X и :latest в этот момент начинают указывать на финальный релиз.

Выпуск релиза (контрольный список для мейнтейнера)

Для обычного патча или минорного выпуска — без канала RC:

  1. В ветке функциональности обновите VERSION и добавьте соответствующий заголовок ## [<version>] - YYYY-MM-DD в CHANGELOG.md.
  2. Запустите python scripts/dump_openapi.py, если изменился какой-либо маршрут или схема бэкенда; зафиксируйте результат, если он изменился.
  3. Откройте PR. CI выполняет проверку lint, тесты, проверку дрейфа OpenAPI и version-check.yml.
  4. Выполните squash-merge в main.
  5. Из main: git tag -s v<version> -m "v<version>" (или git tag v<version>, если ключ подписи не настроен), git push origin v<version>.
  6. Рабочий процесс Publish GitHub Release извлекает раздел ## [<version>] из CHANGELOG.md и создаёт релиз GitHub.
  7. Рабочий процесс Publish Docker images to GHCR собирает, подписывает и публикует мультиархитектурные образы.
  8. Верифицируйте с помощью cosign:
    cosign verify \
    --certificate-identity-regexp 'https://github.com/Rhizo-Tech/canopy/.+' \
    --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
    ghcr.io/rhizo-tech/canopy/backend:<version>

Для минорного выпуска, требующего RC:

  1. Тот же процесс с PR и merge, но версия обновляется до 1.Y.0-rc.1.
  2. После merge создайте тег v1.Y.0-rc.1 и выполните push. Рабочий процесс публикации собирает и публикует образы RC (только :1.Y.0-rc.1, никогда :latest или короткие теги — это обеспечивает flavor: latest=auto). Рабочий процесс releases создаёт релиз GitHub; вручную переключите его в предварительный режим через gh release edit v1.Y.0-rc.1 --prerelease или в интерфейсе GitHub.
  3. Дождитесь окончания периода выдержки. При необходимости выпустите -rc.2, -rc.3 для исправления сообщённых проблем.
  4. Для продвижения: обновите VERSION до 1.Y.0 в финальном PR (запись CHANGELOG объединяет все исправления RC), выполните merge, создайте тег v1.Y.0, выполните push. Теги :latest и короткие теги теперь указывают на продвинутый релиз.

Окончание поддержки

Только последняя минорная ветка получает исправления безопасности. Полная политика — в SECURITY.md. Более старые минорные ветки не поддерживаются и не получают бэкпортов — операторам на старых версиях следует планировать обновления согласно политике совместимости.