From a1f706d17a2ea996c44ba04aad02ecd802390c34 Mon Sep 17 00:00:00 2001 From: Gero Hillebrandt Date: Thu, 1 Jan 2026 19:46:56 +0100 Subject: [PATCH] fix: prevent nil context panic in multi-repo hydration (#840) --- cmd/bd/context.go | 11 ++++++++-- cmd/bd/context_test.go | 48 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 cmd/bd/context_test.go diff --git a/cmd/bd/context.go b/cmd/bd/context.go index 49d7233a..e9cf9ebc 100644 --- a/cmd/bd/context.go +++ b/cmd/bd/context.go @@ -194,11 +194,18 @@ func setDBPath(p string) { } // getRootContext returns the signal-aware root context. +// Returns context.Background() if the root context is nil (e.g., before CLI initialization). func getRootContext() context.Context { + var ctx context.Context if shouldUseGlobals() { - return rootCtx + ctx = rootCtx + } else { + ctx = cmdCtx.RootCtx } - return cmdCtx.RootCtx + if ctx == nil { + return context.Background() + } + return ctx } // setRootContext updates the root context and cancel function. diff --git a/cmd/bd/context_test.go b/cmd/bd/context_test.go new file mode 100644 index 00000000..86cd8337 --- /dev/null +++ b/cmd/bd/context_test.go @@ -0,0 +1,48 @@ +package main + +import ( + "context" + "testing" +) + +func TestGetRootContext_NilFallback(t *testing.T) { + // Save original state + oldRootCtx := rootCtx + oldCmdCtx := cmdCtx + defer func() { + rootCtx = oldRootCtx + cmdCtx = oldCmdCtx + }() + + t.Run("returns background when rootCtx is nil", func(t *testing.T) { + rootCtx = nil + cmdCtx = &CommandContext{} + + ctx := getRootContext() + if ctx == nil { + t.Fatal("getRootContext() returned nil, expected context.Background()") + } + }) + + t.Run("returns rootCtx when set", func(t *testing.T) { + expected := context.WithValue(context.Background(), "test", "value") + rootCtx = expected + cmdCtx = &CommandContext{} + + ctx := getRootContext() + if ctx != expected { + t.Errorf("getRootContext() = %v, want %v", ctx, expected) + } + }) + + t.Run("returns cmdCtx.RootCtx when globals disabled", func(t *testing.T) { + expected := context.WithValue(context.Background(), "cmd", "ctx") + rootCtx = nil + cmdCtx = &CommandContext{RootCtx: expected} + + ctx := getRootContext() + if ctx == nil { + t.Fatal("getRootContext() returned nil") + } + }) +}