Skip to content

deploy local: abort immediately when Docker is unavailable#75

Merged
ewega merged 3 commits intomainfrom
copilot/fix-docker-check-issue
Mar 2, 2026
Merged

deploy local: abort immediately when Docker is unavailable#75
ewega merged 3 commits intomainfrom
copilot/fix-docker-check-issue

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 2, 2026

  • Replace inline Docker check with dockerpkg.CheckAvailable() and abort on failure
  • Return clean, non-wrapping error string so Cobra doesn't print raw exec output to stderr
  • go build ./..., go test ./..., go vet ./... all pass
Original prompt

This section details on the original issue you should resolve

<issue_title>deploy local: Docker check should abort when Docker is unavailable</issue_title>
<issue_description>## Problem

gh devlake deploy local checks Docker availability and prints a warning when Docker Desktop isn't running, but then proceeds to call docker compose up anyway. This produces a confusing low-level pipe error:

🐳 Checking Docker...
   ⚠️  Docker not found or not running
   Install Docker Desktop: https://docs.docker.com/get-docker

🐳 Building and starting containers in C:\Users\eldrickt\devlake-local...
   (Building from source — this may take a few minutes on first run)

Error: docker compose up failed: exit status 1
...
open //./pipe/dockerDesktopLinuxEngine: The system cannot find the file specified.

The Docker check at cmd/deploy_local.go:173-179 is a non-blocking warning — it never gates the startLocalContainers() call that follows.

Additionally, internal/docker/build.go defines a CheckAvailable() helper that is never called anywhere.

Proposed Solution

  1. Abort early when Docker is not available — return a clear error instead of continuing to docker compose up.
  2. Use docker.CheckAvailable() from internal/docker/build.go instead of the inline check — DRY up the duplicate logic.
  3. Improve the error message — tell the user exactly what to do (start Docker Desktop, then re-run) rather than dumping raw docker compose output.

Expected behavior after fix:

🐳 Checking Docker...
   ❌ Docker not found or not running
   Install Docker Desktop: https://docs.docker.com/get-docker
   Start Docker Desktop, then re-run: gh devlake deploy local

(command exits with non-zero status, no docker compose up attempt)

Scope of Changes

  • cmd/deploy_local.go — replace inline Docker check with docker.CheckAvailable() call; return error on failure instead of printing ⚠️ and continuing.
  • internal/docker/build.go — no changes needed (helper already exists).

Acceptance Criteria

  • When Docker is not running, deploy local aborts immediately after the check with a clear error message
  • No docker compose up attempt is made when Docker is unavailable
  • docker.CheckAvailable() is used instead of inline exec.Command check
  • go build ./..., go test ./..., go vet ./... all pass</issue_description>

<agent_instructions>## Context
This is issue #69 (Docker check should abort when Docker is unavailable) for the gh-devlake CLI — a Go + Cobra GitHub CLI extension.

What to do

  1. In cmd/deploy_local.go, replace the inline Docker availability check (around line 173-179) with a call to docker.CheckAvailable() from internal/docker/build.go.
  2. When docker.CheckAvailable() returns an error, abort immediately with a clear error message — do NOT continue to startLocalContainers().
  3. The error message format should be:
🐳 Checking Docker...
   ❌ Docker not found or not running
   Install Docker Desktop: https://docs.docker.com/get-docker
   Start Docker Desktop, then re-run: gh devlake deploy local
  1. Return fmt.Errorf(...) (non-zero exit) — don't just print and continue.

Existing helper

internal/docker/build.go already has:

func CheckAvailable() error {
    out, err := exec.Command("docker", "version", "--format", "{{.Server.Version}}").Output()
    if err != nil {
        return fmt.Errorf("docker not available: %w", err)
    }
    version := strings.TrimSpace(string(out))
    if version == "" {
        return fmt.Errorf("docker daemon not running")
    }
    return nil
}

Key conventions

  • Import the docker package: "github.com/DevExpGBB/gh-devlake/internal/docker"
  • Imports: stdlib → external → internal, separated by blank lines
  • Terminal output: blank line before emoji-prefixed steps, 3-space indent for sub-items
  • Error wrapping: fmt.Errorf("context: %w", err)
  • The cleanup.go references to docker compose down are fine — those are internal status messages

