init
This commit is contained in:
+132
@@ -0,0 +1,132 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
||||
"browser.local/run/api"
|
||||
"browser.local/run/config"
|
||||
runruntime "browser.local/run/runtime"
|
||||
"browser.local/run/spool"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if handled, exitCode := runruntime.RunManagedProcessHelper(os.Args); handled {
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
cfg := config.Load()
|
||||
configSource := "environment-or-build-defaults"
|
||||
if cfg.Mode == "self-update-helper" {
|
||||
log.Printf("RUN phase=self_update_helper status=starting manifestPresent=%t", os.Getenv("RUN_UPDATE_MANIFEST") != "")
|
||||
if err := runruntime.ApplySelfUpdateManifest(os.Getenv("RUN_UPDATE_MANIFEST")); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Run self-update helper failed: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
log.Printf("RUN phase=self_update_helper status=complete")
|
||||
return
|
||||
}
|
||||
if packageConfig, ok, err := config.LoadPackageConfigFromEnv(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "invalid run package config: %v\n", err)
|
||||
os.Exit(1)
|
||||
} else if ok {
|
||||
cfg = config.ApplyPackageConfig(cfg, packageConfig)
|
||||
configSource = "RUN_PACKAGE_CONFIG"
|
||||
} else if packageConfig, ok, err := config.LoadPackageConfigBesideExecutable(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "invalid bundled run package config: %v\n", err)
|
||||
os.Exit(1)
|
||||
} else if ok {
|
||||
cfg = config.ApplyPackageConfig(cfg, packageConfig)
|
||||
configSource = "package-config-beside-executable"
|
||||
}
|
||||
logWorkerPhases := cfg.Mode == "worker"
|
||||
if logWorkerPhases {
|
||||
log.Printf("RUN phase=bootstrap status=starting pid=%d args=%d", os.Getpid(), len(os.Args))
|
||||
log.Printf("RUN phase=config status=loaded source=%s mode=%s platform=%s endpoint=%s server=%s plugin=%s component=%s componentKey=%s version=%s", configSource, cfg.Mode, diagnosticPlatformAddress(cfg.PlatformURL), diagnosticValue(cfg.RunEndpointID), diagnosticValue(cfg.ServerInstanceID), diagnosticValue(cfg.PluginID), diagnosticValue(cfg.ComponentKind), diagnosticValue(cfg.ComponentKey), diagnosticValue(cfg.Version))
|
||||
log.Printf("RUN phase=platform_client status=building platform=%s", diagnosticPlatformAddress(cfg.PlatformURL))
|
||||
}
|
||||
client, err := api.NewPlatformClient(cfg.PlatformURL)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "invalid platform URL: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if logWorkerPhases {
|
||||
log.Printf("RUN phase=platform_client status=ready base=%s", client.BaseURL())
|
||||
}
|
||||
|
||||
if cfg.Mode == "worker" {
|
||||
log.Printf("RUN phase=startup status=worker platform=%s endpoint=%s server=%s plugin=%s workspace=%s spool=%s maxJobs=%d", diagnosticPlatformAddress(cfg.PlatformURL), diagnosticValue(cfg.RunEndpointID), diagnosticValue(cfg.ServerInstanceID), diagnosticValue(cfg.PluginID), diagnosticValue(cfg.WorkspaceRoot), diagnosticValue(cfg.SpoolRoot), cfg.MaxJobs)
|
||||
log.Printf("RUN phase=workspace_seed status=materializing present=%t workspace=%s componentKey=%s", cfg.WorkspaceSeed != "", diagnosticValue(cfg.WorkspaceRoot), diagnosticValue(cfg.ComponentKey))
|
||||
if err := runruntime.MaterializeWorkspaceSeed(cfg); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "initialize plugin workspace assets: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
log.Printf("RUN phase=workspace_seed status=ready workspace=%s", diagnosticValue(cfg.WorkspaceRoot))
|
||||
log.Printf("RUN phase=log_spool status=opening path=%s", diagnosticValue(cfg.SpoolRoot))
|
||||
logSpool, err := spool.NewLogSpool(cfg.SpoolRoot)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "initialize log spool: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
log.Printf("RUN phase=log_spool status=ready path=%s", diagnosticValue(cfg.SpoolRoot))
|
||||
log.Printf("RUN phase=artifact_queue status=opening path=%s", diagnosticValue(cfg.SpoolRoot))
|
||||
artifactQueue, err := spool.NewArtifactQueue(cfg.SpoolRoot)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "initialize artifact queue: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
log.Printf("RUN phase=artifact_queue status=ready path=%s", diagnosticValue(cfg.SpoolRoot))
|
||||
log.Printf("RUN phase=worker_init status=starting endpoint=%s", diagnosticValue(cfg.RunEndpointID))
|
||||
worker, err := runruntime.NewWorker(
|
||||
cfg,
|
||||
client,
|
||||
runruntime.WithProcessLogSink(&runruntime.SpoolLogSink{Spool: logSpool}),
|
||||
runruntime.WithLifecycleArtifactHook(&runruntime.QueueArtifactHook{Queue: artifactQueue}),
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "initialize worker: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
log.Printf("RUN phase=worker_init status=ready endpoint=%s", diagnosticValue(cfg.RunEndpointID))
|
||||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
|
||||
defer stop()
|
||||
log.Printf("RUN phase=worker_loop status=entering endpoint=%s", diagnosticValue(cfg.RunEndpointID))
|
||||
if err := worker.Run(ctx); err != nil && err != context.Canceled && err != runruntime.ErrSelfUpdateRestartRequested {
|
||||
fmt.Fprintf(os.Stderr, "run worker stopped: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
log.Printf("RUN phase=worker_loop status=stopped endpoint=%s", diagnosticValue(cfg.RunEndpointID))
|
||||
return
|
||||
}
|
||||
|
||||
summary := runruntime.SmokeSummary(cfg)
|
||||
summary.PlatformURL = client.BaseURL()
|
||||
|
||||
if err := json.NewEncoder(os.Stdout).Encode(summary); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "encode smoke summary: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func diagnosticValue(value string) string {
|
||||
if value == "" {
|
||||
return "-"
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func diagnosticPlatformAddress(rawURL string) string {
|
||||
parsed, err := url.Parse(rawURL)
|
||||
if err != nil || parsed.Scheme == "" || parsed.Host == "" {
|
||||
return "invalid"
|
||||
}
|
||||
address := parsed.Scheme + "://" + parsed.Host
|
||||
if path := parsed.EscapedPath(); path != "" && path != "/" {
|
||||
address += path
|
||||
}
|
||||
return address
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package main
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestDiagnosticPlatformAddressOmitsCredentials(t *testing.T) {
|
||||
if got := diagnosticPlatformAddress("https://token:secret@scum.npc0.com/api"); got != "https://scum.npc0.com/api" {
|
||||
t.Fatalf("unexpected diagnostic address %q", got)
|
||||
}
|
||||
if got := diagnosticPlatformAddress("not a URL"); got != "invalid" {
|
||||
t.Fatalf("unexpected invalid diagnostic address %q", got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user