diff --git a/containers/novela/main.py b/containers/novela/main.py index aa60208..8cc805c 100644 --- a/containers/novela/main.py +++ b/containers/novela/main.py @@ -53,6 +53,12 @@ app.include_router(changelog_router) app.include_router(search_router) +@app.get("/api/version") +async def version(): + from version import display_version + return JSONResponse({"version": display_version()}) + + @app.get("/health") async def health(): try: diff --git a/containers/novela/shared_templates.py b/containers/novela/shared_templates.py index 54562ee..3f78142 100644 --- a/containers/novela/shared_templates.py +++ b/containers/novela/shared_templates.py @@ -1,6 +1,7 @@ from fastapi.templating import Jinja2Templates from db import get_db_conn +from version import display_version def _develop_mode() -> bool: @@ -16,3 +17,4 @@ def _develop_mode() -> bool: templates = Jinja2Templates(directory="templates") templates.env.globals["develop_mode"] = _develop_mode +templates.env.globals["app_version"] = display_version diff --git a/containers/novela/static/sidebar.css b/containers/novela/static/sidebar.css index 8a79ee1..6608942 100644 --- a/containers/novela/static/sidebar.css +++ b/containers/novela/static/sidebar.css @@ -118,6 +118,18 @@ html { .sidebar-bottom { margin-top: auto; } +.sidebar-version { + display: block; + margin-top: 0.5rem; + text-align: center; + font-family: var(--mono); + font-size: 0.68rem; + color: var(--text-dim); + text-decoration: none; + opacity: 0.75; +} +.sidebar-version:hover { opacity: 1; } + .disk-warning { display: flex; align-items: center; diff --git a/containers/novela/templates/_sidebar.html b/containers/novela/templates/_sidebar.html index a13fd41..ff4e686 100644 --- a/containers/novela/templates/_sidebar.html +++ b/containers/novela/templates/_sidebar.html @@ -289,6 +289,7 @@ Rescan library + {{ app_version() }} diff --git a/containers/novela/version.py b/containers/novela/version.py new file mode 100644 index 0000000..cbf3acb --- /dev/null +++ b/containers/novela/version.py @@ -0,0 +1,26 @@ +"""Novela version metadata. + +The release version is the single source maintained in ``changelog.py`` +(``CHANGELOG[0]["version"]``). Dev/test builds append an explicit ``BUILD`` +segment that is incremented by ``scripts/bump-dev-build.py`` on every test +build, so operators can see exactly which image build is running in the +sidebar. ``BUILD`` is reset to 0 for releases. +""" +from __future__ import annotations + +from changelog import CHANGELOG + +BUILD = 2 + + +def _release_version() -> str: + """Return the semantic release version (e.g. v0.2.11).""" + return CHANGELOG[0]["version"] if CHANGELOG else "v0.0.0" + + +def display_version() -> str: + """Return the user-visible Novela version (e.g. v0.2.11 or v0.2.11.3).""" + version = _release_version() + if BUILD > 0: + return f"{version}.{BUILD}" + return version