-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdev.sh
More file actions
executable file
·187 lines (169 loc) · 7.1 KB
/
dev.sh
File metadata and controls
executable file
·187 lines (169 loc) · 7.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#!/usr/bin/env bash
# platform/scripts/dev.sh — Universeller lokaler Dev-Server-Starter
#
# Usage: dev.sh <repo-name> # z.B. dev.sh writing-hub
# dev.sh <repo-name> --check # Nur Konfiguration prüfen, nicht starten
#
# Port: aus platform/infra/ports.yaml (dev: XXXX)
# Settings: automatisch erkannt aus dem Repo
# venv: automatisch erkannt (.venv, venv, system python3)
# Secrets: <repo>/.env.dev wird automatisch gesourcet (gitignored)
#
# Funktioniert für ALLE Repos — kein manuelles Pflegen nötig.
# Voraussetzung: pyyaml (pip3 install pyyaml)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PLATFORM_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
PORTS_YAML="$PLATFORM_DIR/infra/ports.yaml"
REPOS_BASE="$(cd "$PLATFORM_DIR/.." && pwd)"
REPO="${1:-}"
CHECK_ONLY="${2:-}"
# --- Usage / Liste aller Repos ---
if [[ -z "$REPO" ]]; then
echo "Usage: dev.sh <repo-name> [--check]"
echo ""
echo "Alle Repos in ports.yaml (dev-Port):"
PORTS_YAML_PATH="$PORTS_YAML" python3 - <<'PYEOF'
import yaml, os
data = yaml.safe_load(open(os.environ["PORTS_YAML_PATH"]))
for name, svc in sorted(data.get("services", {}).items(), key=lambda x: x[1].get("dev", 9999)):
port = svc.get("dev", "?")
print(f" {name:<25} port={port}")
PYEOF
exit 1
fi
REPO_DIR="$REPOS_BASE/$REPO"
if [[ ! -d "$REPO_DIR" ]]; then
echo "FEHLER: Verzeichnis nicht gefunden: $REPO_DIR"
exit 1
fi
# ── 1. Port aus ports.yaml ────────────────────────────────────────────────────
DEV_PORT="$(python3 - "$REPO" "$PORTS_YAML" <<'PYEOF'
import sys, yaml
repo, ports_file = sys.argv[1], sys.argv[2]
data = yaml.safe_load(open(ports_file))
svc = data.get("services", {}).get(repo)
if not svc:
print(f"MISSING", end="")
sys.exit(0)
print(svc.get("dev", "8000"), end="")
PYEOF
)"
if [[ "$DEV_PORT" == "MISSING" ]]; then
echo "WARNUNG: '$REPO' nicht in ports.yaml — nutze Port 8000 als Fallback"
DEV_PORT="8000"
fi
# ── 2. manage.py Verzeichnis auto-erkennen ────────────────────────────────────
MANAGE_DIR=""
for candidate in "$REPO_DIR" "$REPO_DIR/src" "$REPO_DIR/app"; do
if [[ -f "$candidate/manage.py" ]]; then
MANAGE_DIR="$candidate"
break
fi
done
# Tiefergehend suchen wenn nötig
if [[ -z "$MANAGE_DIR" ]]; then
FOUND="$(find "$REPO_DIR" -maxdepth 3 -name "manage.py" \
! -path "*/.venv/*" ! -path "*/.claude/*" ! -path "*/node_modules/*" \
-print -quit 2>/dev/null || true)"
if [[ -n "$FOUND" ]]; then
MANAGE_DIR="$(dirname "$FOUND")"
fi
fi
if [[ -z "$MANAGE_DIR" ]]; then
echo "FEHLER: manage.py nicht gefunden in $REPO_DIR"
exit 1
fi
# ── 3. Settings-Modul auto-erkennen ──────────────────────────────────────────
detect_settings() {
local base="$1"
# Bevorzuge development.py falls vorhanden
for try_base in "$base" "$base/src"; do
if [[ -f "$try_base/config/settings/development.py" ]]; then
echo "config.settings.development"; return
fi
if [[ -f "$try_base/config/settings/local.py" ]]; then
echo "config.settings.local"; return
fi
if [[ -f "$try_base/config/settings/base.py" ]]; then
echo "config.settings.base"; return
fi
if [[ -f "$try_base/config/settings.py" ]]; then
echo "config.settings"; return
fi
done
# Non-standard: suche settings.py irgendwo im Repo
local found
found="$(find "$base" -maxdepth 5 -name "settings.py" \
! -path "*/.venv/*" ! -path "*/.claude/*" ! -path "*/test*" \
-print -quit 2>/dev/null || true)"
if [[ -n "$found" ]]; then
# Konvertiere Pfad → Python-Modul relativ zu MANAGE_DIR
local rel
rel="${found#$MANAGE_DIR/}"
rel="${rel%.py}"
rel="${rel//\//.}"
echo "$rel"; return
fi
echo "config.settings"
}
if [[ -z "${DJANGO_SETTINGS_MODULE:-}" ]]; then
DJANGO_SETTINGS_MODULE="$(detect_settings "$REPO_DIR")"
fi
# ── 4. Python / venv auto-erkennen ───────────────────────────────────────────
PYTHON="python3"
for venv_candidate in ".venv" "venv" ".virtualenv"; do
if [[ -f "$REPO_DIR/$venv_candidate/bin/python" ]]; then
PYTHON="$REPO_DIR/$venv_candidate/bin/python"
break
fi
done
# ── 5. .env.dev sourcen (Secrets) ────────────────────────────────────────────
ENV_LOADED=""
for env_file in "$REPO_DIR/.env.dev" "$REPO_DIR/.env"; do
if [[ -f "$env_file" ]]; then
set -a
# shellcheck disable=SC1090
source "$env_file"
set +a
ENV_LOADED="$(basename "$env_file")"
break
fi
done
export DJANGO_SETTINGS_MODULE
# ── Ausgabe ───────────────────────────────────────────────────────────────────
echo ""
echo "╔══════════════════════════════════════════════════════════╗"
printf "║ 🚀 %-52s ║\n" "$REPO"
printf "║ %-52s ║\n" "URL: http://127.0.0.1:$DEV_PORT"
printf "║ %-52s ║\n" "Settings: $DJANGO_SETTINGS_MODULE"
printf "║ %-52s ║\n" "Python: $PYTHON"
printf "║ %-52s ║\n" "Dir: $MANAGE_DIR"
[[ -n "$ENV_LOADED" ]] && printf "║ %-52s ║\n" "Env: $ENV_LOADED geladen"
echo "╚══════════════════════════════════════════════════════════╝"
echo ""
if [[ "$CHECK_ONLY" == "--check" ]]; then
echo " (--check: kein Start)"
exit 0
fi
cd "$MANAGE_DIR"
# Schema-per-Tenant (django_tenants): die Dev-DB muss migriert UND ein Tenant
# geseedet sein, sonst 500t die TenantMainMiddleware bei jedem Request
# (relation "tenants_domain" does not exist). Vorgabe: platform:ADR-219.
#
# WICHTIG: Erkennung am django_tenants-DB-Backend (ENGINE), NICHT an TENANT_MODEL.
# TENANT_MODEL haben auch row-level/RLS-Repos (z. B. dev-hub core.Organization,
# risk-hub tenancy.Organization) — die nutzen `django.db.backends.postgresql`,
# haben KEIN migrate_schemas und dürfen hier NICHT getriggert werden.
if grep -rqsE 'django_tenants\.postgresql_backend' config/ 2>/dev/null; then
echo "🏢 Schema-per-Tenant (django_tenants) → migrate_schemas --shared + seed_public_tenant"
"$PYTHON" manage.py migrate_schemas --shared --noinput \
|| { echo "✗ migrate_schemas fehlgeschlagen — Bring-up abgebrochen"; exit 1; }
if "$PYTHON" manage.py help seed_public_tenant >/dev/null 2>&1; then
"$PYTHON" manage.py seed_public_tenant
else
echo "⚠️ Kein seed_public_tenant-Command in diesem Repo — laut platform:ADR-219 Pflicht."
echo " Ohne Public-Tenant + Domain 500t runserver. Command anlegen (Vorbild: travel-beat)."
fi
fi
exec "$PYTHON" manage.py runserver "127.0.0.1:$DEV_PORT"