()
| 264 | |
| 265 | |
| 266 | def main() -> int: |
| 267 | args = parse_args() |
| 268 | os.chdir(PROJECT_ROOT) |
| 269 | log("启动器已就位,开始检查环境") |
| 270 | |
| 271 | env_values = read_env_file(PROJECT_ROOT / ".env") |
| 272 | database_url = env_values.get("APP_DATABASE_URL") or env_values.get("DATABASE_URL") or "" |
| 273 | database_endpoint = parse_database_endpoint(database_url) |
| 274 | if not database_url: |
| 275 | log(".env 中未发现 APP_DATABASE_URL / DATABASE_URL,应用可能回退到 SQLite", "WARN") |
| 276 | elif not database_endpoint: |
| 277 | log(f".env 中数据库配置不是 PostgreSQL: {database_url}", "WARN") |
| 278 | else: |
| 279 | log(f"检测到 PostgreSQL 数据库配置: {database_endpoint[0]}:{database_endpoint[1]}") |
| 280 | |
| 281 | selected_port = resolve_available_port(args.host, args.port, max_scan=100) |
| 282 | if selected_port != args.port: |
| 283 | log(f"端口 {args.port} 已占用,自动改用 {selected_port}", "WARN") |
| 284 | url = f"http://{get_display_host(args.host)}:{selected_port}" |
| 285 | log(f"本次启动地址: {url}") |
| 286 | |
| 287 | if not args.skip_docker: |
| 288 | if database_endpoint and can_connect_tcp(database_endpoint[0], database_endpoint[1]): |
| 289 | log(f"检测到数据库已可直连,跳过 Docker/PostgreSQL 自动启动: {database_endpoint[0]}:{database_endpoint[1]}") |
| 290 | else: |
| 291 | ensure_docker_daemon(args.db_timeout) |
| 292 | ensure_postgres_service(args.service, args.db_timeout, args.dry_run, database_endpoint=database_endpoint) |
| 293 | else: |
| 294 | log("已按参数跳过 Docker/PostgreSQL 自动启动", "WARN") |
| 295 | |
| 296 | maybe_open_browser(url, args.web_timeout, enabled=not args.no_browser, dry_run=args.dry_run) |
| 297 | exit_code = launch_webui(args.host, selected_port, args.dry_run) |
| 298 | if exit_code == 0: |
| 299 | log("启动器退出,Web UI 进程已正常结束") |
| 300 | else: |
| 301 | log(f"Web UI 进程退出码: {exit_code}", "ERROR") |
| 302 | return exit_code |
| 303 | |
| 304 | |
| 305 | if __name__ == "__main__": |
no test coverage detected