@@ -178,13 +178,11 @@ type WebApp struct {
178178
179179// FrameworkConfig represents framework-specific configuration
180180type FrameworkConfig struct {
181- RuntimeExecutable string `yaml:"runtime_executable"` // e.g., "ruby", "node", "python"
182- ServerExecutable string `yaml:"server_executable"` // e.g., "bin/rails", "server.js"
183- ServerCommand string `yaml:"server_command"` // e.g., "server"
184- ServerArgs []string `yaml:"server_args"` // e.g., ["-p", "4000"]
185- AppDirectory string `yaml:"app_directory"` // e.g., "/rails", "/app"
186- PortEnvVar string `yaml:"port_env_var"` // e.g., "PORT"
187- StartupDelay int `yaml:"startup_delay"` // seconds to wait before marking ready
181+ Command string `yaml:"command"` // e.g., "ruby", "node", "python", "bin/rails"
182+ Args []string `yaml:"args"` // e.g., ["server", "-p", "${port}"]
183+ AppDirectory string `yaml:"app_directory"` // e.g., "/rails", "/app"
184+ PortEnvVar string `yaml:"port_env_var"` // e.g., "PORT"
185+ StartupDelay int `yaml:"startup_delay"` // seconds to wait before marking ready
188186}
189187
190188// Tenant represents a tenant configuration with optional framework overrides
@@ -1741,43 +1739,38 @@ func (m *AppManager) startApp(app *WebApp) {
17411739 }
17421740
17431741 // Build command using framework configuration
1744- var cmd * exec.Cmd
1742+ if framework .Command == "" {
1743+ slog .Error ("Framework command not configured" , "path" , app .Location .Path )
1744+ return // Cannot start without command configured
1745+ }
17451746
1746- // Expand server args with port substitution
1747- serverArgs := make ([]string , len (framework .ServerArgs ))
1748- for i , arg := range framework .ServerArgs {
1747+ // Log the framework configuration being used
1748+ slog .Info ("Starting application with framework config" ,
1749+ "path" , app .Location .Path ,
1750+ "command" , framework .Command ,
1751+ "args" , framework .Args ,
1752+ "appDirectory" , appDir ,
1753+ "port" , app .Port )
1754+
1755+ // Expand args with port substitution
1756+ args := make ([]string , len (framework .Args ))
1757+ for i , arg := range framework .Args {
17491758 if arg == "${port}" {
1750- serverArgs [i ] = strconv .Itoa (app .Port )
1759+ args [i ] = strconv .Itoa (app .Port )
17511760 } else {
1752- serverArgs [i ] = arg
1761+ args [i ] = arg
17531762 }
17541763 }
17551764
1756- // Check if server executable exists in app directory
1757- serverPath := filepath .Join (appDir , framework .ServerExecutable )
1758- if _ , err := os .Stat (serverPath ); err == nil {
1759- // Use the server executable directly
1760- if framework .ServerCommand != "" {
1761- // Add server command as first argument
1762- args := append ([]string {framework .ServerCommand }, serverArgs ... )
1763- cmd = exec .CommandContext (ctx , serverPath , args ... )
1764- } else {
1765- cmd = exec .CommandContext (ctx , serverPath , serverArgs ... )
1766- }
1767- } else {
1768- // Fallback to runtime executable with server executable as argument
1769- runtime := framework .RuntimeExecutable
1770- if runtime == "" {
1771- return // Cannot start without runtime executable configured
1772- }
1773- if framework .ServerCommand != "" {
1774- args := append ([]string {framework .ServerExecutable , framework .ServerCommand }, serverArgs ... )
1775- cmd = exec .CommandContext (ctx , runtime , args ... )
1776- } else {
1777- args := append ([]string {framework .ServerExecutable }, serverArgs ... )
1778- cmd = exec .CommandContext (ctx , runtime , args ... )
1779- }
1780- }
1765+ // Log the final command that will be executed
1766+ slog .Info ("Executing command" ,
1767+ "path" , app .Location .Path ,
1768+ "command" , framework .Command ,
1769+ "expandedArgs" , args ,
1770+ "workingDir" , appDir )
1771+
1772+ // Create command with framework command and args
1773+ cmd := exec .CommandContext (ctx , framework .Command , args ... )
17811774
17821775 cmd .Dir = appDir
17831776 cmd .Env = env
@@ -1844,7 +1837,30 @@ func (m *AppManager) startApp(app *WebApp) {
18441837 "directory" , appDir )
18451838
18461839 if err := cmd .Start (); err != nil {
1847- slog .Error ("Failed to start web app" , "path" , app .Location .Path , "error" , err )
1840+ slog .Error ("Failed to start web app" ,
1841+ "path" , app .Location .Path ,
1842+ "command" , framework .Command ,
1843+ "args" , args ,
1844+ "workingDir" , appDir ,
1845+ "port" , app .Port ,
1846+ "error" , err )
1847+
1848+ // Check if the command executable exists
1849+ if _ , statErr := os .Stat (framework .Command ); statErr != nil {
1850+ slog .Error ("Command executable not found" ,
1851+ "path" , app .Location .Path ,
1852+ "command" , framework .Command ,
1853+ "statError" , statErr )
1854+ }
1855+
1856+ // Check if working directory exists
1857+ if _ , statErr := os .Stat (appDir ); statErr != nil {
1858+ slog .Error ("Working directory not found" ,
1859+ "path" , app .Location .Path ,
1860+ "workingDir" , appDir ,
1861+ "statError" , statErr )
1862+ }
1863+
18481864 app .mutex .Lock ()
18491865 app .Starting = false
18501866 app .mutex .Unlock ()
0 commit comments