From 1a23847d31969f4a45ee539063ac2d35aa9491ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torjus=20H=C3=A5kestad?= Date: Thu, 12 Feb 2026 13:24:04 +0100 Subject: [PATCH] fix(builder): separate build output from error to preserve timeout messages When a build timed out, the timeout error was silently replaced by truncated stderr output. Split into separate Error and Output fields on BuildHostResult so the cause (e.g. "build timed out after 30m0s") is always visible in logs and CLI output. Co-Authored-By: Claude Opus 4.6 --- cmd/homelab-deploy/main.go | 10 +++++++++- internal/builder/builder.go | 8 +++++--- internal/messages/build.go | 1 + 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/cmd/homelab-deploy/main.go b/cmd/homelab-deploy/main.go index 19d3a26..50e0cd2 100644 --- a/cmd/homelab-deploy/main.go +++ b/cmd/homelab-deploy/main.go @@ -17,7 +17,7 @@ import ( "github.com/urfave/cli/v3" ) -const version = "0.2.1" +const version = "0.2.2" func main() { app := &cli.Command{ @@ -565,6 +565,14 @@ func buildCommand() *cli.Command { result.FinalResponse.Succeeded, result.FinalResponse.Failed, result.FinalResponse.TotalDurationSeconds) + for _, hr := range result.FinalResponse.Results { + if !hr.Success { + fmt.Printf("\n--- %s (error: %s) ---\n", hr.Host, hr.Error) + if hr.Output != "" { + fmt.Println(hr.Output) + } + } + } } if !result.AllSucceeded() { diff --git a/internal/builder/builder.go b/internal/builder/builder.go index 2c3c03d..4f5b801 100644 --- a/internal/builder/builder.go +++ b/internal/builder/builder.go @@ -269,10 +269,12 @@ func (b *Builder) handleBuildRequest(subject string, data []byte) { DurationSeconds: hostDuration, } if !result.Success { - hostResult.Error = truncateOutput(result.Stderr, 50) - if hostResult.Error == "" && result.Error != nil { + if result.Error != nil { hostResult.Error = result.Error.Error() } + if result.Stderr != "" { + hostResult.Output = truncateOutput(result.Stderr, 50) + } } results = append(results, hostResult) @@ -284,7 +286,7 @@ func (b *Builder) handleBuildRequest(subject string, data []byte) { } } else { failed++ - b.logger.Error("host build failed", "host", host, "error", hostResult.Error) + b.logger.Error("host build failed", "host", host, "error", hostResult.Error, "output", hostResult.Output) if b.metrics != nil { b.metrics.RecordHostBuildFailure(req.Repo, host, hostDuration) } diff --git a/internal/messages/build.go b/internal/messages/build.go index da310df..0637107 100644 --- a/internal/messages/build.go +++ b/internal/messages/build.go @@ -82,6 +82,7 @@ type BuildHostResult struct { Host string `json:"host"` Success bool `json:"success"` Error string `json:"error,omitempty"` + Output string `json:"output,omitempty"` DurationSeconds float64 `json:"duration_seconds"` }