From 82f278ca00a887ff17e788396d48e7e53974531ff121a5151be2de07abb249a3 Mon Sep 17 00:00:00 2001 From: wlfb Date: Sun, 19 Jul 2026 14:57:49 +0200 Subject: [PATCH] feat: Versionsanzeige (VERSION-Datei, Footer, /api/version, Image-Tag) Co-Authored-By: Claude Fable 5 --- create_pod_finance.sh | 2 +- finance/Containerfile | 1 + finance/VERSION | 1 + finance/app/main.py | 9 ++++++++- finance/app/routers/gui.py | 2 ++ finance/app/static/style.css | 6 ++++++ finance/app/templates/base.html | 1 + finance/app/version.py | 9 +++++++++ finance/tests/test_gui.py | 7 +++++++ 9 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 finance/VERSION create mode 100644 finance/app/version.py diff --git a/create_pod_finance.sh b/create_pod_finance.sh index 120f73c..5ac7727 100755 --- a/create_pod_finance.sh +++ b/create_pod_finance.sh @@ -17,7 +17,7 @@ GRAFANA_CTR_NAME='finance-grafana_ctr' # needed). POSTGRES_IMAGE='docker.io/library/postgres:17.10' GRAFANA_IMAGE='docker.io/grafana/grafana-oss:12.1.0' -API_IMAGE='localhost/finance-api:0.1.0' +API_IMAGE="localhost/finance-api:$(cat "$HOME/bin/finance/VERSION")" HOST_LOCAL_IP='127.0.0.1' # Expose API on 8096 -> 8000 diff --git a/finance/Containerfile b/finance/Containerfile index 68d61a1..6a86cb0 100644 --- a/finance/Containerfile +++ b/finance/Containerfile @@ -6,6 +6,7 @@ RUN pip install --no-cache-dir -r requirements.txt COPY app/ app/ COPY alembic/ alembic/ COPY alembic.ini . +COPY VERSION . COPY entrypoint.sh /entrypoint.sh RUN chmod +x /entrypoint.sh EXPOSE 8000 diff --git a/finance/VERSION b/finance/VERSION new file mode 100644 index 0000000..a82804c --- /dev/null +++ b/finance/VERSION @@ -0,0 +1 @@ +0.2.0 diff --git a/finance/app/main.py b/finance/app/main.py index af484f7..d28b058 100644 --- a/finance/app/main.py +++ b/finance/app/main.py @@ -1,17 +1,19 @@ import hmac from contextlib import asynccontextmanager -from fastapi import FastAPI, Form, Request +from fastapi import Depends, FastAPI, Form, Request from fastapi.responses import HTMLResponse, RedirectResponse from fastapi.staticfiles import StaticFiles from app import auth +from app.auth import require_auth from app.config import get_settings from app.db import get_engine from app.models.views import create_views from app.routers import (accounts, categories, gui, imports, planning, scenarios, transactions) from app.routers.gui import templates +from app.version import get_version @asynccontextmanager @@ -55,3 +57,8 @@ def logout(): resp = RedirectResponse("/login", status_code=303) resp.delete_cookie(auth.COOKIE) return resp + + +@app.get("/api/version", dependencies=[Depends(require_auth)]) +def api_version(): + return {"version": get_version()} diff --git a/finance/app/routers/gui.py b/finance/app/routers/gui.py index ef26afc..113d728 100644 --- a/finance/app/routers/gui.py +++ b/finance/app/routers/gui.py @@ -21,8 +21,10 @@ from app.routers.planning import recurring_suggestions as _recurring_suggestions from app.routers.scenarios import list_scenarios as _list_scenarios from app.routers.transactions import list_transactions from app.services.balances import account_balance, total_balance +from app.version import get_version templates = Jinja2Templates(directory="app/templates") +templates.env.globals["app_version"] = get_version() router = APIRouter() diff --git a/finance/app/static/style.css b/finance/app/static/style.css index 86df18f..976c440 100644 --- a/finance/app/static/style.css +++ b/finance/app/static/style.css @@ -151,3 +151,9 @@ section.planning-section { section.planning-section fieldset { margin-top: 0.75rem; } + +.version { + margin-top: 2rem; + color: #888; + font-size: 0.85rem; +} diff --git a/finance/app/templates/base.html b/finance/app/templates/base.html index b811c16..16a4cb9 100644 --- a/finance/app/templates/base.html +++ b/finance/app/templates/base.html @@ -64,5 +64,6 @@ } }); + diff --git a/finance/app/version.py b/finance/app/version.py new file mode 100644 index 0000000..88be42b --- /dev/null +++ b/finance/app/version.py @@ -0,0 +1,9 @@ +from pathlib import Path + + +def get_version() -> str: + f = Path(__file__).resolve().parent.parent / "VERSION" + try: + return f.read_text().strip() + except OSError: + return "0.0.0-dev" diff --git a/finance/tests/test_gui.py b/finance/tests/test_gui.py index a6354d1..a70f379 100644 --- a/finance/tests/test_gui.py +++ b/finance/tests/test_gui.py @@ -33,6 +33,13 @@ def test_import_list_fragment_renders_after_login(client): assert "Noch keine Imports" in r.text +def test_version_visible(client): + r = client.get("/api/version", headers={"Authorization": "Bearer test-key"}) + assert r.status_code == 200 and r.json()["version"] == "0.2.0" + client.post("/login", data={"username": "admin", "password": "geheim"}) + assert "v0.2.0" in client.get("/").text + + def test_planning_page_has_all_sections(client): client.post("/login", data={"username": "admin", "password": "geheim"}) r = client.get("/planung")