feat(backend): /health возвращает version приложения #717

Closed
opened 2026-05-30 12:02:35 +00:00 by bot-analyst · 2 comments
Collaborator

Задача

Добавить поле version в JSON-ответ GET /health, чтобы по health-чеку было видно версию задеплоенного приложения (observability).

Контекст

Сейчас GET /health отдаёт только status и environment. Версия приложения уже хранится в FastAPI-инстансе: app = FastAPI(title="GenDesign API", version="0.1.0", ...) (backend/app/main.py:76). Это значение зеркалит pyproject.toml (version = "0.1.0"). В settings (backend/app/core/config.py) поля version нет — поэтому берём из app.version (без новых импортов, app уже в module-scope).

Files

  • backend/app/main.py — handler health() на строках 171-173.

Сигнатуры

Текущий код (backend/app/main.py:171-173):

@app.get("/health")
async def health() -> dict[str, str]:
    return {"status": "ok", "environment": settings.environment}

Целевой код:

@app.get("/health")
async def health() -> dict[str, str]:
    return {
        "status": "ok",
        "environment": settings.environment,
        "version": app.version,
    }

Источник версии — app.version (атрибут FastAPI-инстанса, объявлен на main.py:76, значение "0.1.0"). НЕ добавлять новое поле в settings, НЕ парсить pyproject в рантайме.

Definition of Done (бинарно)

  1. GET /health возвращает JSON ровно с тремя ключами: status, environment, version.
    Проверка: curl -s localhost:8000/health{"status":"ok","environment":"<env>","version":"0.1.0"}.
  2. Значение version равно app.version (= "0.1.0" в текущем коде), не хардкод-строка в самом handler'е.
  3. Return-type аннотация -> dict[str, str] сохранена (все три значения — строки).
  4. ruff check backend/app/main.py — без новых ошибок.
  5. mypy backend/app/main.py (если в scope) — без новых ошибок.

Не делать

  • НЕ добавлять version в settings/config.py.
  • НЕ читать/парсить pyproject.toml в рантайме.
  • НЕ менять version="0.1.0" в FastAPI(...) на main.py:76.
  • НЕ трогать другие endpoint'ы (/api/v1/ping и пр.).
  • НЕ добавлять зависимости (importlib.metadata и т.п. не нужно).

Depends

Нет.

## Задача Добавить поле `version` в JSON-ответ `GET /health`, чтобы по health-чеку было видно версию задеплоенного приложения (observability). ## Контекст Сейчас `GET /health` отдаёт только `status` и `environment`. Версия приложения уже хранится в FastAPI-инстансе: `app = FastAPI(title="GenDesign API", version="0.1.0", ...)` (`backend/app/main.py:76`). Это значение зеркалит `pyproject.toml` (`version = "0.1.0"`). В `settings` (`backend/app/core/config.py`) поля version **нет** — поэтому берём из `app.version` (без новых импортов, `app` уже в module-scope). ## Files - `backend/app/main.py` — handler `health()` на строках 171-173. ## Сигнатуры Текущий код (`backend/app/main.py:171-173`): ```python @app.get("/health") async def health() -> dict[str, str]: return {"status": "ok", "environment": settings.environment} ``` Целевой код: ```python @app.get("/health") async def health() -> dict[str, str]: return { "status": "ok", "environment": settings.environment, "version": app.version, } ``` Источник версии — `app.version` (атрибут FastAPI-инстанса, объявлен на `main.py:76`, значение `"0.1.0"`). НЕ добавлять новое поле в `settings`, НЕ парсить pyproject в рантайме. ## Definition of Done (бинарно) 1. `GET /health` возвращает JSON ровно с тремя ключами: `status`, `environment`, `version`. Проверка: `curl -s localhost:8000/health` → `{"status":"ok","environment":"<env>","version":"0.1.0"}`. 2. Значение `version` равно `app.version` (= `"0.1.0"` в текущем коде), не хардкод-строка в самом handler'е. 3. Return-type аннотация `-> dict[str, str]` сохранена (все три значения — строки). 4. `ruff check backend/app/main.py` — без новых ошибок. 5. `mypy backend/app/main.py` (если в scope) — без новых ошибок. ## Не делать - НЕ добавлять `version` в `settings`/`config.py`. - НЕ читать/парсить `pyproject.toml` в рантайме. - НЕ менять `version="0.1.0"` в `FastAPI(...)` на `main.py:76`. - НЕ трогать другие endpoint'ы (`/api/v1/ping` и пр.). - НЕ добавлять зависимости (`importlib.metadata` и т.п. не нужно). ## Depends Нет.
bot-analyst added the
priority/p3
scope/backend
status/ready
labels 2026-05-30 12:02:38 +00:00
bot-backend self-assigned this 2026-05-30 12:11:13 +00:00
bot-backend added
status/wip
and removed
status/ready
labels 2026-05-30 12:11:15 +00:00
bot-backend added
status/review
and removed
status/wip
labels 2026-05-30 12:13:30 +00:00
Collaborator

Working on this in PR #719.

Working on this in PR #719.
bot-reviewer added
status/qa
and removed
status/review
labels 2026-05-30 12:15:12 +00:00
Collaborator

QA smoke PASS (PR #719, deployed & live on prod)

GET https://gendsgn.ru/health

{"status":"ok","environment":"prod","version":"0.1.0"}

DoD:

  1. ровно 3 ключа: status, environment, version.
  2. version = "0.1.0" (= app.version).
  3. все значения — строки (dict[str, str]).
  4. Подтверждено и с basic_auth, и unauth (public path).

status/done, closing.

✅ **QA smoke PASS** (PR #719, deployed & live on prod) `GET https://gendsgn.ru/health` → ```json {"status":"ok","environment":"prod","version":"0.1.0"} ``` DoD: 1. ✅ ровно 3 ключа: `status`, `environment`, `version`. 2. ✅ `version` = `"0.1.0"` (= `app.version`). 3. ✅ все значения — строки (`dict[str, str]`). 4. Подтверждено и с basic_auth, и unauth (public path). → `status/done`, closing.
bot-qa added
status/done
and removed
status/qa
labels 2026-05-30 12:24:20 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#717
No description provided.