From 2df37cb617806f00d0434f7cdbe3ae2683d448e8 Mon Sep 17 00:00:00 2001 From: Claude Code Date: Sun, 26 Apr 2026 20:28:10 +0000 Subject: [PATCH] Update-System: /api/version + /api/release-notes + RELEASES.json Frontend kann jetzt erkennen, wann eine neue Version live ist, und dem Nutzer einen passenden Hinweis sowie die Release-Notes anzeigen. Co-Authored-By: Claude Opus 4.7 (1M context) --- RELEASES.json | 12 ++++++++ src/main.py | 2 ++ src/routes/__init__.py | 0 src/routes/version_router.py | 54 ++++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+) create mode 100644 RELEASES.json create mode 100644 src/routes/__init__.py create mode 100644 src/routes/version_router.py diff --git a/RELEASES.json b/RELEASES.json new file mode 100644 index 0000000..a20d7c4 --- /dev/null +++ b/RELEASES.json @@ -0,0 +1,12 @@ +[ + { + "version": "5473ba3", + "date": "2026-04-26", + "title": "Update-System eingefuehrt", + "items": [ + "Updates beruehren ab jetzt nie mehr die Faelle oder Daten", + "Beim Promote landet eine 'Was ist neu'-Info hier", + "Strukturelle Trennung von Live- und Staging-Datenbank" + ] + } +] diff --git a/src/main.py b/src/main.py index f930a07..1df4348 100644 --- a/src/main.py +++ b/src/main.py @@ -378,6 +378,7 @@ from routers.feedback import router as feedback_router from routers.public_api import router as public_api_router from routers.chat import router as chat_router from routers.tutorial import router as tutorial_router +from routes.version_router import router as version_router app.include_router(auth_router) app.include_router(incidents_router) @@ -387,6 +388,7 @@ app.include_router(feedback_router) app.include_router(public_api_router) app.include_router(chat_router, prefix="/api/chat") app.include_router(tutorial_router) +app.include_router(version_router) @app.websocket("/api/ws") diff --git a/src/routes/__init__.py b/src/routes/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/routes/version_router.py b/src/routes/version_router.py new file mode 100644 index 0000000..a9ed470 --- /dev/null +++ b/src/routes/version_router.py @@ -0,0 +1,54 @@ +"""Version + Release-Notes-Endpoints fuer das Frontend-Update-System.""" +import json +import subprocess +from datetime import datetime, timezone +from pathlib import Path +from fastapi import APIRouter + +REPO_ROOT = Path(__file__).resolve().parent.parent.parent +RELEASES_FILE = REPO_ROOT / 'RELEASES.json' + +# Version-Hash beim Boot einmalig auslesen. +try: + COMMIT_HASH = subprocess.check_output( + ['git', 'rev-parse', '--short=10', 'HEAD'], + cwd=str(REPO_ROOT), text=True, timeout=5 + ).strip() +except Exception: + COMMIT_HASH = 'unknown' + +DEPLOYED_AT = datetime.now(timezone.utc).isoformat() + +router = APIRouter(tags=['version']) + + +@router.get('/api/version') +def version(): + return {'commit': COMMIT_HASH, 'deployed_at': DEPLOYED_AT} + + +@router.get('/api/release-notes') +def release_notes(since: str = '', limit: int = 5): + """Liefert Release-Notes seit der gegebenen Version. + + 'since' = letzte vom User gesehene Version. Liefert alle Eintraege NEUER + als diese Version. Ohne 'since' werden die letzten 'limit' Eintraege + geliefert. + """ + if not RELEASES_FILE.exists(): + return {'entries': [], 'current': COMMIT_HASH} + try: + with open(RELEASES_FILE, 'r', encoding='utf-8') as f: + data = json.load(f) + except Exception as e: + return {'entries': [], 'error': f'parse-failed: {e}'} + + if since: + result = [] + for entry in data: + if entry.get('version') == since: + break + result.append(entry) + return {'entries': result[:limit], 'current': COMMIT_HASH} + + return {'entries': data[:limit], 'current': COMMIT_HASH}