This commit is contained in:
2026-09-24 05:19:06 -04:00
commit 2cec225860
27 changed files with 2640 additions and 0 deletions
Executable
+170
View File
@@ -0,0 +1,170 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
VENV_DIR="${ROOT}/.venv"
PY_BIN="${VENV_DIR}/bin/python"
UVICORN_BIN="${VENV_DIR}/bin/uvicorn"
PID_FILE="${ROOT}/.demo.pid"
LOG_FILE="${ROOT}/.demo.log"
APP_MODULE="examples.demo_backend:app"
HOST="127.0.0.1"
PORT="9292"
BANNER="ApiPilot Demo Backend (port ${PORT})"
msg() { echo -e "[demo] ${*}"; }
err() { echo -e "[demo][error] ${*}" >&2; }
ok() { echo -e "[demo][ok] ${*}"; }
ensure_venv() {
if [ ! -x "${PY_BIN}" ]; then
msg "Creo virtualenv in ${VENV_DIR}..."
python3 -m venv "${VENV_DIR}"
fi
if ! "${PY_BIN}" -c "import apipilot" >/dev/null 2>&1; then
msg "Installo apipilot[test] in modalità editabile..."
"${PY_BIN}" -m pip install --upgrade pip >/dev/null
"${PY_BIN}" -m pip install -e "${ROOT}[test]" >/dev/null
fi
if [ ! -x "${UVICORN_BIN}" ]; then
msg "Installo uvicorn nel venv..."
"${PY_BIN}" -m pip install -q uvicorn >/dev/null
fi
}
read_pid() {
if [ -f "${PID_FILE}" ]; then
local p
p="$(cat "${PID_FILE}" 2>/dev/null || true)"
if [ -n "${p}" ] && kill -0 "${p}" 2>/dev/null; then
echo "${p}"
return 0
fi
fi
return 1
}
cmd_status() {
local pid
if pid="$(read_pid)"; then
ok "${BANNER} in esecuzione (PID=${pid}, log=${LOG_FILE})"
return 0
else
msg "${BANNER} NON in esecuzione"
[ -f "${PID_FILE}" ] && rm -f "${PID_FILE}"
return 3
fi
}
cmd_start() {
local pid
if pid="$(read_pid)"; then
msg "Già in esecuzione (PID=${pid}). Usa 'demo.sh restart' per riavviare."
return 0
fi
ensure_venv
msg "Avvio ${BANNER}..."
cd "${ROOT}"
nohup "${UVICORN_BIN}" "${APP_MODULE}" \
--host "${HOST}" \
--port "${PORT}" \
--reload \
>"${LOG_FILE}" 2>&1 &
local new_pid=$!
echo "${new_pid}" > "${PID_FILE}"
sleep 1
if kill -0 "${new_pid}" 2>/dev/null; then
ok "Avviato. PID=${new_pid}"
msg " URL : http://${HOST}:${PORT}/docs"
msg " Log : tail -f ${LOG_FILE}"
msg " Auth: Demo senza auth obbligatoria (default: demo-user/admin). Opzionale: Bearer admin-token oppure Bearer user-token"
return 0
else
err "Impossibile avviare il server. Controlla ${LOG_FILE}"
return 1
fi
}
cmd_stop() {
local pid
if ! pid="$(read_pid)"; then
msg "Nessun processo in esecuzione."
[ -f "${PID_FILE}" ] && rm -f "${PID_FILE}"
return 0
fi
msg "Arresto processo PID=${pid}..."
kill "${pid}" 2>/dev/null || true
for i in 1 2 3 4 5 6 7 8 9 10; do
if ! kill -0 "${pid}" 2>/dev/null; then
break
fi
sleep 0.5
done
if kill -0 "${pid}" 2>/dev/null; then
msg "Graceful stop fallito, invio SIGKILL..."
kill -9 "${pid}" 2>/dev/null || true
sleep 1
fi
rm -f "${PID_FILE}"
if ! kill -0 "${pid}" 2>/dev/null; then
ok "Arrestato."
else
err "Impossibile arrestare PID=${pid}. Interrompi manualmente."
return 1
fi
}
cmd_restart() {
cmd_stop || true
sleep 0.5
cmd_start
}
cmd_logs() {
if [ -f "${LOG_FILE}" ]; then
tail -n "${1:-50}" "${LOG_FILE}"
else
msg "Nessun log disponibile (${LOG_FILE} non esiste)."
fi
}
usage() {
cat <<EOF
Uso: $(basename "$0") <COMANDO>
Comandi:
start Avvia ${BANNER} in background (con venv creato/aggiornato se serve)
stop Arresta l'istanza in background
restart stop + start
status Verifica se è in esecuzione (ritorna 3 se non in esecuzione)
logs [N] Mostra le ultime N righe del log (default: 50)
help Questo aiuto
Percorsi:
PID : ${PID_FILE}
LOG : ${LOG_FILE}
VENV : ${VENV_DIR}
EOF
}
main() {
local cmd="${1:-help}"
shift || true
case "${cmd}" in
start) cmd_start ;;
stop) cmd_stop ;;
restart) cmd_restart ;;
status) cmd_status ;;
logs) cmd_logs "${1:-}" ;;
help|-h|--help) usage ;;
*)
err "Comando sconosciuto: '${cmd}'"
echo
usage
exit 2
;;
esac
}
main "$@"