# Выпуск версии ## Схема версионирования Версия вычисляется из git автоматически — [versioneer](https://github.com/python-versioneer/python-versioneer) 0.29. Настройки в `pyproject.toml`: ```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 в [](../ai/context.md) такого не допускает, так что это исключение с отдельным решением); * **минорный** — новые функции, новые переменные окружения, миграции; * **патч** — только исправления, без миграций. ## Журнал изменений `CHANGELOG.md` в корне репозитория, формат [Keep a Changelog](https://keepachangelog.com/ru/1.1.0/). Изменение, которое заметит оператор портала или станции, дописывается в раздел «Не выпущено» тем же MR. Первым в версии идёт раздел «Требует действий при обновлении»: переименованные и обязательные переменные, новые сервисы, миграции без отката, ручные шаги. ## Порядок выпуска 1. Убедиться, что основная ветка зелёная: линтеры, тесты, сборка документации. 2. В `CHANGELOG.md` переименовать «Не выпущено» в `[X.Y.Z] — ГГГГ-ММ-ДД` и открыть над ним новый пустой «Не выпущено». Закоммитить. 3. Поставить аннотированный тег с номером версии; сообщение — раздел «Требует действий» этой версии: ```bash 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`. Выкатка в прод срабатывает **только** по тегу и только по кнопке — см. [](deploy.md), там же описан откат на предыдущий тег. ## Сборка пакета ```bash tox -e build # python -m build → dist/ (setup.py на Python 3.12 не используется) ``` В CI то же делает джоба `build` (для портала) и `build_api` (для сгенерированного API-клиента). ```{note} В `tox.ini` сохранилось окружение `upload`, публикующее пакет на PyPI через twine. Соответствующая джоба CI была удалена вместе с переходом на ssh-деплой, так что окружение сейчас не используется — портал распространяется Docker-образом, а не пакетом. ``` ## Перед выпуском * Прогнать `tox -e deps` — расхождение пинов ловится там. * Если менялись зависимости, перегенерировать requirements-файлы: `./contrib/refresh-requirements.sh`. * Если менялись сериализаторы или представления API — убедиться, что джоба `schema` проходит `--validate`, иначе клиент и справочник соберутся из устаревшей схемы. * Обновить документацию: новые настройки, задачи, команды и эндпоинты должны попасть в соответствующие страницы (см. [](contributing.md)). * Миграция, после которой предыдущий тег не запустится (`RemoveField`, `DeleteModel`, переименование, `NOT NULL` без `default`, необратимый `RunPython`), идёт отдельным MR, а в `CHANGELOG.md` и в описании тега пишется «откат на предыдущий тег невозможен, только восстановление из дампа». Иначе откат — штатная команда, см. [](deploy.md).