base_conhecimento / scripts /run_dev.py
Guilherme Silberfarb Costa
Versão inicial da base de conhecimento
75123b0
Raw History Blame Contribute Delete
3.69 kB
"""Own all development child processes, including npm and uvicorn descendants."""
import argparse
import os
import signal
import subprocess
import sys
import time
import urllib.request
import webbrowser
from pathlib import Path
root = Path(__file__).resolve().parents[1]
parser = argparse.ArgumentParser()
parser.add_argument("--port", type=int, default=8010)
parser.add_argument("--no-open", action="store_true")
args = parser.parse_args()
url = f"http://127.0.0.1:{args.port}"
stop = False
def request_stop(*_):
global stop
stop = True
signal.signal(signal.SIGINT, request_stop)
signal.signal(signal.SIGTERM, request_stop)
processes = []
logs = []
try:
for cmd, cwd, logname in [
(["npm", "run", "watch"], root / "frontend", "frontend.log"),
(
[
sys.executable,
"-m",
"uvicorn",
"app.main:app",
"--app-dir",
"backend",
"--host",
"127.0.0.1",
"--port",
str(args.port),
"--reload",
"--reload-dir",
"backend/app",
],
root,
"backend.log",
),
]:
log = (root / ".runtime" / logname).open("w")
logs.append(log)
processes.append(
subprocess.Popen(
cmd,
cwd=cwd,
stdout=log,
stderr=subprocess.STDOUT,
start_new_session=True,
)
)
ready = False
for _ in range(60):
if stop:
break
if any(p.poll() is not None for p in processes):
raise RuntimeError(
"Um processo encerrou. Consulte .runtime/backend.log e frontend.log."
)
try:
with urllib.request.urlopen(url + "/api/health", timeout=1) as r:
ready = r.status == 200
except Exception:
pass
if ready:
break
time.sleep(1)
if not ready and not stop:
raise RuntimeError(
"A aplicação não respondeu em 60 segundos. Consulte .runtime/backend.log."
)
if ready:
from dotenv import dotenv_values
settings = dotenv_values(root / ".env")
identity = (
"Login: mesmos usuários e senhas da MESA (matrícula sem dígito)."
if os.getenv("AUTH_PROVIDER", settings.get("AUTH_PROVIDER", "mesa"))
== "mesa"
else f'Acesso inicial: {root / ".runtime/dev-access.txt"}'
)
print(
f"\nCARLA em desenvolvimento: {url}\nPorta de entrada: carla\n{identity}\nFrontend: recompila ao salvar; atualize a página para ver as mudanças.\nBackend: recarrega automaticamente. Logs em .runtime/.\nCtrl+C encerra todos os processos.\n",
flush=True,
)
if not args.no_open:
webbrowser.open(url)
while not stop:
if any(p.poll() is not None for p in processes):
raise RuntimeError("Um processo encerrou; consulte os logs em .runtime/.")
time.sleep(0.5)
except Exception as exc:
print(str(exc), file=sys.stderr)
sys.exit(1)
finally:
for process in processes:
try:
os.killpg(process.pid, signal.SIGTERM)
except ProcessLookupError:
pass
for process in processes:
try:
process.wait(timeout=7)
except subprocess.TimeoutExpired:
try:
os.killpg(process.pid, signal.SIGKILL)
except ProcessLookupError:
pass
for log in logs:
log.close()