Выпуск версии

Схема версионирования

Версия вычисляется из git автоматически — versioneer 0.29. Настройки в pyproject.toml:

[tool.versioneer]
VCS = "git"
style = "pep440"
versionfile_source = "network/_version.py"
versionfile_build = "network/_version.py"
tag_prefix = ""
parentdir_prefix = ""

Из этого следует:

  • стиль версий — PEP 440;

  • префикса у тегов нет: тег выглядит как 1.2.3, а не v1.2.3;

  • network/_version.py — сгенерированный файл, руками не правится и исключён из линтеров;

  • коммит без тега получает версию вида 1.2.3+N.gHASH — наличие + в версии означает сборку не с тега.

Номер версии

Тег ставится на каждую выкатку в прод — прод не работает на коммите без тега. Номер — семантический:

  • мажорный — изменение ломает контракт API v1 или клиента станции (инвариант 7 в Контекст для ИИ-агента такого не допускает, так что это исключение с отдельным решением);

  • минорный — новые функции, новые переменные окружения, миграции;

  • патч — только исправления, без миграций.

Журнал изменений

CHANGELOG.md в корне репозитория, формат Keep a Changelog. Изменение, которое заметит оператор портала или станции, дописывается в раздел «Не выпущено» тем же MR. Первым в версии идёт раздел «Требует действий при обновлении»: переименованные и обязательные переменные, новые сервисы, миграции без отката, ручные шаги.

Порядок выпуска

  1. Убедиться, что основная ветка зелёная: линтеры, тесты, сборка документации.

  2. В CHANGELOG.md переименовать «Не выпущено» в [X.Y.Z] — ГГГГ-ММ-ДД и открыть над ним новый пустой «Не выпущено». Закоммитить.

  3. Поставить аннотированный тег с номером версии; сообщение — раздел «Требует действий» этой версии:

    git tag -a 1.2.3        # в редакторе: заголовок "1.2.3" и раздел «Требует действий»
    git push origin 1.2.3
    
  4. Пайплайн по тегу:

    • publish дополнительно помечает образ тегом коммита и :latest;

    • deploy_stand выкатывает тег на стенд;

    • deploy_prod ждёт ручного запуска, затем клонирует этот тег на прод-сервер и выполняет ./soniks.sh update_prod.

Выкатка в прод срабатывает только по тегу и только по кнопке — см. CI/CD и деплой, там же описан откат на предыдущий тег.

Сборка пакета

tox -e build     # python -m build → dist/ (setup.py на Python 3.12 не используется)

В CI то же делает джоба build (для портала) и build_api (для сгенерированного API-клиента).

Примечание

В tox.ini сохранилось окружение upload, публикующее пакет на PyPI через twine. Соответствующая джоба CI была удалена вместе с переходом на ssh-деплой, так что окружение сейчас не используется — портал распространяется Docker-образом, а не пакетом.

Перед выпуском

  • Прогнать tox -e deps — расхождение пинов ловится там.

  • Если менялись зависимости, перегенерировать requirements-файлы: ./contrib/refresh-requirements.sh.

  • Если менялись сериализаторы или представления API — убедиться, что джоба schema проходит --validate, иначе клиент и справочник соберутся из устаревшей схемы.

  • Обновить документацию: новые настройки, задачи, команды и эндпоинты должны попасть в соответствующие страницы (см. Как вносить изменения).

  • Миграция, после которой предыдущий тег не запустится (RemoveField, DeleteModel, переименование, NOT NULL без default, необратимый RunPython), идёт отдельным MR, а в CHANGELOG.md и в описании тега пишется «откат на предыдущий тег невозможен, только восстановление из дампа». Иначе откат — штатная команда, см. CI/CD и деплой.