Coverage for /Users/antonigmitruk/golf/src/golf/commands/run.py: 0%

65 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-08-16 18:46 +0200

1"""Command to run the built FastMCP server.""" 

2 

3import os 

4import subprocess 

5import sys 

6from pathlib import Path 

7 

8from rich.console import Console 

9from rich.panel import Panel 

10from rich.align import Align 

11from rich.text import Text 

12 

13from golf.cli.branding import create_command_header, get_status_text, STATUS_ICONS, GOLF_BLUE, GOLF_GREEN, GOLF_ORANGE 

14from golf.core.config import Settings 

15 

16console = Console() 

17 

18 

19def run_server( 

20 project_path: Path, 

21 settings: Settings, 

22 dist_dir: Path | None = None, 

23 host: str | None = None, 

24 port: int | None = None, 

25) -> int: 

26 """Run the built FastMCP server. 

27 

28 Args: 

29 project_path: Path to the project root 

30 settings: Project settings 

31 dist_dir: Path to the directory containing the built server 

32 (defaults to project_path/dist) 

33 host: Host to bind the server to (overrides settings) 

34 port: Port to bind the server to (overrides settings) 

35 

36 Returns: 

37 Process return code 

38 """ 

39 # Set default dist directory if not specified 

40 if dist_dir is None: 

41 dist_dir = project_path / "dist" 

42 

43 # Check if server file exists 

44 server_path = dist_dir / "server.py" 

45 if not server_path.exists(): 

46 console.print(get_status_text("error", f"Server file {server_path} not found")) 

47 return 1 

48 

49 # Display server startup header 

50 create_command_header("Starting Server", f"{settings.name}", console) 

51 

52 # Show server info with flashy styling 

53 server_host = host or settings.host or "localhost" 

54 server_port = port or settings.port or 3000 

55 

56 server_content = Text() 

57 server_content.append("🚀 ", style=f"bold {GOLF_ORANGE}") 

58 server_content.append(f"{STATUS_ICONS['server']} Server starting on ", style=f"bold {GOLF_BLUE}") 

59 server_content.append(f"http://{server_host}:{server_port}", style=f"bold {GOLF_GREEN}") 

60 server_content.append(" 🚀", style=f"bold {GOLF_ORANGE}") 

61 server_content.append("\n") 

62 

63 # Add telemetry status indicator 

64 if settings.opentelemetry_enabled: 

65 server_content.append("📊 Golf telemetry enabled", style=f"dim {GOLF_BLUE}") 

66 server_content.append("\n") 

67 

68 server_content.append("⚡ Press Ctrl+C to stop ⚡", style=f"dim {GOLF_ORANGE}") 

69 

70 console.print( 

71 Panel( 

72 Align.center(server_content), 

73 border_style=GOLF_BLUE, 

74 padding=(1, 2), 

75 title="[bold]🌐 SERVER READY 🌐[/bold]", 

76 title_align="center", 

77 ) 

78 ) 

79 console.print() 

80 

81 # Prepare environment variables 

82 env = os.environ.copy() 

83 if host is not None: 

84 env["HOST"] = host 

85 elif settings.host: 

86 env["HOST"] = settings.host 

87 

88 if port is not None: 

89 env["PORT"] = str(port) 

90 elif settings.port: 

91 env["PORT"] = str(settings.port) 

92 

93 # Run the server 

94 try: 

95 # Using subprocess to properly handle signals (Ctrl+C) 

96 process = subprocess.run( 

97 [sys.executable, str(server_path)], 

98 cwd=dist_dir, 

99 env=env, 

100 ) 

101 

102 # Provide more context about the exit 

103 console.print() 

104 if process.returncode == 0: 

105 console.print(get_status_text("success", "Server stopped successfully")) 

106 elif process.returncode == 130: 

107 console.print(get_status_text("info", "Server stopped by user interrupt (Ctrl+C)")) 

108 elif process.returncode == 143: 

109 console.print(get_status_text("info", "Server stopped by SIGTERM (graceful shutdown)")) 

110 elif process.returncode == 137: 

111 console.print(get_status_text("warning", "Server stopped by SIGKILL (forced shutdown)")) 

112 elif process.returncode in [1, 2]: 

113 console.print(get_status_text("error", f"Server exited with error code {process.returncode}")) 

114 else: 

115 console.print(get_status_text("warning", f"Server exited with code {process.returncode}")) 

116 

117 return process.returncode 

118 except KeyboardInterrupt: 

119 console.print() 

120 console.print(get_status_text("info", "Server stopped by user (Ctrl+C)")) 

121 return 130 # Standard exit code for SIGINT 

122 except Exception as e: 

123 console.print() 

124 console.print(get_status_text("error", f"Error running server: {e}")) 

125 return 1