143 lines
4.8 KiB
Python
143 lines
4.8 KiB
Python
import html
|
|
|
|
from fastapi import APIRouter, HTTPException
|
|
from fastapi.responses import HTMLResponse
|
|
|
|
from app.db.apps import get_deployment, get_deployments
|
|
from app.templates.layout import page
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
def render_status_pill(status: str | None) -> str:
|
|
status_value = status or ""
|
|
normalized = status_value.strip().lower()
|
|
|
|
if normalized in {"ok", "success", "succeeded", "done", "deployed", "completed"}:
|
|
class_name = "pill pill-success"
|
|
elif normalized in {"running", "pending", "queued", "in_progress", "starting"}:
|
|
class_name = "pill pill-warning"
|
|
elif normalized in {"failed", "failure", "error", "cancelled", "canceled"}:
|
|
class_name = "pill pill-danger"
|
|
else:
|
|
class_name = "pill pill-muted"
|
|
|
|
return f'<span class="{class_name}">{html.escape(status_value)}</span>'
|
|
|
|
|
|
@router.get("/deployments", response_class=HTMLResponse)
|
|
async def deployments_page():
|
|
deployments = get_deployments()
|
|
|
|
rows = ""
|
|
for deployment in deployments:
|
|
deployment_id = html.escape(str(deployment.get("id", "")))
|
|
app_id = html.escape(deployment.get("app_id", "") or "")
|
|
kind = html.escape(deployment.get("kind", "") or "")
|
|
status = render_status_pill(deployment.get("status"))
|
|
started_at = html.escape(deployment.get("started_at", "") or "")
|
|
finished_at = html.escape(deployment.get("finished_at", "") or "")
|
|
returncode = deployment.get("returncode")
|
|
returncode_label = "" if returncode is None else html.escape(str(returncode))
|
|
|
|
rows += f"""
|
|
<tr>
|
|
<td>
|
|
<strong>#{deployment_id}</strong><br>
|
|
<span class="muted">{started_at}</span>
|
|
</td>
|
|
<td>{app_id}</td>
|
|
<td>{kind}</td>
|
|
<td>{status}</td>
|
|
<td>{returncode_label}</td>
|
|
<td>{finished_at}</td>
|
|
<td class="actions-cell">
|
|
<a class="btn" href="/portal/deployments/{deployment_id}">Detail</a>
|
|
</td>
|
|
</tr>
|
|
"""
|
|
|
|
if not rows:
|
|
rows = '<tr><td colspan="7">Zatím nejsou evidovaná žádná nasazení.</td></tr>'
|
|
|
|
return page(
|
|
"Nasazení",
|
|
f"""
|
|
<div class="card">
|
|
<h2>Historie nasazení</h2>
|
|
<p class="muted">Přehled posledních běhů nasazení a jejich výsledků.</p>
|
|
<a class="btn" href="/portal">← Zpět na portál</a>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h2>Nasazení</h2>
|
|
<table>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>Aplikace</th>
|
|
<th>Typ</th>
|
|
<th>Status</th>
|
|
<th>Kód</th>
|
|
<th>Dokončeno</th>
|
|
<th>Akce</th>
|
|
</tr>
|
|
{rows}
|
|
</table>
|
|
</div>
|
|
""",
|
|
)
|
|
|
|
|
|
@router.get("/deployments/{deployment_id}", response_class=HTMLResponse)
|
|
async def deployment_detail_page(
|
|
deployment_id: int,
|
|
):
|
|
deployment = get_deployment(deployment_id)
|
|
|
|
if not deployment:
|
|
raise HTTPException(status_code=404, detail="Deployment not found")
|
|
|
|
title = f"Nasazení #{html.escape(str(deployment.get('id', deployment_id)))}"
|
|
app_id = html.escape(deployment.get("app_id", "") or "")
|
|
kind = html.escape(deployment.get("kind", "") or "")
|
|
status = render_status_pill(deployment.get("status"))
|
|
started_at = html.escape(deployment.get("started_at", "") or "")
|
|
finished_at = html.escape(deployment.get("finished_at", "") or "")
|
|
returncode = deployment.get("returncode")
|
|
returncode_label = "" if returncode is None else html.escape(str(returncode))
|
|
stdout = html.escape(deployment.get("stdout", "") or "")
|
|
stderr = html.escape(deployment.get("stderr", "") or "")
|
|
|
|
return page(
|
|
title,
|
|
f"""
|
|
<div class="card">
|
|
<h2>{title}</h2>
|
|
<p class="muted">Detail běhu nasazení včetně výstupu procesu.</p>
|
|
<p>
|
|
<a class="btn" href="/portal/deployments">← Zpět na nasazení</a>
|
|
<a class="btn btn-secondary" href="/portal">Zpět na portál</a>
|
|
</p>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h2>Souhrn</h2>
|
|
<table>
|
|
<tr><th>Aplikace</th><td>{app_id}</td></tr>
|
|
<tr><th>Typ</th><td>{kind}</td></tr>
|
|
<tr><th>Status</th><td>{status}</td></tr>
|
|
<tr><th>Návratový kód</th><td>{returncode_label}</td></tr>
|
|
<tr><th>Spuštěno</th><td>{started_at}</td></tr>
|
|
<tr><th>Dokončeno</th><td>{finished_at}</td></tr>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h2>Výstup</h2>
|
|
<pre>{stdout}</pre>
|
|
<h2>Chyba</h2>
|
|
<pre>{stderr}</pre>
|
|
</div>
|
|
""",
|
|
)
|