Implementována portálová část SQLite job queue.
Přidán DB helper pro jobs a job_logs bez ORM.
Přidána idempotentní migrace pro job tabulky včetně created_by_display_name.
Přidány stránky /portal/jobs a /portal/jobs/{id}.
Jobs page zobrazuje status, type, target, source, created_by, created_at, started_at, finished_at.
Job detail zobrazuje payload, result/error a job_logs.
Queued/running joby mají auto-refresh po 5 s.
Navigace portálu obsahuje odkaz na Joby.
App redeploy už nespouští deploy script přímo; vytváří queued job deploy_app s prázdným payloadem.
Po redeploy se uživatel přesměruje na detail jobu.
Přidán audit event app.redeploy.queued s metadata={"job_id": job_id}.
Přidána ochrana proti duplicitnímu aktivnímu deploy jobu pro stejnou appku.
This commit is contained in:
+16
-16
@@ -16,8 +16,9 @@ from ..config import (
|
||||
)
|
||||
from ..db.apps import get_app, get_app_deployments, get_apps, update_app_resources
|
||||
from ..db.audit import log_audit_event
|
||||
from ..db.jobs import create_job, has_active_deploy_job
|
||||
from ..routes.deployments import render_status_pill
|
||||
from ..shell import run_command, run_command_background
|
||||
from ..shell import run_command
|
||||
from ..templates.layout import page, render_result
|
||||
|
||||
router = APIRouter()
|
||||
@@ -250,28 +251,27 @@ def redeploy_app(app_id: str, user=Depends(require_user)):
|
||||
if not app:
|
||||
raise HTTPException(status_code=404, detail="App not found")
|
||||
|
||||
process = run_command_background(
|
||||
[DEPLOY_SCRIPT, app_id],
|
||||
extra_env={
|
||||
"APPFACTORY_TRIGGER_SOURCE": "portal",
|
||||
"APPFACTORY_TRIGGERED_BY_USER_ID": user.get("id"),
|
||||
"APPFACTORY_TRIGGERED_BY_USERNAME": user.get("username"),
|
||||
"APPFACTORY_TRIGGERED_BY_DISPLAY_NAME": user.get("display_name") or user.get("username"),
|
||||
},
|
||||
active_job = has_active_deploy_job("app", app_id)
|
||||
if active_job:
|
||||
return RedirectResponse(url=f"/portal/jobs/{active_job['id']}", status_code=303)
|
||||
|
||||
job_id = create_job(
|
||||
job_type="deploy_app",
|
||||
target_type="app",
|
||||
target_id=app_id,
|
||||
payload={},
|
||||
user=user,
|
||||
source="portal",
|
||||
)
|
||||
log_audit_event(
|
||||
user,
|
||||
action="app.redeploy",
|
||||
action="app.redeploy.queued",
|
||||
target_type="app",
|
||||
target_id=app_id,
|
||||
metadata={
|
||||
"app_id": app_id,
|
||||
"pid": process.pid,
|
||||
"trigger_source": "portal",
|
||||
},
|
||||
metadata={"job_id": job_id},
|
||||
)
|
||||
|
||||
return RedirectResponse(url=f"/portal/apps/{quote(app_id, safe='')}", status_code=303)
|
||||
return RedirectResponse(url=f"/portal/jobs/{job_id}", status_code=303)
|
||||
|
||||
|
||||
@router.get("/new-app", response_class=HTMLResponse)
|
||||
|
||||
Reference in New Issue
Block a user