Release 0.2.3: /api/health framework dependency for flotilla
Adds an unauthenticated GET /api/health endpoint returning JSON
{version, status} for ops tooling. version is the running framework
version (read from VERSION at process start, cached as a module-level
constant in backend/app/health.py); status is "ok" with HTTP 200 in
v1, with the "degraded" / 503 path reserved in the response shape for
future degradation conditions.
The structural value is the version-match check: a deploy control
panel (flotilla, in particular) polls the endpoint after
`systemctl restart` reports active and verifies the returned version
equals the tag just deployed, catching the failure mode where a
restart did not pick up the new code.
Patch-shaped per SPEC.md §20.2 — no operator action required, no env
vars, no schema changes. The CHANGELOG carries one MAY-language step
naming the optional monitoring affordance.
SPEC.md §17 now lists the endpoint; the §19.2 candidate-topic entry
records the topic's settlement (version source = VERSION file at
import time; degraded = reserved v1 scaffold; CHANGELOG = patch shape
with MAY-language).
Tests: backend/tests/test_health.py (3 tests — 200/payload shape,
unauthenticated, version-matches-VERSION). Full suite 128/128 green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
"""§17 health-check endpoint source.
|
||||
|
||||
A small unauthenticated probe used by ops tooling (e.g. the flotilla
|
||||
deploy control panel) to verify a deploy landed correctly. The
|
||||
structural value is the version-match check — after `systemctl
|
||||
restart` reports active, the operator polls `/api/health` and
|
||||
verifies the returned `version` equals the tag just deployed,
|
||||
catching the failure mode where a restart did not pick up the new
|
||||
code.
|
||||
|
||||
The version is read from the `VERSION` file at the repo root at
|
||||
import time (§20.1's canonical source) and cached as a module-level
|
||||
constant. A missing `VERSION` fails loudly per §20.6 rather than
|
||||
serving a placeholder — a silent default would defeat the
|
||||
version-match check that is the entire point of the endpoint.
|
||||
|
||||
`status` is always `"ok"` (HTTP 200) in v1. The `"degraded"` / 503
|
||||
path stays in the response shape so a later release can wire real
|
||||
degradation conditions (reconciler stuck, migrations pending,
|
||||
provider universe empty) without breaking the contract.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
_VERSION_PATH = Path(__file__).resolve().parents[2] / "VERSION"
|
||||
|
||||
|
||||
def _read_version() -> str:
|
||||
text = _VERSION_PATH.read_text(encoding="utf-8").strip()
|
||||
if not text:
|
||||
raise RuntimeError(f"VERSION file at {_VERSION_PATH} is empty")
|
||||
return text
|
||||
|
||||
|
||||
VERSION: str = _read_version()
|
||||
Reference in New Issue
Block a user