Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions internal/models/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@ type Configuration struct {
}

type ServiceConfigRequest struct {
ID string `json:"id"`
Name string `json:"name"`
Dir string `json:"dir"`
JavaOpts string `json:"javaOpts"`
HealthURL string `json:"healthUrl"`
Port int `json:"port"`
Order int `json:"order"`
Description string `json:"description"`
IsEnabled bool `json:"isEnabled"`
BuildSystem string `json:"buildSystem"` // "maven", "gradle", or "auto"
EnvVars map[string]EnvVar `json:"envVars"`
ID string `json:"id"`
Name string `json:"name"`
Dir string `json:"dir"`
JavaOpts string `json:"javaOpts"`
HealthURL string `json:"healthUrl"`
Port int `json:"port"`
Order int `json:"order"`
Description string `json:"description"`
IsEnabled bool `json:"isEnabled"`
BuildSystem string `json:"buildSystem"` // "maven", "gradle", or "auto"
VerboseLogging bool `json:"verboseLogging"` // Enable verbose/debug logging for build tools
EnvVars map[string]EnvVar `json:"envVars"`
}
9 changes: 7 additions & 2 deletions internal/services/buildsystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,15 @@ func GetStartCommand(serviceDir, buildSystem string, javaOpts string, extraEnv s
if verboseLogging {
if effectiveBuildSystem == BuildSystemMaven {
// Maven: use -X for debug output
baseCommand = strings.Replace(baseCommand, "spring-boot:run", "spring-boot:run -X", 1)
// Check if the command contains the wrapper, then add -X after it
if strings.Contains(baseCommand, "./mvnw") {
baseCommand = strings.Replace(baseCommand, "./mvnw", "./mvnw -X", 1)
}
} else if effectiveBuildSystem == BuildSystemGradle {
// Gradle: use -i for info level logging
baseCommand = strings.Replace(baseCommand, "bootRun", "bootRun -i", 1)
if strings.Contains(baseCommand, "./gradlew") {
baseCommand = strings.Replace(baseCommand, "./gradlew", "./gradlew -i", 1)
}
}
}

Expand Down
10 changes: 8 additions & 2 deletions internal/services/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ func (sm *Manager) loadGlobalConfigFromDB() error {
func (sm *Manager) loadDynamicServices() error {
// Query all services from database
rows, err := sm.db.Query(`
SELECT id, name, dir, extra_env, java_opts, status, health_status, health_url, port, pid, service_order, last_started, description, is_enabled, build_system
SELECT id, name, dir, extra_env, java_opts, status, health_status, health_url, port, pid, service_order, last_started, description, is_enabled, build_system, verbose_logging
FROM services`)
if err != nil {
return fmt.Errorf("failed to query dynamic services: %w", err)
Expand All @@ -315,10 +315,11 @@ func (sm *Manager) loadDynamicServices() error {
var description sql.NullString
var isEnabled sql.NullBool
var buildSystem sql.NullString
var verboseLogging sql.NullBool

err := rows.Scan(&dbService.ID, &dbService.Name, &dbService.Dir, &dbService.ExtraEnv, &dbService.JavaOpts,
&dbService.Status, &dbService.HealthStatus, &dbService.HealthURL, &dbService.Port,
&dbService.PID, &dbService.Order, &dbService.LastStarted, &description, &isEnabled, &buildSystem)
&dbService.PID, &dbService.Order, &dbService.LastStarted, &description, &isEnabled, &buildSystem, &verboseLogging)
if err != nil {
log.Printf("[WARN] Failed to scan dynamic service: %v", err)
continue
Expand All @@ -343,6 +344,11 @@ func (sm *Manager) loadDynamicServices() error {
} else {
dbService.BuildSystem = "auto"
}
if verboseLogging.Valid {
dbService.VerboseLogging = verboseLogging.Bool
} else {
dbService.VerboseLogging = false
}

// Initialize required fields
dbService.EnvVars = make(map[string]models.EnvVar)
Expand Down
1 change: 1 addition & 0 deletions internal/services/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ func (sm *Manager) UpdateService(serviceConfig *models.ServiceConfigRequest) err
service.Description = serviceConfig.Description
service.IsEnabled = serviceConfig.IsEnabled
service.BuildSystem = serviceConfig.BuildSystem
service.VerboseLogging = serviceConfig.VerboseLogging
service.EnvVars = serviceConfig.EnvVars

// Save to database
Expand Down
84 changes: 62 additions & 22 deletions internal/services/operations.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,15 @@ func (sm *Manager) startServiceWithProjectsDir(service *models.Service, projects
cmd.Dir = serviceDir
SetProcessGroup(cmd)

// Start with the current environment
cmd.Env = os.Environ()
// Start with current environment, but filter out JAVA_HOME and PATH to avoid conflicts
baseEnv := []string{}
for _, env := range os.Environ() {
// Skip JAVA_HOME and PATH from base environment - we'll set them explicitly
if !strings.HasPrefix(env, "JAVA_HOME=") && !strings.HasPrefix(env, "PATH=") {
baseEnv = append(baseEnv, env)
}
}
cmd.Env = baseEnv

// Build environment variables with proper precedence
// Priority: Service-specific env vars > Profile Java Home override > Global env vars
Expand All @@ -388,25 +395,37 @@ func (sm *Manager) startServiceWithProjectsDir(service *models.Service, projects
serviceEnvKeys[key] = true
}

// Apply Java Home override if set (only if not overridden by service)
if sm.config.JavaHomeOverride != "" && !serviceEnvKeys["JAVA_HOME"] {
cmd.Env = append(cmd.Env, fmt.Sprintf("JAVA_HOME=%s", sm.config.JavaHomeOverride))
cmd.Env = append(cmd.Env, fmt.Sprintf("PATH=%s/bin:%s", sm.config.JavaHomeOverride, os.Getenv("PATH")))
// Determine which JAVA_HOME to use and set PATH accordingly
var finalJavaHome string
if serviceEnvKeys["JAVA_HOME"] {
// Service-specific JAVA_HOME takes highest priority
finalJavaHome = service.EnvVars["JAVA_HOME"].Value
} else if sm.config.JavaHomeOverride != "" {
// Profile Java Home override
finalJavaHome = sm.config.JavaHomeOverride
}

// Set JAVA_HOME and PATH if we have a Java home
if finalJavaHome != "" {
cmd.Env = append(cmd.Env, fmt.Sprintf("JAVA_HOME=%s", finalJavaHome))
cmd.Env = append(cmd.Env, fmt.Sprintf("PATH=%s/bin:%s", finalJavaHome, os.Getenv("PATH")))
} else {
// No Java home override, use system PATH
cmd.Env = append(cmd.Env, fmt.Sprintf("PATH=%s", os.Getenv("PATH")))
}

// Add global environment variables (only if not overridden by service)
for key, value := range globalEnvVars {
if !serviceEnvKeys[key] {
if !serviceEnvKeys[key] && key != "JAVA_HOME" { // Skip JAVA_HOME as we handled it above
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", key, value))
}
}

// Add service-specific environment variables (these take precedence)
for key, envVar := range service.EnvVars {
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", key, envVar.Value))
// If service sets JAVA_HOME, also update PATH to use that Java
if key == "JAVA_HOME" {
cmd.Env = append(cmd.Env, fmt.Sprintf("PATH=%s/bin:%s", envVar.Value, os.Getenv("PATH")))
// Skip JAVA_HOME as we already handled it above
if key != "JAVA_HOME" {
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", key, envVar.Value))
}
// Also set SPRING_PROFILES_ACTIVE for Spring Boot if ACTIVE_PROFILE is set
if key == "ACTIVE_PROFILE" {
Expand Down Expand Up @@ -569,7 +588,15 @@ func (sm *Manager) startService(service *models.Service) error {
SetProcessGroup(cmd)

// Set environment variables for the process
cmd.Env = os.Environ() // Start with current environment
// Start with current environment, but filter out JAVA_HOME and PATH to avoid conflicts
baseEnv := []string{}
for _, env := range os.Environ() {
// Skip JAVA_HOME and PATH from base environment - we'll set them explicitly
if !strings.HasPrefix(env, "JAVA_HOME=") && !strings.HasPrefix(env, "PATH=") {
baseEnv = append(baseEnv, env)
}
}
cmd.Env = baseEnv

// Build environment variables with proper precedence
// Priority: Service-specific env vars > Profile Java Home override > Global env vars
Expand All @@ -580,25 +607,37 @@ func (sm *Manager) startService(service *models.Service) error {
serviceEnvKeys[key] = true
}

// Apply Java Home override if set (only if not overridden by service)
if sm.config.JavaHomeOverride != "" && !serviceEnvKeys["JAVA_HOME"] {
cmd.Env = append(cmd.Env, fmt.Sprintf("JAVA_HOME=%s", sm.config.JavaHomeOverride))
cmd.Env = append(cmd.Env, fmt.Sprintf("PATH=%s/bin:%s", sm.config.JavaHomeOverride, os.Getenv("PATH")))
// Determine which JAVA_HOME to use and set PATH accordingly
var finalJavaHome string
if serviceEnvKeys["JAVA_HOME"] {
// Service-specific JAVA_HOME takes highest priority
finalJavaHome = service.EnvVars["JAVA_HOME"].Value
} else if sm.config.JavaHomeOverride != "" {
// Profile Java Home override
finalJavaHome = sm.config.JavaHomeOverride
}

// Set JAVA_HOME and PATH if we have a Java home
if finalJavaHome != "" {
cmd.Env = append(cmd.Env, fmt.Sprintf("JAVA_HOME=%s", finalJavaHome))
cmd.Env = append(cmd.Env, fmt.Sprintf("PATH=%s/bin:%s", finalJavaHome, os.Getenv("PATH")))
} else {
// No Java home override, use system PATH
cmd.Env = append(cmd.Env, fmt.Sprintf("PATH=%s", os.Getenv("PATH")))
}

// Add global environment variables (only if not overridden by service)
for key, value := range globalEnvVars {
if !serviceEnvKeys[key] {
if !serviceEnvKeys[key] && key != "JAVA_HOME" { // Skip JAVA_HOME as we handled it above
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", key, value))
}
}

// Add service-specific environment variables (these take precedence)
for key, envVar := range service.EnvVars {
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", key, envVar.Value))
// If service sets JAVA_HOME, also update PATH to use that Java
if key == "JAVA_HOME" {
cmd.Env = append(cmd.Env, fmt.Sprintf("PATH=%s/bin:%s", envVar.Value, os.Getenv("PATH")))
// Skip JAVA_HOME as we already handled it above
if key != "JAVA_HOME" {
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", key, envVar.Value))
}
// Also set SPRING_PROFILES_ACTIVE for Spring Boot if ACTIVE_PROFILE is set
if key == "ACTIVE_PROFILE" {
Expand Down Expand Up @@ -927,11 +966,12 @@ func logJavaVersion(env []string, serviceName string) {
return
}

log.Printf("===================[INFO] JAVA_HOME set is===================: %s", javaHome)

// Try to get Java version
javaPath := filepath.Join(javaHome, "bin", "java")
cmd := exec.Command(javaPath, "-version")
output, err := cmd.CombinedOutput()

if err != nil {
log.Printf("[WARN] Service %s: JAVA_HOME=%s but failed to detect version: %v", serviceName, javaHome, err)
return
Expand Down
1 change: 1 addition & 0 deletions web/src/hooks/useServiceManagement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ export function useServiceManagement(onServiceUpdated: () => void) {
description: service.description || "",
isEnabled: service.isEnabled,
buildSystem: service.buildSystem || "auto",
verboseLogging: service.verboseLogging || false,
envVars: service.envVars || {},
startupDelay: service.startupDelay || 0,
};
Expand Down
2 changes: 2 additions & 0 deletions web/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ export interface ServiceConfigRequest {
order: number;
description: string;
isEnabled: boolean;
buildSystem: string;
verboseLogging: boolean;
envVars: Record<string, EnvVar>;
}

Expand Down