#!/usr/bin/env bash # ============================================================ # 大时代 生产环境检查脚本 # # 用法: # ./scripts/check-prod-env.sh # ./scripts/check-prod-env.sh --strict # ./scripts/check-prod-env.sh --smoke-evo # ./scripts/check-prod-env.sh --strict --smoke-evo # # 检查内容: # - Python / Node / npm 是否可用 # - 后端关键 Python 模块是否已安装 # - frontend/package-lock.json 与 npm ci 是否可消费 # - .env 是否存在以及关键变量是否配置 # - 前端是否可构建 # - 可选:EvoAgent 运行时 smoke 检查(默认覆盖 fundamentals_analyst + risk_manager + portfolio_manager) # ============================================================ set -euo pipefail RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' NC='\033[0m' STRICT=false SMOKE_EVO=false for arg in "$@"; do case "$arg" in --strict) STRICT=true ;; --smoke-evo) SMOKE_EVO=true ;; *) echo -e "${YELLOW}忽略未知参数: ${arg}${NC}" ;; esac done SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" cd "${PROJECT_ROOT}" WARNINGS=0 PYTHON_BIN="" PROJECT_PYTHONPATH="" ok() { echo -e "${GREEN}✔${NC} $1" } warn() { WARNINGS=$((WARNINGS + 1)) echo -e "${YELLOW}⚠${NC} $1" } fail() { echo -e "${RED}✘${NC} $1" exit 1 } require_cmd() { local cmd="$1" command -v "${cmd}" >/dev/null 2>&1 || fail "未找到命令: ${cmd}" } resolve_python() { if command -v python >/dev/null 2>&1; then PYTHON_BIN="python" return fi if command -v python3 >/dev/null 2>&1; then PYTHON_BIN="python3" return fi fail "未找到命令: python 或 python3" } init_pythonpath() { PROJECT_PYTHONPATH="${PROJECT_ROOT}/.pydeps:." } check_python_modules() { PYTHONPATH="${PROJECT_PYTHONPATH}" "${PYTHON_BIN}" - <<'PY' mods = [ 'fastapi', 'uvicorn', 'yaml', 'httpx', 'cryptography', 'websockets', 'rich', 'dotenv', 'pandas_market_calendars', 'finnhub', 'openai', 'anthropic', 'agentscope', 'pydantic' ] missing = [] for m in mods: try: __import__(m) except Exception as exc: missing.append((m, f"{type(exc).__name__}: {exc}")) if missing: for name, err in missing: print(f"MISSING {name} {err}") raise SystemExit(1) print("OK") PY } check_env_file() { if [ ! -f .env ]; then if ${STRICT}; then fail "未找到 .env,生产环境请先基于 env.template 配置" fi warn "未找到 .env,生产部署前需要补齐" return fi set -a # shellcheck disable=SC1091 source .env set +a [ -n "${MODEL_NAME:-}" ] || warn "MODEL_NAME 未配置" [ -n "${OPENAI_API_KEY:-}" ] || warn "OPENAI_API_KEY 未配置" [ -n "${FINNHUB_API_KEY:-}" ] || warn "FINNHUB_API_KEY 未配置(live 模式必需)" ok ".env 已加载" } check_frontend_install() { [ -f frontend/package-lock.json ] || fail "frontend/package-lock.json 缺失,生产部署建议保留锁文件" ( cd frontend npm ci --dry-run >/tmp/bigtime-npm-ci.log 2>&1 || true ) if rg -n "npm error code EUSAGE|can only install packages when your package.json and package-lock.json.*in sync|Missing: .* from lock file|Invalid: lock file's " /tmp/bigtime-npm-ci.log >/dev/null 2>&1; then warn "frontend package-lock.json 与 package.json 不一致;需在 frontend/ 重新生成锁文件,但这不阻断当前后端 smoke 检查" elif rg -n "ERESOLVE could not resolve|Conflicting peer dependency" /tmp/bigtime-npm-ci.log >/dev/null 2>&1; then warn "frontend npm ci --dry-run 存在 peer 依赖冲突,当前以后续构建结果为准" elif rg -n "@emoji-mart/react|@lobehub/ui|ERESOLVE overriding peer dependency" /tmp/bigtime-npm-ci.log >/dev/null 2>&1; then warn "frontend npm ci 存在已知非阻塞 peer warning(@lobehub/icons 依赖链),可忽略" elif rg -n "npm warn" /tmp/bigtime-npm-ci.log >/dev/null 2>&1; then warn "frontend npm ci 存在 warning,建议查看 /tmp/bigtime-npm-ci.log" else ok "frontend npm ci --dry-run 通过" fi } check_frontend_build() { ( cd frontend npm run build >/tmp/bigtime-frontend-build.log 2>&1 || { cat /tmp/bigtime-frontend-build.log exit 1 } ) ok "frontend 构建通过" } check_evo_runtime_smoke() { local configured_ids="${EVO_AGENT_IDS:-}" local -a smoke_agent_ids=() local raw_id="" if [ -n "${configured_ids}" ]; then IFS=',' read -r -a smoke_agent_ids <<< "${configured_ids}" else smoke_agent_ids=("fundamentals_analyst" "risk_manager" "portfolio_manager") fi for raw_id in "${smoke_agent_ids[@]}"; do local agent_id agent_id="$(printf '%s' "${raw_id}" | xargs)" [ -n "${agent_id}" ] || continue echo -e "${CYAN}运行 EvoAgent smoke 检查(agent=${agent_id})${NC}" PYTHONPATH="${PROJECT_PYTHONPATH}" "${PYTHON_BIN}" \ "${PROJECT_ROOT}/scripts/smoke_evo_runtime.py" \ --agent-id "${agent_id}" >/tmp/bigtime-evo-smoke.log 2>&1 || { cat /tmp/bigtime-evo-smoke.log exit 1 } cat /tmp/bigtime-evo-smoke.log ok "EvoAgent smoke 检查通过(agent=${agent_id})" done } echo -e "${CYAN}大时代 · 生产环境检查${NC}" resolve_python init_pythonpath require_cmd node require_cmd npm ok "python: $(${PYTHON_BIN} -V 2>&1)" ok "node: $(node -v)" ok "npm: $(npm -v)" check_python_modules && ok "后端关键 Python 模块已安装" check_env_file check_frontend_install check_frontend_build if ${SMOKE_EVO}; then check_evo_runtime_smoke fi if [ "${WARNINGS}" -gt 0 ]; then echo -e "${YELLOW}检查完成:有 ${WARNINGS} 项 warning${NC}" ${STRICT} && exit 1 || exit 0 fi echo -e "${GREEN}检查完成:环境可用于生产部署${NC}"