Validation

Run go build ./..., go test ./..., and go vet ./... before completing.</agent_instructions>

Comments on the Issue (you are @copilot in this section)


🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

Co-authored-by: ewega <26189114+ewega@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix Docker check to abort if Docker is unavailable deploy local: abort immediately when Docker is unavailable Mar 2, 2026
Copilot finished work on behalf of ewega March 2, 2026 11:17
@ewega ewega requested a review from Copilot March 2, 2026 11:29
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves the gh devlake deploy local UX by making the Docker availability check blocking and reusing the existing shared Docker helper, preventing a confusing docker compose up failure path when Docker isn’t running.

Changes:

  • Replaced the inline docker version availability check with internal/docker.CheckAvailable().
  • Aborts deploy local immediately when Docker is unavailable, after printing actionable guidance.

Comment on lines +174 to +178
if err := dockerpkg.CheckAvailable(); err != nil {
fmt.Println(" ❌ Docker not found or not running")
fmt.Println(" Install Docker Desktop: https://docs.docker.com/get-docker")
} else {
fmt.Printf(" ✅ Docker %s found\n", strings.TrimSpace(string(dockerOut)))
fmt.Println(" Start Docker Desktop, then re-run: gh devlake deploy local")
return fmt.Errorf("docker unavailable: %w", err)
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

runDeployLocal prints the friendly Docker guidance, but then returns a wrapped error (docker unavailable: %w). Because cmd.Execute() always prints the returned error to stderr, users will still see a trailing low-level docker version failure (often including the Windows named-pipe message) which undermines the goal of avoiding confusing output. Consider returning a concise, user-facing error string (without wrapping the underlying exec error), or using a dedicated error type/handling path that preserves the underlying error for debugging while keeping the default terminal message clean.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 7cefc6b — the return now uses fmt.Errorf("Docker is not available — start Docker Desktop and retry") (no %w wrapping), so Cobra only prints the clean message to stderr and the raw exec/pipe error is suppressed.

@ewega
Copy link
Copy Markdown
Contributor

ewega commented Mar 2, 2026

@copilot Fix the error return so users don't see ugly low-level output:

When Docker is unavailable, runDeployLocal prints the friendly guidance (❌ Docker not found, install link, re-run hint) but then returns a wrapped error like docker unavailable: docker not available: exec: "docker": .... Cobra's Execute() prints returned errors to stderr, so users see BOTH the nice message AND the raw pipe/exec error.

Fix: After printing the user-friendly guidance, return a clean, concise error without wrapping the underlying exec error. For example:

fmt.Println("\n🐳 Checking Docker...")
if err := docker.CheckAvailable(); err != nil {
    fmt.Println("   ❌ Docker not found or not running")
    fmt.Println("   Install Docker Desktop: https://docs.docker.com/get-docker")
    fmt.Println("   Start Docker Desktop, then re-run: gh devlake deploy local")
    return fmt.Errorf("Docker is not available — start Docker Desktop and retry")
}

The key change: fmt.Errorf("Docker is not available — start Docker Desktop and retry") instead of fmt.Errorf("docker unavailable: %w", err). This keeps the Cobra stderr output clean and human-readable.

Co-authored-by: ewega <26189114+ewega@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 2, 2026

@copilot Fix the error return so users don't see ugly low-level output:

When Docker is unavailable, runDeployLocal prints the friendly guidance (❌ Docker not found, install link, re-run hint) but...

Done in 7cefc6b — changed to fmt.Errorf("Docker is not available — start Docker Desktop and retry") exactly as suggested, dropping the %w wrap so Cobra's stderr output stays clean.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

@ewega ewega marked this pull request as ready for review March 2, 2026 12:45
@ewega ewega merged commit f15150b into main Mar 2, 2026
4 checks passed
@ewega ewega deleted the copilot/fix-docker-check-issue branch March 2, 2026 12:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

deploy local: Docker check should abort when Docker is unavailable

3 participants