package config import ( "os" "path/filepath" "strconv" "time" ) const ( DefaultMode = "smoke" DefaultPlatformURL = "http://127.0.0.1:8080" DefaultEndpointID = "run-local" DefaultDisplayName = "Local Run" DefaultVersion = "0.1.0" ) var BuildVersion = DefaultVersion var BuildMode string var BuildPlatformURL string var BuildRunEndpointID string var BuildDisplayName string var BuildRegistrationToken string var BuildServerInstanceID string var BuildPluginID string var BuildComponentKind string var BuildComponentKey string var BuildKeyGeneration string var BuildWorkspaceSeed string type Config struct { Mode string PlatformURL string RunEndpointID string DisplayName string Version string RegistrationToken string ServerInstanceID string PluginID string ComponentKind string ComponentKey string KeyGeneration int SecretRef string WorkspaceSeed string WorkspaceRoot string BuildSourceRoot string SpoolRoot string MaxJobs int HeartbeatInterval time.Duration PollInterval time.Duration RetryBackoff time.Duration UpdateJobID string UpdateOutcome string UpdateAttempt int UpdateLeaseToken string UpdateHealthFile string LocalStartupDiagnostics bool } func Load() Config { mode := os.Getenv("RUN_MODE") if mode == "" { mode = stringOrDefault(BuildMode, DefaultMode) } platformURL := os.Getenv("RUN_PLATFORM_URL") if platformURL == "" { platformURL = stringOrDefault(BuildPlatformURL, DefaultPlatformURL) } workspaceRoot := envOrDefault("RUN_WORKSPACE_ROOT", filepath.Join(".", ".run-workspace")) identity := loadPackagedIdentity() return Config{ Mode: mode, PlatformURL: platformURL, RunEndpointID: identity.runEndpointID, DisplayName: envOrDefault("RUN_DISPLAY_NAME", stringOrDefault(BuildDisplayName, DefaultDisplayName)), Version: identity.version, RegistrationToken: identity.registrationToken, ServerInstanceID: identity.serverInstanceID, PluginID: identity.pluginID, ComponentKind: identity.componentKind, ComponentKey: identity.componentKey, KeyGeneration: identity.keyGeneration, WorkspaceSeed: envOrDefault("RUN_WORKSPACE_SEED", BuildWorkspaceSeed), WorkspaceRoot: workspaceRoot, BuildSourceRoot: envOrDefault("RUN_BUILD_SOURCE_ROOT", "."), SpoolRoot: envOrDefault("RUN_SPOOL_ROOT", filepath.Join(workspaceRoot, "spool")), MaxJobs: intEnvOrDefault("RUN_MAX_JOBS", 1), HeartbeatInterval: durationEnvOrDefault("RUN_HEARTBEAT_INTERVAL_MS", 15*time.Second), PollInterval: durationEnvOrDefault("RUN_POLL_INTERVAL_MS", 2*time.Second), RetryBackoff: durationEnvOrDefault("RUN_RETRY_BACKOFF_MS", time.Second), UpdateJobID: os.Getenv("RUN_UPDATE_JOB_ID"), UpdateOutcome: os.Getenv("RUN_UPDATE_OUTCOME"), UpdateAttempt: intEnvOrDefault("RUN_UPDATE_ATTEMPT", 0), UpdateLeaseToken: os.Getenv("RUN_UPDATE_LEASE_TOKEN"), UpdateHealthFile: os.Getenv("RUN_UPDATE_HEALTH_FILE"), LocalStartupDiagnostics: os.Getenv("RUN_LOCAL_STARTUP_DIAGNOSTICS") == "1", } } type packagedIdentity struct { runEndpointID string version string registrationToken string serverInstanceID string pluginID string componentKind string componentKey string keyGeneration int } func loadPackagedIdentity() packagedIdentity { if BuildRegistrationToken != "" { return packagedIdentity{ runEndpointID: stringOrDefault(BuildRunEndpointID, DefaultEndpointID), version: stringOrDefault(BuildVersion, DefaultVersion), registrationToken: BuildRegistrationToken, serverInstanceID: BuildServerInstanceID, pluginID: BuildPluginID, componentKind: BuildComponentKind, componentKey: BuildComponentKey, keyGeneration: intStringOrDefault(BuildKeyGeneration, 0), } } return packagedIdentity{ runEndpointID: envOrDefault("RUN_ENDPOINT_ID", stringOrDefault(BuildRunEndpointID, DefaultEndpointID)), version: envOrDefault("RUN_VERSION", BuildVersion), registrationToken: envOrDefault("RUN_REGISTRATION_TOKEN", "local-registration"), serverInstanceID: envOrDefault("RUN_SERVER_INSTANCE_ID", BuildServerInstanceID), pluginID: envOrDefault("RUN_PLUGIN_ID", BuildPluginID), componentKind: envOrDefault("RUN_COMPONENT_KIND", BuildComponentKind), componentKey: envOrDefault("RUN_COMPONENT_KEY", BuildComponentKey), keyGeneration: intEnvOrDefault("RUN_KEY_GENERATION", intStringOrDefault(BuildKeyGeneration, 0)), } } func stringOrDefault(value string, fallback string) string { if value == "" { return fallback } return value } func intStringOrDefault(value string, fallback int) int { parsed, err := strconv.Atoi(value) if err != nil || parsed <= 0 { return fallback } return parsed } func envOrDefault(key string, fallback string) string { value := os.Getenv(key) if value == "" { return fallback } return value } func intEnvOrDefault(key string, fallback int) int { value, err := strconv.Atoi(os.Getenv(key)) if err != nil || value <= 0 { return fallback } return value } func durationEnvOrDefault(key string, fallback time.Duration) time.Duration { value, err := strconv.Atoi(os.Getenv(key)) if err != nil || value <= 0 { return fallback } return time.Duration(value) * time.Millisecond }