feat(portal): add app metadata and variables management

This commit is contained in:
JiriUhlir
2026-06-01 13:13:17 +02:00
parent 1ade865df4
commit 994171be1a
4 changed files with 650 additions and 6 deletions
+168 -1
View File
@@ -1,4 +1,5 @@
from app.db.database import get_connection
from app.db.migrations import run_migrations
SUCCESS_STATUSES = ("ok", "success", "succeeded", "done", "deployed", "completed")
@@ -7,6 +8,7 @@ RUNNING_STATUSES = ("running", "pending", "queued", "in_progress", "starting")
def get_apps():
run_migrations()
con = get_connection()
rows = con.execute(
@@ -44,11 +46,32 @@ def get_apps():
def get_app(app_id: str):
run_migrations()
con = get_connection()
row = con.execute(
"""
SELECT id, name, language, version, status, memory, cpus, updated_at
SELECT
id,
name,
language,
version,
status,
memory,
cpus,
updated_at,
description,
owner,
template,
runtime,
repository_url,
repository_name,
default_branch,
domain,
health_url,
container_port,
COALESCE(is_public, 0) AS is_public,
COALESCE(is_enabled, 1) AS is_enabled
FROM apps
WHERE id = ?
""",
@@ -59,7 +82,151 @@ def get_app(app_id: str):
return dict(row) if row else None
def get_app_templates():
run_migrations()
con = get_connection()
rows = con.execute(
"""
SELECT name, runtime, description
FROM app_templates
ORDER BY name
"""
).fetchall()
con.close()
return [dict(row) for row in rows]
def update_app_metadata(app_id: str, metadata: dict):
run_migrations()
con = get_connection()
con.execute(
"""
UPDATE apps
SET name = ?,
description = ?,
owner = ?,
template = ?,
runtime = ?,
repository_url = ?,
repository_name = ?,
default_branch = ?,
domain = ?,
health_url = ?,
container_port = ?,
is_public = ?,
is_enabled = ?,
updated_at = CURRENT_TIMESTAMP
WHERE id = ?
""",
(
metadata.get("name") or None,
metadata.get("description") or None,
metadata.get("owner") or None,
metadata.get("template") or None,
metadata.get("runtime") or None,
metadata.get("repository_url") or None,
metadata.get("repository_name") or None,
metadata.get("default_branch") or None,
metadata.get("domain") or None,
metadata.get("health_url") or None,
metadata.get("container_port"),
1 if metadata.get("is_public") else 0,
1 if metadata.get("is_enabled") else 0,
app_id,
),
)
con.commit()
con.close()
def get_app_variables(app_id: str):
run_migrations()
con = get_connection()
rows = con.execute(
"""
SELECT id, app_id, "key", value, COALESCE(is_secret, 0) AS is_secret
FROM app_variables
WHERE app_id = ?
ORDER BY "key"
""",
(app_id,),
).fetchall()
con.close()
return [dict(row) for row in rows]
def create_app_variable(app_id: str, key: str, value: str, is_secret: bool):
run_migrations()
con = get_connection()
con.execute(
"""
INSERT INTO app_variables (app_id, "key", value, is_secret, created_at, updated_at)
VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
""",
(app_id, key, value, 1 if is_secret else 0),
)
con.commit()
con.close()
def update_app_variable(variable_id: int, app_id: str, key: str, value: str | None, is_secret: bool):
run_migrations()
con = get_connection()
if value is None:
con.execute(
"""
UPDATE app_variables
SET "key" = ?,
is_secret = ?,
updated_at = CURRENT_TIMESTAMP
WHERE id = ? AND app_id = ?
""",
(key, 1 if is_secret else 0, variable_id, app_id),
)
else:
con.execute(
"""
UPDATE app_variables
SET "key" = ?,
value = ?,
is_secret = ?,
updated_at = CURRENT_TIMESTAMP
WHERE id = ? AND app_id = ?
""",
(key, value, 1 if is_secret else 0, variable_id, app_id),
)
con.commit()
con.close()
def delete_app_variable(variable_id: int, app_id: str):
run_migrations()
con = get_connection()
con.execute(
"""
DELETE FROM app_variables
WHERE id = ? AND app_id = ?
""",
(variable_id, app_id),
)
con.commit()
con.close()
def update_app_resources(app_id: str, memory: str, cpus: str):
run_migrations()
con = get_connection()
con.execute(
+58
View File
@@ -66,5 +66,63 @@ def run_migrations():
except Exception:
pass
for statement in (
"ALTER TABLE apps ADD COLUMN description TEXT",
"ALTER TABLE apps ADD COLUMN owner TEXT",
"ALTER TABLE apps ADD COLUMN template TEXT",
"ALTER TABLE apps ADD COLUMN runtime TEXT",
"ALTER TABLE apps ADD COLUMN repository_url TEXT",
"ALTER TABLE apps ADD COLUMN repository_name TEXT",
"ALTER TABLE apps ADD COLUMN default_branch TEXT",
"ALTER TABLE apps ADD COLUMN domain TEXT",
"ALTER TABLE apps ADD COLUMN health_url TEXT",
"ALTER TABLE apps ADD COLUMN container_port INTEGER",
"ALTER TABLE apps ADD COLUMN is_public INTEGER NOT NULL DEFAULT 0",
"ALTER TABLE apps ADD COLUMN is_enabled INTEGER NOT NULL DEFAULT 1",
):
try:
con.execute(statement)
except Exception:
pass
con.execute(
"""
CREATE TABLE IF NOT EXISTS app_templates (
name TEXT PRIMARY KEY,
runtime TEXT,
description TEXT,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
)
"""
)
con.execute(
"""
CREATE TABLE IF NOT EXISTS app_variables (
id INTEGER PRIMARY KEY AUTOINCREMENT,
app_id TEXT NOT NULL,
"key" TEXT NOT NULL,
value TEXT,
is_secret INTEGER NOT NULL DEFAULT 0,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY(app_id) REFERENCES apps(id)
)
"""
)
for statement in (
"ALTER TABLE app_templates ADD COLUMN runtime TEXT",
"ALTER TABLE app_templates ADD COLUMN description TEXT",
"ALTER TABLE app_templates ADD COLUMN created_at TEXT",
"ALTER TABLE app_templates ADD COLUMN updated_at TEXT",
"ALTER TABLE app_variables ADD COLUMN created_at TEXT",
"ALTER TABLE app_variables ADD COLUMN updated_at TEXT",
):
try:
con.execute(statement)
except Exception:
pass
con.execute("CREATE INDEX IF NOT EXISTS idx_app_variables_app_id ON app_variables(app_id)")
con.commit()
con.close()