diff --git a/scripts/deploy-app.sh b/scripts/deploy-app.sh index 05cc85a..c8440eb 100755 --- a/scripts/deploy-app.sh +++ b/scripts/deploy-app.sh @@ -17,6 +17,8 @@ mkdir -p "$DOCKER_CONFIG" DB_FILE="/opt/appfactory/data/appfactory/appfactory.db" APP_SOURCE_DIR="$WORKSPACE_DIR/$APP_ID" TOOLS_DIR="$WORKSPACE_DIR/appfactory-tools" +APP_DATA_DIR="$APPFACTORY_DIR/data/apps/$APP_ID" +APP_ENV_FILE="$APP_DATA_DIR/.env" TRIGGER_SOURCE="${APPFACTORY_TRIGGER_SOURCE:-cli}" TRIGGERED_BY_USER_ID="${APPFACTORY_TRIGGERED_BY_USER_ID:-}" @@ -179,6 +181,73 @@ fi RESULT=$? +if [ "$RESULT" -eq 0 ]; then + run_step "Generating app environment file" bash -c " +mkdir -p '$APP_DATA_DIR' + +python3 - '$DB_FILE' '$APP_ID' '$APP_ENV_FILE' <<'PY' +import os +import re +import sqlite3 +import sys +from pathlib import Path + +db_file = sys.argv[1] +app_id = sys.argv[2] +env_file = Path(sys.argv[3]) + +key_pattern = re.compile(r'^[A-Za-z_][A-Za-z0-9_]*$') + +con = sqlite3.connect(db_file) +con.row_factory = sqlite3.Row + +rows = con.execute( + ''' + SELECT key, value, is_secret, required + FROM app_variables + WHERE app_id = ? + ORDER BY key + ''', + (app_id,), +).fetchall() + +missing_required = [] + +lines = [ + '# Generated by AppFactory. Do not edit manually.', + f'APP_ID={app_id}', +] + +for row in rows: + key = row['key'] + value = row['value'] or '' + required = int(row['required'] or 0) + + if not key_pattern.match(key): + raise SystemExit(f'Invalid environment variable key: {key}') + + if required and value == '': + missing_required.append(key) + + escaped = value.replace('\\\\', '\\\\\\\\').replace('\"', '\\\\\"').replace('\\n', '\\\\n') + lines.append(f'{key}=\"{escaped}\"') + +if missing_required: + raise SystemExit('Missing required variables: ' + ', '.join(missing_required)) + +env_file.parent.mkdir(parents=True, exist_ok=True) +env_file.write_text('\\n'.join(lines) + '\\n', encoding='utf-8') +os.chmod(env_file, 0o600) + +con.close() +PY + +echo 'Generated env file: $APP_ENV_FILE' +" + + RESULT=$? +fi + if [ "$RESULT" -eq 0 ]; then run_step "Building Docker image" \ docker build --pull --no-cache \ diff --git a/scripts/generate-apps-compose.sh b/scripts/generate-apps-compose.sh index 73f3ff7..6a2d4fa 100755 --- a/scripts/generate-apps-compose.sh +++ b/scripts/generate-apps-compose.sh @@ -11,11 +11,13 @@ cat > "$COMPOSE_FILE" <<'EOF_COMPOSE' services: EOF_COMPOSE -python3 - "$CATALOG_FILE" "$COMPOSE_FILE" <<'PY' +python3 - "$CATALOG_FILE" "$COMPOSE_FILE" "$APPFACTORY_DIR" <<'PY' import sys +from pathlib import Path catalog_file = sys.argv[1] compose_file = sys.argv[2] +appfactory_dir = sys.argv[3] apps = [] current = None @@ -41,11 +43,14 @@ with open(compose_file, "a", encoding="utf-8") as f: app_id = app["id"] memory = app.get("memory", "") cpus = app.get("cpus", "") + env_file = f"{appfactory_dir}/data/apps/{app_id}/.env" f.write(f" {app_id}:\n") f.write(f" image: {app_id}:latest\n") f.write(f" container_name: {app_id}\n") f.write(" restart: unless-stopped\n") + f.write(" env_file:\n") + f.write(f" - {env_file}\n") if memory: f.write(f" mem_limit: {memory}\n")