diff --git a/Makefile b/Makefile index b88f41b..2982dee 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ PORT := 8002 PIDFILE := var/api.pid LOGFILE := var/api-8002.log UVICORN := .venv/bin/uvicorn +HEALTH_URL := http://127.0.0.1:$(PORT)/health .DEFAULT_GOAL := help .PHONY: help start stop restart status showlogs @@ -15,10 +16,23 @@ start: ## Start the API server in the background on port 8002 @if [ -f $(PIDFILE) ] && kill -0 $$(cat $(PIDFILE)) 2>/dev/null; then \ echo "Already running (PID $$(cat $(PIDFILE)))"; \ else \ - nohup $(UVICORN) repo_registry.web_api.app:app --port $(PORT) \ + setsid sh -c 'echo $$$$ > $(PIDFILE); exec $(UVICORN) repo_registry.web_api.app:app --host 127.0.0.1 --port $(PORT)' \ >> $(LOGFILE) 2>&1 & \ - echo $$! > $(PIDFILE); \ - echo "Started (PID $$!) — http://127.0.0.1:$(PORT)/ui"; \ + PID=""; \ + for i in $$(seq 1 50); do \ + if [ -f $(PIDFILE) ]; then PID=$$(cat $(PIDFILE)); fi; \ + if [ -n "$$PID" ] && ! kill -0 $$PID 2>/dev/null; then break; fi; \ + if curl -fsS $(HEALTH_URL) >/dev/null 2>&1; then \ + echo "Started (PID $$PID) — http://127.0.0.1:$(PORT)/ui"; \ + exit 0; \ + fi; \ + sleep 0.1; \ + done; \ + rm -f $(PIDFILE); \ + echo "Failed to start API server on http://127.0.0.1:$(PORT)/ui"; \ + echo "Recent log output:"; \ + tail -40 $(LOGFILE) 2>/dev/null || true; \ + exit 1; \ fi stop: ## Stop the API server diff --git a/src/repo_registry/web_ui/views.py b/src/repo_registry/web_ui/views.py index 94178ce..1862136 100644 --- a/src/repo_registry/web_ui/views.py +++ b/src/repo_registry/web_ui/views.py @@ -17,7 +17,12 @@ router = APIRouter(include_in_schema=False) APP_NAME = "Repository Scoping" -def page(title: str, body: str) -> HTMLResponse: +def page(title: str, body: str, selected_repository: str | None = None) -> HTMLResponse: + repository_context = ( + f'{escape(selected_repository)}' + if selected_repository + else "" + ) return HTMLResponse( f""" @@ -166,6 +171,9 @@ def page(title: str, body: str) -> HTMLResponse: font: 13px/1.55 ui-monospace, SFMono-Regular, Consolas, monospace; }} .actions {{ display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }} + .header-brand {{ display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap; }} + .header-context {{ color: #b6c8d6; font-weight: 650; }} + .header-context::before {{ content: "/"; color: #6b7d8f; margin-right: 10px; }} [data-pending] {{ display: none; color: var(--muted); }} form.is-submitting [data-pending] {{ display: inline; }} form.is-submitting button[type="submit"] {{ opacity: .7; cursor: wait; }} @@ -182,7 +190,10 @@ def page(title: str, body: str) -> HTMLResponse:
- {APP_NAME} +
+ {APP_NAME} + {repository_context} +