Skip to content

Commit e08e7de

Browse files
authored
Merge branch 'main' into main
2 parents 6b433c4 + e8c2143 commit e08e7de

8 files changed

Lines changed: 234 additions & 49 deletions

File tree

.go-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.25.7
1+
1.25.8

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# See the License for the specific language governing permissions and
1616
# limitations under the License.
1717

18-
ARG GO_VERSION=1.25.7
18+
ARG GO_VERSION=1.25.8
1919
ARG XX_VERSION=1.9.0
2020
ARG GOLANGCI_LINT_VERSION=v2.8.0
2121
ARG ADDLICENSE_VERSION=v1.0.0

cmd/display/tty.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,9 @@ func (w *ttyWriter) Done(operation string, success bool) {
178178
w.print()
179179
w.mtx.Lock()
180180
defer w.mtx.Unlock()
181-
w.ticker.Stop()
181+
if w.ticker != nil {
182+
w.ticker.Stop()
183+
}
182184
w.operation = ""
183185
w.done <- true
184186
}
@@ -202,12 +204,14 @@ func (w *ttyWriter) On(events ...api.Resource) {
202204

203205
func (w *ttyWriter) event(e api.Resource) {
204206
// Suspend print while a build is in progress, to avoid collision with buildkit Display
205-
if e.Text == api.StatusBuilding {
206-
w.ticker.Stop()
207-
w.suspended = true
208-
} else if w.suspended {
209-
w.ticker.Reset(100 * time.Millisecond)
210-
w.suspended = false
207+
if w.ticker != nil {
208+
if e.Text == api.StatusBuilding {
209+
w.ticker.Stop()
210+
w.suspended = true
211+
} else if w.suspended {
212+
w.ticker.Reset(100 * time.Millisecond)
213+
w.suspended = false
214+
}
211215
}
212216

213217
if last, ok := w.tasks[e.ID]; ok {

go.mod

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ require (
1010
github.com/buger/goterm v1.0.4
1111
github.com/compose-spec/compose-go/v2 v2.10.1
1212
github.com/containerd/console v1.0.5
13-
github.com/containerd/containerd/v2 v2.2.1
13+
github.com/containerd/containerd/v2 v2.2.2
1414
github.com/containerd/errdefs v1.0.0
1515
github.com/containerd/platforms v1.0.0-rc.2
1616
github.com/distribution/reference v0.6.0
@@ -30,8 +30,8 @@ require (
3030
github.com/mitchellh/go-ps v1.0.0
3131
github.com/moby/buildkit v0.27.1
3232
github.com/moby/go-archive v0.2.0
33-
github.com/moby/moby/api v1.53.0
34-
github.com/moby/moby/client v0.2.2
33+
github.com/moby/moby/api v1.54.0
34+
github.com/moby/moby/client v0.3.0
3535
github.com/moby/patternmatcher v0.6.0
3636
github.com/moby/sys/atomicwriter v0.1.0
3737
github.com/morikuni/aec v1.1.0
@@ -54,8 +54,8 @@ require (
5454
go.uber.org/goleak v1.3.0
5555
go.uber.org/mock v0.6.0
5656
go.yaml.in/yaml/v4 v4.0.0-rc.4
57-
golang.org/x/sync v0.19.0
58-
golang.org/x/sys v0.41.0
57+
golang.org/x/sync v0.20.0
58+
golang.org/x/sys v0.42.0
5959
google.golang.org/grpc v1.78.0
6060
gotest.tools/v3 v3.5.2
6161
tags.cncf.io/container-device-interface v1.1.0

go.sum

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/q
4040
github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
4141
github.com/containerd/containerd/api v1.10.0 h1:5n0oHYVBwN4VhoX9fFykCV9dF1/BvAXeg2F8W6UYq1o=
4242
github.com/containerd/containerd/api v1.10.0/go.mod h1:NBm1OAk8ZL+LG8R0ceObGxT5hbUYj7CzTmR3xh0DlMM=
43-
github.com/containerd/containerd/v2 v2.2.1 h1:TpyxcY4AL5A+07dxETevunVS5zxqzuq7ZqJXknM11yk=
44-
github.com/containerd/containerd/v2 v2.2.1/go.mod h1:NR70yW1iDxe84F2iFWbR9xfAN0N2F0NcjTi1OVth4nU=
43+
github.com/containerd/containerd/v2 v2.2.2 h1:mjVQdtfryzT7lOqs5EYUFZm8ioPVjOpkSoG1GJPxEMY=
44+
github.com/containerd/containerd/v2 v2.2.2/go.mod h1:5Jhevmv6/2J+Iu/A2xXAdUIdI5Ah/hfyO7okJ4AFIdY=
4545
github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
4646
github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
4747
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
@@ -238,10 +238,10 @@ github.com/moby/go-archive v0.2.0 h1:zg5QDUM2mi0JIM9fdQZWC7U8+2ZfixfTYoHL7rWUcP8
238238
github.com/moby/go-archive v0.2.0/go.mod h1:mNeivT14o8xU+5q1YnNrkQVpK+dnNe/K6fHqnTg4qPU=
239239
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
240240
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
241-
github.com/moby/moby/api v1.53.0 h1:PihqG1ncw4W+8mZs69jlwGXdaYBeb5brF6BL7mPIS/w=
242-
github.com/moby/moby/api v1.53.0/go.mod h1:8mb+ReTlisw4pS6BRzCMts5M49W5M7bKt1cJy/YbAqc=
243-
github.com/moby/moby/client v0.2.2 h1:Pt4hRMCAIlyjL3cr8M5TrXCwKzguebPAc2do2ur7dEM=
244-
github.com/moby/moby/client v0.2.2/go.mod h1:2EkIPVNCqR05CMIzL1mfA07t0HvVUUOl85pasRz/GmQ=
241+
github.com/moby/moby/api v1.54.0 h1:7kbUgyiKcoBhm0UrWbdrMs7RX8dnwzURKVbZGy2GnL0=
242+
github.com/moby/moby/api v1.54.0/go.mod h1:8mb+ReTlisw4pS6BRzCMts5M49W5M7bKt1cJy/YbAqc=
243+
github.com/moby/moby/client v0.3.0 h1:UUGL5okry+Aomj3WhGt9Aigl3ZOxZGqR7XPo+RLPlKs=
244+
github.com/moby/moby/client v0.3.0/go.mod h1:HJgFbJRvogDQjbM8fqc1MCEm4mIAGMLjXbgwoZp6jCQ=
245245
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
246246
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
247247
github.com/moby/sys/atomicwriter v0.1.0 h1:kw5D/EqkBwsBFi0ss9v1VG3wIkVhzGvLklJ+w3A14Sw=
@@ -430,8 +430,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
430430
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
431431
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
432432
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
433-
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
434-
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
433+
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
434+
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
435435
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
436436
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
437437
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -445,8 +445,8 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
445445
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
446446
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
447447
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
448-
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
449-
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
448+
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
449+
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
450450
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
451451
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
452452
golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=

pkg/compose/hook.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,17 @@ func (s composeService) runHook(ctx context.Context, ctr container.Summary, serv
6161
return s.runWaitExec(ctx, exec.ID, service, listener)
6262
}
6363

64-
height, width := s.stdout().GetTtySize()
65-
consoleSize := client.ConsoleSize{
66-
Width: width,
67-
Height: height,
64+
attachOptions := client.ExecAttachOptions{
65+
TTY: service.Tty,
6866
}
69-
attach, err := s.apiClient().ExecAttach(ctx, exec.ID, client.ExecAttachOptions{
70-
TTY: service.Tty,
71-
ConsoleSize: consoleSize,
72-
})
67+
if service.Tty {
68+
height, width := s.stdout().GetTtySize()
69+
attachOptions.ConsoleSize = client.ConsoleSize{
70+
Width: width,
71+
Height: height,
72+
}
73+
}
74+
attach, err := s.apiClient().ExecAttach(ctx, exec.ID, attachOptions)
7375
if err != nil {
7476
return err
7577
}

pkg/compose/hook_test.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*
2+
Copyright 2020 Docker Compose CLI authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package compose
18+
19+
import (
20+
"net"
21+
"os"
22+
"testing"
23+
24+
"github.com/compose-spec/compose-go/v2/types"
25+
"github.com/containerd/console"
26+
"github.com/docker/cli/cli/streams"
27+
"github.com/moby/moby/api/types/container"
28+
"github.com/moby/moby/client"
29+
"go.uber.org/mock/gomock"
30+
"gotest.tools/v3/assert"
31+
32+
"github.com/docker/compose/v5/pkg/api"
33+
"github.com/docker/compose/v5/pkg/mocks"
34+
)
35+
36+
// TestRunHook_ConsoleSize verifies that ConsoleSize is only passed to ExecAttach
37+
// when the service has TTY enabled. When TTY is disabled, passing a non-zero
38+
// ConsoleSize causes the Docker daemon to return "console size is only supported
39+
// when TTY is enabled" (regression introduced in v5.1.0).
40+
func TestRunHook_ConsoleSize(t *testing.T) {
41+
tests := []struct {
42+
name string
43+
tty bool
44+
expectedConsole client.ConsoleSize
45+
}{
46+
{
47+
name: "no tty - ConsoleSize must be zero",
48+
tty: false,
49+
expectedConsole: client.ConsoleSize{},
50+
},
51+
{
52+
name: "with tty - ConsoleSize should reflect terminal dimensions",
53+
tty: true,
54+
expectedConsole: client.ConsoleSize{Width: 80, Height: 24},
55+
},
56+
}
57+
58+
for _, tc := range tests {
59+
t.Run(tc.name, func(t *testing.T) {
60+
mockCtrl := gomock.NewController(t)
61+
defer mockCtrl.Finish()
62+
63+
mockAPI := mocks.NewMockAPIClient(mockCtrl)
64+
mockCli := mocks.NewMockCli(mockCtrl)
65+
mockCli.EXPECT().Client().Return(mockAPI).AnyTimes()
66+
mockCli.EXPECT().Err().Return(streams.NewOut(os.Stderr)).AnyTimes()
67+
68+
// Create a PTY so GetTtySize() returns real non-zero dimensions,
69+
// simulating an interactive terminal session.
70+
pty, slavePath, err := console.NewPty()
71+
assert.NilError(t, err)
72+
defer pty.Close() //nolint:errcheck
73+
assert.NilError(t, pty.Resize(console.WinSize{Height: 24, Width: 80}))
74+
75+
slaveFile, err := os.OpenFile(slavePath, os.O_RDWR, 0)
76+
assert.NilError(t, err)
77+
defer slaveFile.Close() //nolint:errcheck
78+
79+
mockCli.EXPECT().Out().Return(streams.NewOut(slaveFile)).AnyTimes()
80+
81+
service := types.ServiceConfig{
82+
Name: "test",
83+
Tty: tc.tty,
84+
}
85+
hook := types.ServiceHook{Command: []string{"echo", "hello"}}
86+
ctr := container.Summary{ID: "container123"}
87+
88+
mockAPI.EXPECT().
89+
ExecCreate(gomock.Any(), "container123", gomock.Any()).
90+
Return(client.ExecCreateResult{ID: "exec123"}, nil)
91+
92+
// Return a pipe that immediately closes so the reader gets EOF.
93+
serverConn, clientConn := net.Pipe()
94+
serverConn.Close() //nolint:errcheck
95+
mockAPI.EXPECT().
96+
ExecAttach(gomock.Any(), "exec123", client.ExecAttachOptions{
97+
TTY: tc.tty,
98+
ConsoleSize: tc.expectedConsole,
99+
}).
100+
Return(client.ExecAttachResult{
101+
HijackedResponse: client.NewHijackedResponse(clientConn, ""),
102+
}, nil)
103+
104+
mockAPI.EXPECT().
105+
ExecInspect(gomock.Any(), "exec123", gomock.Any()).
106+
Return(client.ExecInspectResult{ExitCode: 0}, nil)
107+
108+
s, err := NewComposeService(mockCli)
109+
assert.NilError(t, err)
110+
111+
noopListener := func(api.ContainerEvent) {}
112+
err = s.(*composeService).runHook(t.Context(), ctr, service, hook, noopListener)
113+
assert.NilError(t, err)
114+
})
115+
}
116+
}

0 commit comments

Comments
 (0)