deployment observability, filters, stats, details

This commit is contained in:
JiriUhlir
2026-05-28 13:22:51 +02:00
parent 80d82d36dd
commit e6ffeb8fef
5 changed files with 585 additions and 34 deletions
+165 -4
View File
@@ -1,6 +1,11 @@
from app.db.database import get_connection
SUCCESS_STATUSES = ("ok", "success", "succeeded", "done", "deployed", "completed")
FAILED_STATUSES = ("failed", "failure", "error", "cancelled", "canceled")
RUNNING_STATUSES = ("running", "pending", "queued", "in_progress", "starting")
def get_apps():
con = get_connection()
@@ -38,6 +43,22 @@ def get_apps():
return [dict(row) for row in rows]
def get_app(app_id: str):
con = get_connection()
row = con.execute(
"""
SELECT id, name, language, version, status, memory, cpus, updated_at
FROM apps
WHERE id = ?
""",
(app_id,),
).fetchone()
con.close()
return dict(row) if row else None
def update_app_resources(app_id: str, memory: str, cpus: str):
con = get_connection()
@@ -60,17 +81,143 @@ def update_app_resources(app_id: str, memory: str, cpus: str):
con.close()
def get_deployments(limit: int = 100):
def get_deployments(
limit: int = 100,
status: str | None = None,
app_id: str | None = None,
source: str | None = None,
):
con = get_connection()
filters = []
params = []
if status:
normalized_status = status.strip().lower()
if normalized_status == "success":
filters.append(f"LOWER(COALESCE(status, '')) IN ({','.join('?' for _ in SUCCESS_STATUSES)})")
params.extend(SUCCESS_STATUSES)
elif normalized_status == "failed":
filters.append(f"LOWER(COALESCE(status, '')) IN ({','.join('?' for _ in FAILED_STATUSES)})")
params.extend(FAILED_STATUSES)
elif normalized_status == "running":
filters.append(f"LOWER(COALESCE(status, '')) IN ({','.join('?' for _ in RUNNING_STATUSES)})")
params.extend(RUNNING_STATUSES)
else:
filters.append("LOWER(status) = LOWER(?)")
params.append(status)
if app_id:
filters.append("app_id = ?")
params.append(app_id)
if source:
filters.append("trigger_source = ?")
params.append(source)
where = f"WHERE {' AND '.join(filters)}" if filters else ""
rows = con.execute(
f"""
SELECT
id,
app_id,
kind,
status,
started_at,
finished_at,
returncode,
trigger_source,
triggered_by_username,
triggered_by_display_name
FROM deployments
{where}
ORDER BY
CASE
WHEN LOWER(COALESCE(status, '')) IN ({','.join('?' for _ in RUNNING_STATUSES)}) THEN 0
ELSE 1
END,
id DESC
LIMIT ?
""",
(*params, *RUNNING_STATUSES, limit),
).fetchall()
con.close()
return [dict(row) for row in rows]
def get_deployment_filter_options():
con = get_connection()
apps = con.execute(
"""
SELECT DISTINCT app_id
FROM deployments
WHERE app_id IS NOT NULL AND app_id != ''
ORDER BY app_id
"""
).fetchall()
sources = con.execute(
"""
SELECT DISTINCT trigger_source
FROM deployments
WHERE trigger_source IS NOT NULL AND trigger_source != ''
ORDER BY trigger_source
"""
).fetchall()
con.close()
return {
"apps": [row["app_id"] for row in apps],
"sources": [row["trigger_source"] for row in sources],
}
def get_deployment_stats():
con = get_connection()
row = con.execute(
f"""
SELECT
COUNT(*) AS total,
SUM(CASE WHEN LOWER(COALESCE(status, '')) IN ({','.join('?' for _ in FAILED_STATUSES)}) THEN 1 ELSE 0 END) AS failed,
SUM(CASE WHEN LOWER(COALESCE(status, '')) IN ({','.join('?' for _ in RUNNING_STATUSES)}) THEN 1 ELSE 0 END) AS running,
SUM(CASE WHEN LOWER(COALESCE(status, '')) IN ({','.join('?' for _ in SUCCESS_STATUSES)}) THEN 1 ELSE 0 END) AS success
FROM deployments
""",
(*FAILED_STATUSES, *RUNNING_STATUSES, *SUCCESS_STATUSES),
).fetchone()
con.close()
stats = dict(row) if row else {"total": 0, "failed": 0, "running": 0, "success": 0}
total = stats.get("total") or 0
success = stats.get("success") or 0
stats["success_rate"] = round((success / total) * 100, 1) if total else 0
return stats
def get_app_deployments(app_id: str, limit: int = 10):
con = get_connection()
rows = con.execute(
"""
SELECT id, app_id, kind, status, started_at, finished_at, returncode
SELECT
id,
app_id,
kind,
status,
started_at,
finished_at,
returncode,
trigger_source,
triggered_by_username,
triggered_by_display_name
FROM deployments
WHERE app_id = ?
ORDER BY id DESC
LIMIT ?
""",
(limit,),
(app_id, limit),
).fetchall()
con.close()
@@ -82,7 +229,21 @@ def get_deployment(deployment_id: int):
row = con.execute(
"""
SELECT id, app_id, kind, status, started_at, finished_at, returncode, stdout, stderr
SELECT
id,
app_id,
kind,
status,
started_at,
finished_at,
returncode,
stdout,
stderr,
trigger_source,
triggered_by_username,
triggered_by_display_name,
commit_author,
pusher
FROM deployments
WHERE id = ?
""",