From 4b0fc9c16463f2e320460c7a69009f76bc91dc4f Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Fri, 6 Feb 2026 11:38:54 +0000 Subject: [PATCH] cmd/hi: fix contextcheck issues Propagate context through function call chains to enable proper cancellation and timeout handling: - createDockerClient: accept context parameter - getCurrentDockerContext: use exec.CommandContext - NewStatsCollector: accept context parameter - checkGoInstallation, checkGitRepository, checkRequiredFiles: accept context and use exec.CommandContext - Update all call sites in cleanup.go and doctor.go --- cmd/hi/cleanup.go | 12 ++++++------ cmd/hi/docker.go | 14 +++++++------- cmd/hi/doctor.go | 28 ++++++++++++++-------------- cmd/hi/stats.go | 4 ++-- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/cmd/hi/cleanup.go b/cmd/hi/cleanup.go index 946815c1..9d3bee3a 100644 --- a/cmd/hi/cleanup.go +++ b/cmd/hi/cleanup.go @@ -55,7 +55,7 @@ func cleanupAfterTest(ctx context.Context, cli *client.Client, containerID, runI // killTestContainers terminates and removes all test containers. func killTestContainers(ctx context.Context) error { - cli, err := createDockerClient() + cli, err := createDockerClient(ctx) if err != nil { return fmt.Errorf("creating Docker client: %w", err) } @@ -109,7 +109,7 @@ func killTestContainers(ctx context.Context) error { // This function filters containers by the hi.run-id label to only affect containers // belonging to the specified test run, leaving other concurrent test runs untouched. func killTestContainersByRunID(ctx context.Context, runID string) error { - cli, err := createDockerClient() + cli, err := createDockerClient(ctx) if err != nil { return fmt.Errorf("creating Docker client: %w", err) } @@ -151,7 +151,7 @@ func killTestContainersByRunID(ctx context.Context, runID string) error { // This is useful for cleaning up leftover containers from previous crashed or interrupted test runs // without interfering with currently running concurrent tests. func cleanupStaleTestContainers(ctx context.Context) error { - cli, err := createDockerClient() + cli, err := createDockerClient(ctx) if err != nil { return fmt.Errorf("creating Docker client: %w", err) } @@ -225,7 +225,7 @@ func removeContainerWithRetry(ctx context.Context, cli *client.Client, container // pruneDockerNetworks removes unused Docker networks. func pruneDockerNetworks(ctx context.Context) error { - cli, err := createDockerClient() + cli, err := createDockerClient(ctx) if err != nil { return fmt.Errorf("creating Docker client: %w", err) } @@ -247,7 +247,7 @@ func pruneDockerNetworks(ctx context.Context) error { // cleanOldImages removes test-related and old dangling Docker images. func cleanOldImages(ctx context.Context) error { - cli, err := createDockerClient() + cli, err := createDockerClient(ctx) if err != nil { return fmt.Errorf("creating Docker client: %w", err) } @@ -299,7 +299,7 @@ func cleanOldImages(ctx context.Context) error { // cleanCacheVolume removes the Docker volume used for Go module cache. func cleanCacheVolume(ctx context.Context) error { - cli, err := createDockerClient() + cli, err := createDockerClient(ctx) if err != nil { return fmt.Errorf("creating Docker client: %w", err) } diff --git a/cmd/hi/docker.go b/cmd/hi/docker.go index f7ea957a..c402f578 100644 --- a/cmd/hi/docker.go +++ b/cmd/hi/docker.go @@ -33,7 +33,7 @@ var ( // runTestContainer executes integration tests in a Docker container. func runTestContainer(ctx context.Context, config *RunConfig) error { - cli, err := createDockerClient() + cli, err := createDockerClient(ctx) if err != nil { return fmt.Errorf("creating Docker client: %w", err) } @@ -104,7 +104,7 @@ func runTestContainer(ctx context.Context, config *RunConfig) error { if config.Stats { var err error - statsCollector, err = NewStatsCollector() + statsCollector, err = NewStatsCollector(ctx) if err != nil { if config.Verbose { log.Printf("Warning: failed to create stats collector: %v", err) @@ -447,8 +447,8 @@ type DockerContext struct { } // createDockerClient creates a Docker client with context detection. -func createDockerClient() (*client.Client, error) { - contextInfo, err := getCurrentDockerContext() +func createDockerClient(ctx context.Context) (*client.Client, error) { + contextInfo, err := getCurrentDockerContext(ctx) if err != nil { return client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) } @@ -479,8 +479,8 @@ func createDockerClient() (*client.Client, error) { } // getCurrentDockerContext retrieves the current Docker context information. -func getCurrentDockerContext() (*DockerContext, error) { - cmd := exec.CommandContext(context.Background(), "docker", "context", "inspect") +func getCurrentDockerContext(ctx context.Context) (*DockerContext, error) { + cmd := exec.CommandContext(ctx, "docker", "context", "inspect") output, err := cmd.Output() if err != nil { @@ -626,7 +626,7 @@ func listControlFiles(logsDir string) { // extractArtifactsFromContainers collects container logs and files from the specific test run. func extractArtifactsFromContainers(ctx context.Context, testContainerID, logsDir string, verbose bool) error { - cli, err := createDockerClient() + cli, err := createDockerClient(ctx) if err != nil { return fmt.Errorf("creating Docker client: %w", err) } diff --git a/cmd/hi/doctor.go b/cmd/hi/doctor.go index c30a1ca9..1791d66d 100644 --- a/cmd/hi/doctor.go +++ b/cmd/hi/doctor.go @@ -38,13 +38,13 @@ func runDoctorCheck(ctx context.Context) error { } // Check 3: Go installation - results = append(results, checkGoInstallation()) + results = append(results, checkGoInstallation(ctx)) // Check 4: Git repository - results = append(results, checkGitRepository()) + results = append(results, checkGitRepository(ctx)) // Check 5: Required files - results = append(results, checkRequiredFiles()) + results = append(results, checkRequiredFiles(ctx)) // Display results displayDoctorResults(results) @@ -86,7 +86,7 @@ func checkDockerBinary() DoctorResult { // checkDockerDaemon verifies Docker daemon is running and accessible. func checkDockerDaemon(ctx context.Context) DoctorResult { - cli, err := createDockerClient() + cli, err := createDockerClient(ctx) if err != nil { return DoctorResult{ Name: "Docker Daemon", @@ -124,8 +124,8 @@ func checkDockerDaemon(ctx context.Context) DoctorResult { } // checkDockerContext verifies Docker context configuration. -func checkDockerContext(_ context.Context) DoctorResult { - contextInfo, err := getCurrentDockerContext() +func checkDockerContext(ctx context.Context) DoctorResult { + contextInfo, err := getCurrentDockerContext(ctx) if err != nil { return DoctorResult{ Name: "Docker Context", @@ -155,7 +155,7 @@ func checkDockerContext(_ context.Context) DoctorResult { // checkDockerSocket verifies Docker socket accessibility. func checkDockerSocket(ctx context.Context) DoctorResult { - cli, err := createDockerClient() + cli, err := createDockerClient(ctx) if err != nil { return DoctorResult{ Name: "Docker Socket", @@ -192,7 +192,7 @@ func checkDockerSocket(ctx context.Context) DoctorResult { // checkGolangImage verifies the golang Docker image is available locally or can be pulled. func checkGolangImage(ctx context.Context) DoctorResult { - cli, err := createDockerClient() + cli, err := createDockerClient(ctx) if err != nil { return DoctorResult{ Name: "Golang Image", @@ -251,7 +251,7 @@ func checkGolangImage(ctx context.Context) DoctorResult { } // checkGoInstallation verifies Go is installed and working. -func checkGoInstallation() DoctorResult { +func checkGoInstallation(ctx context.Context) DoctorResult { _, err := exec.LookPath("go") if err != nil { return DoctorResult{ @@ -265,7 +265,7 @@ func checkGoInstallation() DoctorResult { } } - cmd := exec.CommandContext(context.Background(), "go", "version") + cmd := exec.CommandContext(ctx, "go", "version") output, err := cmd.Output() if err != nil { @@ -286,8 +286,8 @@ func checkGoInstallation() DoctorResult { } // checkGitRepository verifies we're in a git repository. -func checkGitRepository() DoctorResult { - cmd := exec.CommandContext(context.Background(), "git", "rev-parse", "--git-dir") +func checkGitRepository(ctx context.Context) DoctorResult { + cmd := exec.CommandContext(ctx, "git", "rev-parse", "--git-dir") err := cmd.Run() if err != nil { @@ -310,7 +310,7 @@ func checkGitRepository() DoctorResult { } // checkRequiredFiles verifies required files exist. -func checkRequiredFiles() DoctorResult { +func checkRequiredFiles(ctx context.Context) DoctorResult { requiredFiles := []string{ "go.mod", "integration/", @@ -320,7 +320,7 @@ func checkRequiredFiles() DoctorResult { var missingFiles []string for _, file := range requiredFiles { - cmd := exec.CommandContext(context.Background(), "test", "-e", file) + cmd := exec.CommandContext(ctx, "test", "-e", file) err := cmd.Run() if err != nil { diff --git a/cmd/hi/stats.go b/cmd/hi/stats.go index 9da6d5a8..715c2308 100644 --- a/cmd/hi/stats.go +++ b/cmd/hi/stats.go @@ -47,8 +47,8 @@ type StatsCollector struct { } // NewStatsCollector creates a new stats collector instance. -func NewStatsCollector() (*StatsCollector, error) { - cli, err := createDockerClient() +func NewStatsCollector(ctx context.Context) (*StatsCollector, error) { + cli, err := createDockerClient(ctx) if err != nil { return nil, fmt.Errorf("creating Docker client: %w", err) }