Skip to content

Commit 70ee1e2

Browse files
aledbfclaude
andcommitted
refactor(compose): drop dead code (Down, v1 fallback, IsV2)
Cleanups surfaced during the self-containment review: - Remove ComposeClient.Down() — never called from non-test code (only an arg-builder test exercised it). - Remove the Compose v1 (`docker-compose`) detection fallback in NewComposeClient. Compose is v2-only by scope; v2 is required and the v1 path was never taken (the parity matrix pins v2). --docker-compose-path is still accepted (flag parity) and now only surfaces in the not-found error. - Remove the write-only IsV2 field (set, never read). - Drop the stale Config() comment about YAML output (it always requests --format json). The version-gated helpers (UsesNewProjectNames, SupportsAdditionalContexts, ToProjectName) stay — they serve v2 sub-version differences and are used by up/build/exec. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 7cf85a4 commit 70ee1e2

2 files changed

Lines changed: 8 additions & 64 deletions

File tree

‎internal/docker/argbuilders_test.go‎

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,6 @@ func TestFindDockerDriverBuilder(t *testing.T) {
167167
func newComposeV2(rr *recordingRunner, version []int) *ComposeClient {
168168
return &ComposeClient{
169169
Command: []string{"docker", "compose"},
170-
IsV2: true,
171170
Version: version,
172171
Log: log.Null,
173172
Runner: rr,
@@ -283,24 +282,6 @@ func TestComposeUp_NoProjectNoRecreate(t *testing.T) {
283282
}
284283
}
285284

286-
func TestComposeDown_Args(t *testing.T) {
287-
rr := &recordingRunner{}
288-
c := newComposeV2(rr, []int{2, 24, 0})
289-
if err := c.Down([]string{"c.yml"}, ".env", []string{"--timeout", "5"}, "proj"); err != nil {
290-
t.Fatalf("Down error: %v", err)
291-
}
292-
want := []string{"compose",
293-
"-f", "c.yml",
294-
"--env-file", ".env",
295-
"--project-name", "proj",
296-
"--timeout", "5",
297-
"down",
298-
}
299-
if !reflect.DeepEqual(rr.last().args, want) {
300-
t.Errorf("down args =\n %v\nwant\n %v", rr.last().args, want)
301-
}
302-
}
303-
304285
func TestComposeConfig_ArgsAndParse(t *testing.T) {
305286
rr := &recordingRunner{responses: []cannedResponse{
306287
{stdout: []byte(`{"services":{"app":{"image":"x"}}}`), code: 0},

‎internal/docker/compose.go‎

Lines changed: 8 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@ import (
1515

1616
// ComposeClient wraps Docker Compose CLI (v1 or v2).
1717
type ComposeClient struct {
18-
// Command is either ["docker-compose"] (v1) or ["docker", "compose"] (v2)
18+
// Command is ["docker", "compose"] (Compose v2).
1919
Command []string
20-
IsV2 bool
2120
Version []int // parsed version e.g. [2, 24, 0]
2221
Env []string
2322
Log log.Log
@@ -26,40 +25,25 @@ type ComposeClient struct {
2625
Runner exec.Runner
2726
}
2827

29-
// NewComposeClient detects the compose CLI and returns a client.
28+
// NewComposeClient detects Compose v2 (`docker compose`) and returns a client.
29+
// Compose v1 (`docker-compose`) is out of scope for this CLI; --docker-compose-path
30+
// is accepted for flag parity but only surfaces in the not-found error.
3031
func NewComposeClient(dockerPath, composePath string, env []string, logger log.Log) (*ComposeClient, error) {
31-
if composePath == "" {
32-
composePath = "docker-compose"
33-
}
3432
if dockerPath == "" {
3533
dockerPath = "docker"
3634
}
37-
38-
// Try docker compose (v2) first
3935
if out, err := osexec.Command(dockerPath, "compose", "version", "--short").Output(); err == nil {
40-
version := strings.TrimSpace(string(out))
4136
return &ComposeClient{
4237
Command: []string{dockerPath, "compose"},
43-
IsV2: true,
44-
Version: parseComposeVersion(version),
38+
Version: parseComposeVersion(strings.TrimSpace(string(out))),
4539
Env: env,
4640
Log: logger,
4741
}, nil
4842
}
49-
50-
// Fall back to docker-compose (v1)
51-
if out, err := osexec.Command(composePath, "version", "--short").Output(); err == nil {
52-
version := strings.TrimSpace(string(out))
53-
return &ComposeClient{
54-
Command: []string{composePath},
55-
IsV2: false,
56-
Version: parseComposeVersion(version),
57-
Env: env,
58-
Log: logger,
59-
}, nil
43+
if composePath != "" {
44+
return nil, fmt.Errorf("'docker compose' (v2) not found; --docker-compose-path %q is Compose v1, which is unsupported", composePath)
6045
}
61-
62-
return nil, fmt.Errorf("neither 'docker compose' nor '%s' found", composePath)
46+
return nil, fmt.Errorf("'docker compose' (v2) not found")
6347
}
6448

6549
// Run executes a compose command.
@@ -105,8 +89,6 @@ func (c *ComposeClient) Config(composeFiles []string, envFile string) (map[strin
10589

10690
var config map[string]interface{}
10791
if err := json.Unmarshal(res.Stdout, &config); err != nil {
108-
// compose config outputs YAML, but json might work for v2
109-
// For simplicity we'll handle the raw output
11092
return nil, fmt.Errorf("parse compose config: %w", err)
11193
}
11294
return config, nil
@@ -155,25 +137,6 @@ func (c *ComposeClient) Up(composeFiles []string, envFile string, globalArgs []s
155137
return nil
156138
}
157139

158-
// Down runs `docker compose down`.
159-
func (c *ComposeClient) Down(composeFiles []string, envFile string, globalArgs []string, projectName string) error {
160-
args := c.buildGlobalArgs(composeFiles, envFile)
161-
if projectName != "" {
162-
args = append(args, "--project-name", projectName)
163-
}
164-
args = append(args, globalArgs...)
165-
args = append(args, "down")
166-
167-
res, err := c.Run(args...)
168-
if err != nil {
169-
return err
170-
}
171-
if res.ExitCode != 0 {
172-
return fmt.Errorf("compose down failed (exit %d): %s", res.ExitCode, string(res.Stderr))
173-
}
174-
return nil
175-
}
176-
177140
// SupportsAdditionalContexts returns true if compose version >= 2.17.0.
178141
func (c *ComposeClient) SupportsAdditionalContexts() bool {
179142
if len(c.Version) < 2 {

0 commit comments

Comments
 (0)