Add app metadata database migration
This commit is contained in:
Executable
+161
@@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
DB_FILE="/opt/appfactory/data/appfactory/appfactory.db"
|
||||
|
||||
if [ ! -f "$DB_FILE" ]; then
|
||||
echo "Missing database: $DB_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
python3 - "$DB_FILE" <<'PY'
|
||||
import sqlite3
|
||||
import sys
|
||||
|
||||
db_file = sys.argv[1]
|
||||
con = sqlite3.connect(db_file)
|
||||
|
||||
columns = [row[1] for row in con.execute("PRAGMA table_info(apps)").fetchall()]
|
||||
|
||||
def add_column(name: str, definition: str):
|
||||
if name not in columns:
|
||||
con.execute(f"ALTER TABLE apps ADD COLUMN {name} {definition}")
|
||||
|
||||
add_column("description", "TEXT")
|
||||
add_column("owner", "TEXT")
|
||||
add_column("template", "TEXT")
|
||||
add_column("runtime", "TEXT")
|
||||
add_column("repository_url", "TEXT")
|
||||
add_column("repository_name", "TEXT")
|
||||
add_column("default_branch", "TEXT NOT NULL DEFAULT 'main'")
|
||||
add_column("domain", "TEXT")
|
||||
add_column("health_url", "TEXT")
|
||||
add_column("container_port", "INTEGER")
|
||||
add_column("is_public", "INTEGER NOT NULL DEFAULT 1")
|
||||
add_column("is_enabled", "INTEGER NOT NULL DEFAULT 1")
|
||||
|
||||
con.execute("""
|
||||
CREATE TABLE IF NOT EXISTS app_templates (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
runtime TEXT NOT NULL,
|
||||
language TEXT NOT NULL,
|
||||
description TEXT,
|
||||
default_port INTEGER,
|
||||
default_health_path TEXT NOT NULL DEFAULT '/health',
|
||||
is_enabled INTEGER NOT NULL DEFAULT 1,
|
||||
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,
|
||||
UNIQUE(app_id, key)
|
||||
)
|
||||
""")
|
||||
|
||||
con.execute("""
|
||||
CREATE INDEX IF NOT EXISTS idx_app_variables_app_id
|
||||
ON app_variables(app_id)
|
||||
""")
|
||||
|
||||
templates = [
|
||||
(
|
||||
"fastapi",
|
||||
"FastAPI",
|
||||
"python",
|
||||
"python",
|
||||
"Python FastAPI service",
|
||||
8000,
|
||||
"/health",
|
||||
),
|
||||
(
|
||||
"dotnet-api",
|
||||
".NET API",
|
||||
"dotnet",
|
||||
"csharp",
|
||||
".NET Web API service",
|
||||
8080,
|
||||
"/health",
|
||||
),
|
||||
(
|
||||
"dotnet-worker",
|
||||
".NET Worker",
|
||||
"dotnet",
|
||||
"csharp",
|
||||
".NET background worker service",
|
||||
None,
|
||||
"/health",
|
||||
),
|
||||
(
|
||||
"nodejs-ts",
|
||||
"Node.js TypeScript",
|
||||
"node",
|
||||
"typescript",
|
||||
"Node.js service written in TypeScript",
|
||||
3000,
|
||||
"/health",
|
||||
),
|
||||
(
|
||||
"static-site",
|
||||
"Static Site",
|
||||
"static",
|
||||
"html",
|
||||
"Static website served by gateway",
|
||||
80,
|
||||
"/",
|
||||
),
|
||||
]
|
||||
|
||||
con.executemany(
|
||||
"""
|
||||
INSERT INTO app_templates (
|
||||
id,
|
||||
name,
|
||||
runtime,
|
||||
language,
|
||||
description,
|
||||
default_port,
|
||||
default_health_path
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(id) DO UPDATE SET
|
||||
name = excluded.name,
|
||||
runtime = excluded.runtime,
|
||||
language = excluded.language,
|
||||
description = excluded.description,
|
||||
default_port = excluded.default_port,
|
||||
default_health_path = excluded.default_health_path,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
""",
|
||||
templates,
|
||||
)
|
||||
|
||||
con.execute("""
|
||||
UPDATE apps
|
||||
SET
|
||||
runtime = COALESCE(runtime, language),
|
||||
template = COALESCE(template, CASE
|
||||
WHEN language = 'python' THEN 'fastapi'
|
||||
ELSE language
|
||||
END),
|
||||
repository_name = COALESCE(repository_name, id),
|
||||
health_url = COALESCE(health_url, '/health'),
|
||||
container_port = COALESCE(container_port, 8000),
|
||||
is_public = COALESCE(is_public, 1),
|
||||
is_enabled = COALESCE(is_enabled, 1)
|
||||
""")
|
||||
|
||||
con.commit()
|
||||
con.close()
|
||||
|
||||
print("App metadata migration completed.")
|
||||
PY
|
||||
Reference in New Issue
Block a user