Co se změnilo:

app_templates je teď jediný source of truth.
Detail služby načítá šablony přes is_enabled = 1.
Vytvoření služby načítá šablony přes is_enabled = 1 AND create_enabled = 1.
Select hodnoty používají app_templates.id, takže fastapi odpovídá existující službě microsoft-365-service.
Při vytvoření služby se z vybrané šablony nastaví template, runtime, language, container_port a health_url.
Neznámá šablona se zobrazí jako Neznámá šablona a detail nespadne.
Hardcoded python-fastapi / seznam šablon byl odstraněn.
This commit is contained in:
JiriUhlir
2026-06-03 09:02:36 +02:00
parent 786d055f6b
commit 54c86702d2
3 changed files with 135 additions and 15 deletions
+42 -11
View File
@@ -19,12 +19,14 @@ from ..db.apps import (
create_app_variable,
delete_app_variable,
get_app,
get_app_template,
get_app_deployments,
get_app_templates,
get_app_variables,
get_apps,
update_app_metadata,
update_app_resources,
update_app_template_metadata,
update_app_variable,
)
from ..db.audit import log_audit_event
@@ -73,9 +75,11 @@ def bool_checked(value) -> str:
return " checked" if value else ""
def render_template_options(templates: list[dict], selected_template: str) -> str:
options = ['<option value="">Bez &scaron;ablony</option>']
def render_template_options(templates: list[dict], selected_template: str, include_blank: bool = True) -> str:
options = ['<option value="">Bez &scaron;ablony</option>'] if include_blank else []
selected_exists = not selected_template
for template in templates:
template_id = template.get("id", "") or ""
name = template.get("name", "") or ""
runtime = template.get("runtime", "") or ""
description = template.get("description", "") or ""
@@ -84,13 +88,28 @@ def render_template_options(templates: list[dict], selected_template: str) -> st
label_parts.append(runtime)
if description:
label_parts.append(description)
selected = " selected" if selected_template == name else ""
selected = " selected" if selected_template == template_id else ""
if selected:
selected_exists = True
options.append(
f'<option value="{html.escape(name)}"{selected}>{html.escape(" - ".join(label_parts))}</option>'
f'<option value="{html.escape(template_id)}"{selected}>{html.escape(" - ".join(label_parts))}</option>'
)
if not selected_exists:
options.append(
f'<option value="{html.escape(selected_template)}" selected>Nezn&aacute;m&aacute; &scaron;ablona</option>'
)
return "".join(options)
def render_template_label(templates: list[dict], template_id: str) -> str:
if not template_id:
return ""
for template in templates:
if template.get("id") == template_id:
return html.escape(template.get("name", "") or template_id)
return "Nezn&aacute;m&aacute; &scaron;ablona"
def diff_metadata(before: dict, after: dict) -> dict:
changes = {}
for field in METADATA_FIELDS:
@@ -404,7 +423,6 @@ def app_detail(app_id: str, request: Request, user=Depends(require_user)):
updated_at = html.escape(app.get("updated_at", "") or "")
description = html.escape(app.get("description", "") or "")
owner = html.escape(app.get("owner", "") or "")
template_value = html.escape(app.get("template", "") or "")
runtime = html.escape(app.get("runtime", "") or "")
repository_url = html.escape(app.get("repository_url", "") or "")
repository_name = html.escape(app.get("repository_name", "") or "")
@@ -416,6 +434,7 @@ def app_detail(app_id: str, request: Request, user=Depends(require_user)):
is_enabled = bool(app.get("is_enabled"))
templates = get_app_templates()
template_options = render_template_options(templates, app.get("template", "") or "")
template_value = render_template_label(templates, app.get("template", "") or "")
variables = get_app_variables(app.get("id", ""))
incidents = get_service_incidents(app.get("id", ""), limit=20)
current_health = get_service_health(app.get("id", ""))
@@ -867,9 +886,10 @@ def redeploy_app(app_id: str, user=Depends(require_user)):
@router.get("/new-app", response_class=HTMLResponse)
def new_app_form(request: Request, user=Depends(require_user)):
template_options = render_template_options(get_app_templates(create_enabled=True), "", include_blank=False)
return page(
"Nová služba",
"""
f"""
<div class="card">
<h2>Vytvořit novou službu</h2>
<p class="muted">Vytvoří Gitea repozitář, webhook, lokální workspace, první commit a nasadí službu.</p>
@@ -887,9 +907,7 @@ def new_app_form(request: Request, user=Depends(require_user)):
<p>
<label>Šablona</label><br>
<select name="template">
<option value="python-fastapi">Python FastAPI</option>
</select>
<select name="template" required>{template_options}</select>
</p>
<button type="submit">Vytvořit službu</button>
@@ -909,10 +927,23 @@ def create_app(
template: str = Form(...),
user=Depends(require_user),
):
if template != "python-fastapi":
selected_template = get_app_template(template, create_enabled=True)
if not selected_template:
return HTMLResponse("Nepodporovaná šablona", status_code=400)
create_result = run_command([NEW_APP_SCRIPT, app_id, app_name])
if create_result.returncode == 0:
update_app_template_metadata(
app_id,
{
"name": app_name,
"template": selected_template.get("id"),
"runtime": selected_template.get("runtime"),
"language": selected_template.get("language"),
"health_url": selected_template.get("default_health_path"),
"container_port": selected_template.get("default_port"),
},
)
deploy_result = run_command([DEPLOY_SCRIPT, app_id])
status = "OK" if create_result.returncode == 0 and deploy_result.returncode == 0 else "FAILED"
@@ -924,7 +955,7 @@ def create_app(
metadata={
"app_id": app_id,
"app_name": app_name,
"template": template,
"template": selected_template.get("id"),
"status": status,
"create_returncode": create_result.returncode,
"deploy_returncode": deploy_result.returncode,