feat: professionalize control plane and standalone delivery

This commit is contained in:
theshy
2026-04-07 10:46:30 +08:00
parent d0cf1fd0df
commit 862db502b0
100 changed files with 8313 additions and 1483 deletions

112
cold-start-smoke.sh Normal file
View File

@ -0,0 +1,112 @@
#!/usr/bin/env bash
set -euo pipefail
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOCAL_DEFAULT_PYTHON="$PROJECT_DIR/.venv/bin/python"
LEGACY_DEFAULT_PYTHON="$PROJECT_DIR/../.venv/bin/python"
PYTHON_BIN="${BILIUP_NEXT_PYTHON:-$LOCAL_DEFAULT_PYTHON}"
HOST="${BILIUP_NEXT_SMOKE_HOST:-127.0.0.1}"
PORT="${BILIUP_NEXT_SMOKE_PORT:-18787}"
if [[ ! -x "$PYTHON_BIN" ]]; then
if [[ -x "$LEGACY_DEFAULT_PYTHON" ]]; then
PYTHON_BIN="$LEGACY_DEFAULT_PYTHON"
else
PYTHON_BIN="${BILIUP_NEXT_PYTHON:-python3}"
fi
fi
if [[ ! -x "$PYTHON_BIN" ]]; then
echo "python not found: $PYTHON_BIN" >&2
exit 1
fi
API_PID=""
cleanup() {
if [[ -n "${API_PID:-}" ]]; then
kill "$API_PID" >/dev/null 2>&1 || true
wait "$API_PID" >/dev/null 2>&1 || true
fi
}
trap cleanup EXIT
cd "$PROJECT_DIR"
echo "==> check generated files"
for REQUIRED_FILE in \
"$PROJECT_DIR/config/settings.json" \
"$PROJECT_DIR/config/settings.staged.json" \
"$PROJECT_DIR/runtime/cookies.json" \
"$PROJECT_DIR/runtime/upload_config.json"
do
if [[ ! -f "$REQUIRED_FILE" ]]; then
echo "missing file: $REQUIRED_FILE" >&2
exit 1
fi
done
echo "==> doctor"
PYTHONPATH="$PROJECT_DIR/src" "$PYTHON_BIN" -m biliup_next.app.cli doctor >/dev/null
echo "==> init-workspace"
PYTHONPATH="$PROJECT_DIR/src" "$PYTHON_BIN" -m biliup_next.app.cli init-workspace >/dev/null
echo "==> start api"
PYTHONPATH="$PROJECT_DIR/src" "$PYTHON_BIN" -m biliup_next.app.cli serve --host "$HOST" --port "$PORT" >/tmp/biliup-next-cold-start-smoke.log 2>&1 &
API_PID="$!"
echo "==> wait for health"
for _ in $(seq 1 40); do
if "$PYTHON_BIN" - "$HOST" "$PORT" <<'PY'
import json
import sys
import urllib.request
host = sys.argv[1]
port = sys.argv[2]
try:
with urllib.request.urlopen(f"http://{host}:{port}/health", timeout=0.5) as resp:
payload = json.load(resp)
if payload.get("ok") is True:
raise SystemExit(0)
except Exception:
pass
raise SystemExit(1)
PY
then
break
fi
sleep 0.5
done
echo "==> api settings schema"
"$PYTHON_BIN" - "$HOST" "$PORT" <<'PY'
import json
import sys
import urllib.request
host = sys.argv[1]
port = sys.argv[2]
with urllib.request.urlopen(f"http://{host}:{port}/settings/schema", timeout=2) as resp:
payload = json.load(resp)
assert isinstance(payload, dict)
assert payload.get("title")
PY
echo "==> api tasks"
"$PYTHON_BIN" - "$HOST" "$PORT" <<'PY'
import json
import sys
import urllib.request
host = sys.argv[1]
port = sys.argv[2]
with urllib.request.urlopen(f"http://{host}:{port}/tasks?limit=5", timeout=2) as resp:
payload = json.load(resp)
assert isinstance(payload, dict)
assert "items" in payload
PY
echo "==> cold start smoke ok"