🚀 NEUE FEATURES: Push-to-Gitea, Inotify-Watcher, Changelog mit git log
docker-build-and-push / build (push) Successful in 1m54s

This commit is contained in:
KI-Sparringpartner
2026-08-03 17:23:50 +02:00
parent b390d90061
commit 9161abae63
6 changed files with 187 additions and 66 deletions
+68 -34
View File
@@ -19,6 +19,13 @@ class UnsubscribeRequest(BaseModel):
project_name: str
class PushRequest(BaseModel):
"""Schema für Push mit Changelog-Content"""
project_name: str
commit_message: str = "AI-bearbeitete Änderungen pushen"
changelog_content: str | None = None
@router.get("/projects") # Listet abonierte Projekte!
async def list_projects():
"""Listet lokale (abonierte) Projekte an."""
@@ -27,13 +34,12 @@ async def list_projects():
projects = []
if PROJECTS_DIR.exists() and str(PROJECTS_DIR).strip():
# Sortiere nach dem Status der Changes zuerst
all_projects = []
for project_dir in sorted(PROJECTS_DIR.iterdir()):
if project_dir.is_dir() and not project_dir.name.startswith('.'):
has_git = (project_dir / '.git').exists()
# Pruefe ob dieses Projekt bearbeitet werden darf (chmod-check)
# Pruefe ob dieses Projekt bearbeitet werden darf
can_write = os.access(str(project_dir), os.W_OK) if project_dir.exists() else False
all_projects.append({
@@ -44,8 +50,7 @@ async def list_projects():
"can_write": can_write
})
# Sortiere: Projects mit Changes zuerst (kan signale anzeigen)
projects = sorted(all_projects, key=lambda x: ("." in x["name"]), reverse=True)
projects = sorted(all_projects, key=lambda x: ("" in x["name"]), reverse=True)
return {"projects": projects}
@@ -53,7 +58,7 @@ async def list_projects():
@router.post("/unsubscribe") # Deabonination Endpoint!
async def unsubscribe_repo(req: UnsubscribeRequest):
"""Loeschen eines abonnierten Projekts."""
from .main import PROJECTS_DIR, get_token
from .main import PROJECTS_DIR
target_dir = PROJECTS_DIR / req.project_name
@@ -61,37 +66,13 @@ async def unsubscribe_repo(req: UnsubscribeRequest):
return {"success": False, "error": f"Projekt '{req.project_name}' nicht gefunden"}
try:
import shutil
# ✅ SCHRITT 1: Alle Berechtigungen normalisieren damit wir es loeschen können!
# Alles auf Schreibbar setzen fuer Loeschen
set_permissions(str(target_dir))
# ✅ SCHRITT 2: Mit FORCE-LöSCHUNG entfernen (wegen root-Besitzern)
import stat
def force_remove_dir(dir_path):
"""Erzwingt das Loeschen von Verzeichnissen."""
for root, dirs, files in os.walk(str(dir_path), topdown=False):
for d in dirs:
dir_full = Path(root) / d
try:
dir_full.chmod(0o755 | stat.S_IWUSR | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
except Exception:
pass
for f in files:
file_full = Path(root) / f
try:
# Schreibrechte wiederherstellen
os.chmod(str(file_full), 0o666)
file_full.unlink()
except Exception:
pass
force_remove_dir(target_dir)
import shutil
shutil.rmtree(str(target_dir))
return {"success": True, "message": f"{req.project_name} erfolgreich geloescht"}
except Exception as e:
# Fallback mit rm -rf (Unix-Force)
try:
@@ -136,7 +117,7 @@ async def subscribe_repo(req: SubscribeRequest):
if not result["success"]:
return {"error": result.get("error"), "success": False}
# BERECHTIGUNGEN SETZEN NACH DEM KLOONEN!
# BERECHTIGUNGEN SETZEN NACH DEM KLOONEN!
set_permissions(str(target_dir))
generate_changelog(target_dir)
@@ -149,6 +130,59 @@ async def subscribe_repo(req: SubscribeRequest):
}
@router.post("/push") # Push zu Gitea!
async def push_to_gitea(req: PushRequest):
"""Pusht Changes eines Projekts zurueck zu Gitea."""
from .main import PROJECTS_DIR
import stat
target_dir = PROJECTS_DIR / req.project_name
if not target_dir.exists():
return {"success": False, "error": f"Projekt '{req.project_name}' nicht gefunden"}
# Alles auf Schreibbar setzen fuer Push
force_remove_all(str(target_dir))
result = push_changes(target_dir, req.commit_message, req.changelog_content)
if result["success"]:
return {
"message": f"{req.project_name} erfolgreich gepusht!",
"path": str(target_dir),
"output": result.get("output", ""),
"success": True
}
else:
return {"error": result.get("error"), "success": False}
@router.post("/push/{project_name}") # Alternative Push-Route!
async def push_project(project_name: str):
"""Pusht Changes eines Projekts zurueck zu Gitea (ohne ChangelogContent)."""
from .main import PROJECTS_DIR
target_dir = PROJECTS_DIR / project_name
if not target_dir.exists():
return {"success": False, "error": f"Projekt '{project_name}' nicht gefunden"}
# Alles auf Schreibbar setzen fuer Push
force_remove_all(str(target_dir))
result = push_changes(target_dir, "AI-bearbeitete Änderungen")
if result["success"]:
return {
"message": f"{project_name} erfolgreich gepusht!",
"path": str(target_dir),
"output": result.get("output", ""),
"success": True
}
else:
return {"error": result.get("error"), "success": False}
# Importiere die Funktionen am Ende damit sie verfügbar sind!
from .git_manager import clone_repo, set_permissions
from .git_manager import clone_repo, set_permissions, push_changes, force_remove_all
from .changelog_gen import generate_changelog