|
| 1 | +#!/usr/bin/env bash |
| 2 | +set -euo pipefail |
| 3 | + |
| 4 | +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
| 5 | +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" |
| 6 | +SUITE_ROOT="$(cd "$REPO_ROOT/.." && pwd)" |
| 7 | + |
| 8 | +DEMO_HOST="${ORCHIVISTE_DEMO_HOST:-127.0.0.1}" |
| 9 | +DEMO_PORT="${ORCHIVISTE_DEMO_PORT:-28780}" |
| 10 | +BASE_URL="http://${DEMO_HOST}:${DEMO_PORT}" |
| 11 | + |
| 12 | +RUNTIME_ROOT="${ORCHIVISTE_DEMO_RUNTIME_DIR:-$REPO_ROOT/runtime/demo-local}" |
| 13 | +LOG_DIR="$RUNTIME_ROOT/logs" |
| 14 | +REQUEST_DIR="$RUNTIME_ROOT/requests" |
| 15 | +RESULT_DIR="$RUNTIME_ROOT/results" |
| 16 | +PID_FILE="$RUNTIME_ROOT/orchiviste-api.pid" |
| 17 | +API_LOG_FILE="$LOG_DIR/orchiviste-api.log" |
| 18 | +SQLITE_PATH="${ORCHIVISTE_DEMO_SQLITE_PATH:-$RUNTIME_ROOT/orchiviste-demo.sqlite}" |
| 19 | +COCKPIT_CONFIG_FILE="${ORCHIVISTE_DEMO_CONFIG_FILE:-$REPO_ROOT/OrchivisteAPI/configs/cockpit/demo.local.json}" |
| 20 | +FIXTURE_FILE="${ORCHIVISTE_DEMO_FIXTURE:-$REPO_ROOT/fixtures/demo/cockpit/input_document.txt}" |
| 21 | + |
| 22 | +MUNI_ANALYSE_DIR="${MUNI_ANALYSE_DIR:-$SUITE_ROOT/MuniAnalyse}" |
| 23 | +MUNI_METADONNEES_DIR="${MUNI_METADONNEES_DIR:-$SUITE_ROOT/MuniMetadonnees}" |
| 24 | +MUNI_PRECLASSEMENT_DIR="${MUNI_PRECLASSEMENT_DIR:-$SUITE_ROOT/MuniPreclassement}" |
| 25 | +MUNI_CONTROLE_DIR="${MUNI_CONTROLE_DIR:-$SUITE_ROOT/MuniControle}" |
| 26 | + |
| 27 | +need_cmd() { |
| 28 | + local cmd="$1" |
| 29 | + if ! command -v "$cmd" >/dev/null 2>&1; then |
| 30 | + echo "ECHEC: commande requise manquante: $cmd" >&2 |
| 31 | + exit 1 |
| 32 | + fi |
| 33 | +} |
| 34 | + |
| 35 | +need_file() { |
| 36 | + local path="$1" |
| 37 | + local label="$2" |
| 38 | + if [[ ! -f "$path" ]]; then |
| 39 | + echo "ECHEC: $label introuvable: $path" >&2 |
| 40 | + exit 1 |
| 41 | + fi |
| 42 | +} |
| 43 | + |
| 44 | +need_dir() { |
| 45 | + local path="$1" |
| 46 | + local label="$2" |
| 47 | + if [[ ! -d "$path" ]]; then |
| 48 | + echo "ECHEC: $label introuvable: $path" >&2 |
| 49 | + exit 1 |
| 50 | + fi |
| 51 | +} |
| 52 | + |
| 53 | +require_prereqs() { |
| 54 | + need_cmd swift |
| 55 | + need_cmd curl |
| 56 | + need_cmd python3 |
| 57 | + need_file "$COCKPIT_CONFIG_FILE" "configuration cockpit demo" |
| 58 | + need_file "$FIXTURE_FILE" "fixture demo" |
| 59 | + need_dir "$MUNI_ANALYSE_DIR" "repo MuniAnalyse" |
| 60 | + need_dir "$MUNI_METADONNEES_DIR" "repo MuniMetadonnees" |
| 61 | + need_dir "$MUNI_PRECLASSEMENT_DIR" "repo MuniPreclassement" |
| 62 | + need_dir "$MUNI_CONTROLE_DIR" "repo MuniControle" |
| 63 | +} |
| 64 | + |
| 65 | +is_running() { |
| 66 | + if [[ ! -f "$PID_FILE" ]]; then |
| 67 | + return 1 |
| 68 | + fi |
| 69 | + local pid |
| 70 | + pid="$(cat "$PID_FILE" 2>/dev/null || true)" |
| 71 | + [[ -n "$pid" ]] || return 1 |
| 72 | + kill -0 "$pid" >/dev/null 2>&1 |
| 73 | +} |
| 74 | + |
| 75 | +wait_health() { |
| 76 | + local attempts=60 |
| 77 | + while (( attempts > 0 )); do |
| 78 | + if curl -sS "$BASE_URL/v1/health" >/dev/null 2>&1; then |
| 79 | + return 0 |
| 80 | + fi |
| 81 | + sleep 1 |
| 82 | + attempts=$((attempts - 1)) |
| 83 | + done |
| 84 | + return 1 |
| 85 | +} |
| 86 | + |
| 87 | +ensure_api_reachable() { |
| 88 | + if ! curl -sS "$BASE_URL/v1/health" >/dev/null 2>&1; then |
| 89 | + echo "ECHEC: API indisponible sur $BASE_URL. Lance d'abord: scripts/demo_local_cockpit.sh start" >&2 |
| 90 | + exit 1 |
| 91 | + fi |
| 92 | +} |
| 93 | + |
| 94 | +build_demo_binaries() { |
| 95 | + echo "== Build OrchivisteAPI ==" |
| 96 | + (cd "$REPO_ROOT/OrchivisteAPI" && swift build -c debug --product OrchivisteAPI) |
| 97 | + |
| 98 | + echo "== Build outils actifs (Muni) ==" |
| 99 | + (cd "$MUNI_ANALYSE_DIR" && swift build -c debug --product muni-analyse-cli) |
| 100 | + (cd "$MUNI_METADONNEES_DIR" && swift build -c debug --product muni-metadonnees-cli) |
| 101 | + (cd "$MUNI_PRECLASSEMENT_DIR" && swift build -c debug --product muni-preclassement-cli) |
| 102 | + (cd "$MUNI_CONTROLE_DIR" && swift build -c debug --product muni-controle-cli) |
| 103 | +} |
| 104 | + |
| 105 | +cmd_start() { |
| 106 | + require_prereqs |
| 107 | + |
| 108 | + if is_running; then |
| 109 | + echo "OrchivisteAPI est deja en cours (PID $(cat "$PID_FILE"))." |
| 110 | + echo "URL: $BASE_URL/ui/cockpit" |
| 111 | + exit 0 |
| 112 | + fi |
| 113 | + |
| 114 | + mkdir -p "$LOG_DIR" "$REQUEST_DIR" "$RESULT_DIR" |
| 115 | + |
| 116 | + if [[ "${SKIP_BUILD:-0}" != "1" ]]; then |
| 117 | + build_demo_binaries |
| 118 | + fi |
| 119 | + |
| 120 | + echo "== Demarrage OrchivisteAPI (sans Docker) ==" |
| 121 | + local pid |
| 122 | + pushd "$REPO_ROOT/OrchivisteAPI" >/dev/null |
| 123 | + nohup env \ |
| 124 | + ORCHIVISTE_API_HOST="$DEMO_HOST" \ |
| 125 | + ORCHIVISTE_API_PORT="$DEMO_PORT" \ |
| 126 | + ORCHIVISTE_AUTO_MIGRATE=1 \ |
| 127 | + ORCHIVISTE_SQLITE_PATH="$SQLITE_PATH" \ |
| 128 | + ORCHIVISTE_COCKPIT_CONFIG_FILE="$COCKPIT_CONFIG_FILE" \ |
| 129 | + ./.build/debug/OrchivisteAPI \ |
| 130 | + >"$API_LOG_FILE" 2>&1 < /dev/null & |
| 131 | + pid="$!" |
| 132 | + popd >/dev/null |
| 133 | + |
| 134 | + if [[ -z "$pid" ]]; then |
| 135 | + echo "ECHEC: impossible de recuperer le PID OrchivisteAPI." >&2 |
| 136 | + [[ -f "$API_LOG_FILE" ]] && tail -n 80 "$API_LOG_FILE" >&2 |
| 137 | + exit 1 |
| 138 | + fi |
| 139 | + echo "$pid" > "$PID_FILE" |
| 140 | + |
| 141 | + if ! wait_health; then |
| 142 | + echo "ECHEC: API non prete sur $BASE_URL (voir $API_LOG_FILE)" >&2 |
| 143 | + cmd_stop >/dev/null 2>&1 || true |
| 144 | + exit 1 |
| 145 | + fi |
| 146 | + |
| 147 | + echo "API prete." |
| 148 | + echo "- URL cockpit: $BASE_URL/ui/cockpit" |
| 149 | + echo "- URL catalogue API: $BASE_URL/v1/cockpit/tools" |
| 150 | + echo "- PID file: $PID_FILE" |
| 151 | + echo "- Log API: $API_LOG_FILE" |
| 152 | + echo "- SQLite: $SQLITE_PATH" |
| 153 | + echo "- Runtime cockpit: $REPO_ROOT/runtime/demo-local/cockpit" |
| 154 | +} |
| 155 | + |
| 156 | +cmd_catalog() { |
| 157 | + require_prereqs |
| 158 | + ensure_api_reachable |
| 159 | + local out="$RESULT_DIR/catalog.tools.json" |
| 160 | + mkdir -p "$RESULT_DIR" |
| 161 | + curl -sS "$BASE_URL/v1/cockpit/tools" > "$out" |
| 162 | + python3 - <<'PY' "$out" |
| 163 | +import json, sys |
| 164 | +with open(sys.argv[1], 'r', encoding='utf-8') as f: |
| 165 | + tools = json.load(f) |
| 166 | +print("Catalogue outils:") |
| 167 | +for item in tools: |
| 168 | + d = item.get("descriptor", {}) |
| 169 | + print(f"- {d.get('id')} v{d.get('version')} status={d.get('integration_status')} available={item.get('is_available')}") |
| 170 | +PY |
| 171 | + echo "JSON complet: $out" |
| 172 | +} |
| 173 | + |
| 174 | +cmd_sample_run() { |
| 175 | + require_prereqs |
| 176 | + ensure_api_reachable |
| 177 | + mkdir -p "$REQUEST_DIR" "$RESULT_DIR" |
| 178 | + |
| 179 | + local payload="$REQUEST_DIR/demo-run-muni-analyse.payload.json" |
| 180 | + local response="$RESULT_DIR/demo-run-muni-analyse.response.json" |
| 181 | + local report_path="$RESULT_DIR/demo-run-muni-analyse.report.json" |
| 182 | + |
| 183 | + cat > "$payload" <<JSON |
| 184 | +{ |
| 185 | + "tool_id": "MuniAnalyse", |
| 186 | + "action": "run", |
| 187 | + "parameters": { |
| 188 | + "source_path": "$FIXTURE_FILE", |
| 189 | + "report_path": "$report_path" |
| 190 | + } |
| 191 | +} |
| 192 | +JSON |
| 193 | + |
| 194 | + curl -sS -X POST "$BASE_URL/v1/cockpit/runs" \ |
| 195 | + -H "Content-Type: application/json" \ |
| 196 | + --data-binary "@$payload" \ |
| 197 | + > "$response" |
| 198 | + |
| 199 | + python3 - <<'PY' "$response" "$report_path" |
| 200 | +import json, sys, os |
| 201 | +resp = json.load(open(sys.argv[1], 'r', encoding='utf-8')) |
| 202 | +report_path = sys.argv[2] |
| 203 | +status = resp.get('status') |
| 204 | +if status not in {'succeeded', 'needs_review'}: |
| 205 | + raise SystemExit(f"ECHEC run: statut inattendu {status}") |
| 206 | +print(f"Run OK: status={status}") |
| 207 | +print(f"Execution ID: {resp.get('execution_id')}") |
| 208 | +print(f"Request file: {resp.get('request_file')}") |
| 209 | +print(f"Result file: {resp.get('result_file')}") |
| 210 | +print(f"History file: {resp.get('history_file')}") |
| 211 | +print(f"Report exists: {os.path.exists(report_path)} ({report_path})") |
| 212 | +PY |
| 213 | + |
| 214 | + echo "Payload: $payload" |
| 215 | + echo "Reponse: $response" |
| 216 | +} |
| 217 | + |
| 218 | +cmd_history() { |
| 219 | + require_prereqs |
| 220 | + ensure_api_reachable |
| 221 | + local out="$RESULT_DIR/history.latest.json" |
| 222 | + mkdir -p "$RESULT_DIR" |
| 223 | + curl -sS "$BASE_URL/v1/cockpit/history?limit=20" > "$out" |
| 224 | + python3 - <<'PY' "$out" |
| 225 | +import json, sys |
| 226 | +payload = json.load(open(sys.argv[1], 'r', encoding='utf-8')) |
| 227 | +entries = payload.get('entries', []) |
| 228 | +print(f"Historique ({len(entries)} entree(s))") |
| 229 | +for e in entries[:10]: |
| 230 | + print(f"- {e.get('started_at')} | {e.get('tool_id')} | {e.get('action')} | {e.get('status')} | {e.get('execution_id')}") |
| 231 | +print(f"history_file={payload.get('history_file')}") |
| 232 | +PY |
| 233 | + echo "JSON complet: $out" |
| 234 | +} |
| 235 | + |
| 236 | +cmd_status() { |
| 237 | + if is_running; then |
| 238 | + local pid |
| 239 | + pid="$(cat "$PID_FILE")" |
| 240 | + echo "API en cours (PID $pid)." |
| 241 | + else |
| 242 | + echo "API arretee." |
| 243 | + fi |
| 244 | + |
| 245 | + if curl -sS "$BASE_URL/v1/health" >/dev/null 2>&1; then |
| 246 | + echo "Health endpoint OK: $BASE_URL/v1/health" |
| 247 | + else |
| 248 | + echo "Health endpoint indisponible: $BASE_URL/v1/health" |
| 249 | + fi |
| 250 | + |
| 251 | + echo "Cockpit UI: $BASE_URL/ui/cockpit" |
| 252 | +} |
| 253 | + |
| 254 | +cmd_stop() { |
| 255 | + if ! is_running; then |
| 256 | + echo "API deja arretee." |
| 257 | + rm -f "$PID_FILE" |
| 258 | + return 0 |
| 259 | + fi |
| 260 | + |
| 261 | + local pid |
| 262 | + pid="$(cat "$PID_FILE")" |
| 263 | + echo "Arret API (PID $pid)..." |
| 264 | + kill "$pid" >/dev/null 2>&1 || true |
| 265 | + |
| 266 | + local attempts=20 |
| 267 | + while kill -0 "$pid" >/dev/null 2>&1 && (( attempts > 0 )); do |
| 268 | + sleep 0.5 |
| 269 | + attempts=$((attempts - 1)) |
| 270 | + done |
| 271 | + |
| 272 | + if kill -0 "$pid" >/dev/null 2>&1; then |
| 273 | + echo "Force kill PID $pid" |
| 274 | + kill -9 "$pid" >/dev/null 2>&1 || true |
| 275 | + fi |
| 276 | + |
| 277 | + rm -f "$PID_FILE" |
| 278 | + echo "API arretee." |
| 279 | +} |
| 280 | + |
| 281 | +cmd_demo_once() { |
| 282 | + echo "== Demo locale Orchiviste (sans Docker) ==" |
| 283 | + cmd_start |
| 284 | + trap 'cmd_stop >/dev/null 2>&1 || true' EXIT |
| 285 | + cmd_catalog |
| 286 | + cmd_sample_run |
| 287 | + cmd_history |
| 288 | + echo "Demo locale terminee." |
| 289 | +} |
| 290 | + |
| 291 | +usage() { |
| 292 | + cat <<'TXT' |
| 293 | +Usage: |
| 294 | + scripts/demo_local_cockpit.sh start |
| 295 | + scripts/demo_local_cockpit.sh status |
| 296 | + scripts/demo_local_cockpit.sh catalog |
| 297 | + scripts/demo_local_cockpit.sh sample-run |
| 298 | + scripts/demo_local_cockpit.sh history |
| 299 | + scripts/demo_local_cockpit.sh stop |
| 300 | + scripts/demo_local_cockpit.sh demo-once |
| 301 | +
|
| 302 | +Variables utiles: |
| 303 | + ORCHIVISTE_DEMO_HOST (defaut: 127.0.0.1) |
| 304 | + ORCHIVISTE_DEMO_PORT (defaut: 28780) |
| 305 | + ORCHIVISTE_DEMO_RUNTIME_DIR (defaut: Orchiviste/runtime/demo-local) |
| 306 | + ORCHIVISTE_DEMO_SQLITE_PATH (defaut: runtime/demo-local/orchiviste-demo.sqlite) |
| 307 | + ORCHIVISTE_DEMO_CONFIG_FILE (defaut: OrchivisteAPI/configs/cockpit/demo.local.json) |
| 308 | + ORCHIVISTE_DEMO_FIXTURE (defaut: fixtures/demo/cockpit/input_document.txt) |
| 309 | + MUNI_ANALYSE_DIR (defaut: ../MuniAnalyse) |
| 310 | + MUNI_METADONNEES_DIR (defaut: ../MuniMetadonnees) |
| 311 | + MUNI_PRECLASSEMENT_DIR (defaut: ../MuniPreclassement) |
| 312 | + MUNI_CONTROLE_DIR (defaut: ../MuniControle) |
| 313 | + SKIP_BUILD=1 (skip des builds) |
| 314 | +TXT |
| 315 | +} |
| 316 | + |
| 317 | +main() { |
| 318 | + local cmd="${1:-start}" |
| 319 | + case "$cmd" in |
| 320 | + start) cmd_start ;; |
| 321 | + status) cmd_status ;; |
| 322 | + catalog) cmd_catalog ;; |
| 323 | + sample-run) cmd_sample_run ;; |
| 324 | + history) cmd_history ;; |
| 325 | + stop) cmd_stop ;; |
| 326 | + demo-once) cmd_demo_once ;; |
| 327 | + -h|--help|help) usage ;; |
| 328 | + *) |
| 329 | + echo "Commande inconnue: $cmd" >&2 |
| 330 | + usage |
| 331 | + exit 1 |
| 332 | + ;; |
| 333 | + esac |
| 334 | +} |
| 335 | + |
| 336 | +main "$@" |
0 commit comments