Compare commits

...

16 Commits

Author SHA1 Message Date
dependabot[bot] 0dc9852c67 build(deps): bump github.com/docker/docker
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 28.3.2+incompatible to 28.3.3+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v28.3.2...v28.3.3)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-version: 28.3.3+incompatible
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-30 11:39:57 +02:00
dependabot[bot] a478702236 build(deps): bump github.com/docker/cli
Bumps [github.com/docker/cli](https://github.com/docker/cli) from 28.3.2+incompatible to 28.3.3+incompatible.
- [Commits](https://github.com/docker/cli/compare/v28.3.2...v28.3.3)

---
updated-dependencies:
- dependency-name: github.com/docker/cli
  dependency-version: 28.3.3+incompatible
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-30 11:27:29 +02:00
Nicolas De Loof 2c12ad19db use log API for containers we didn't attached to
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2025-07-29 14:23:24 +02:00
Guillaume Lours 038ea8441a apply BUILDKIT_PROGRESS value when building with bake
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2025-07-29 11:45:33 +02:00
Guillaume Lours 9e98e6101e add missing _MODEL suffix to model variable pass to dependent services of a model
Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
2025-07-29 09:40:46 +02:00
keitosuwahara 52f04229c0 fixed lint error
Signed-off-by: keitosuwahara <keitosuwahara0816@gmail.com>
2025-07-28 10:07:03 +02:00
keitosuwahara 28895d0322 fix lint error
Signed-off-by: keitosuwahara <keitosuwahara0816@gmail.com>
2025-07-28 10:07:03 +02:00
keitosuwahara a926f7d717 Elimneted magic string
Signed-off-by: keitosuwahara <keitosuwahara0816@gmail.com>
2025-07-28 10:07:03 +02:00
Nicolas De Loof fe046915eb buildkit require os.Stdout to access the raw terminal
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
2025-07-28 09:25:35 +02:00
keitosuwahara adbd61e5d6 fixed lint error
Signed-off-by: keitosuwahara <keitosuwahara0816@gmail.com>
2025-07-27 19:36:40 +02:00
keitosuwahara e37ac04329 deleted useless comment
Signed-off-by: keitosuwahara <keitosuwahara0816@gmail.com>
2025-07-27 19:36:40 +02:00
keitosuwahara cab2c2a44e Refactoring of redundant condition checks
Signed-off-by: keitosuwahara <keitosuwahara0816@gmail.com>
2025-07-27 19:36:40 +02:00
keitosuwahara 1946de598d improved lint error
Signed-off-by: keitosuwahara <keitosuwahara0816@gmail.com>
2025-07-27 15:12:38 +02:00
keitosuwahara 8e29a138aa improved test
Signed-off-by: keitosuwahara <keitosuwahara0816@gmail.com>
2025-07-27 15:12:38 +02:00
keitosuwahara 3c8da0afee Add test of json.go
Signed-off-by: keitosuwahara <keitosuwahara0816@gmail.com>
2025-07-27 15:12:38 +02:00
keitosuwahara 1b12c867c5 add Streams Comment
Signed-off-by: keitosuwahara <keitosuwahara0816@gmail.com>
2025-07-27 14:57:43 +02:00
11 changed files with 178 additions and 50 deletions

4
go.mod
View File

@ -15,9 +15,9 @@ require (
github.com/davecgh/go-spew v1.1.1
github.com/distribution/reference v0.6.0
github.com/docker/buildx v0.26.1
github.com/docker/cli v28.3.2+incompatible
github.com/docker/cli v28.3.3+incompatible
github.com/docker/cli-docs-tool v0.10.0
github.com/docker/docker v28.3.2+incompatible
github.com/docker/docker v28.3.3+incompatible
github.com/docker/go-connections v0.5.0
github.com/docker/go-units v0.5.0
github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203

8
go.sum
View File

@ -129,15 +129,15 @@ github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxK
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/docker/buildx v0.26.1 h1:nlj3bVhHK9fV7g6floRvGhPcR0u2hxCPMmObCS1ZKL4=
github.com/docker/buildx v0.26.1/go.mod h1:oxMC30cSHPaCCkY2j+EqN7uxFikjSzVC0c44lo9b4Fo=
github.com/docker/cli v28.3.2+incompatible h1:mOt9fcLE7zaACbxW1GeS65RI67wIJrTnqS3hP2huFsY=
github.com/docker/cli v28.3.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli v28.3.3+incompatible h1:fp9ZHAr1WWPGdIWBM1b3zLtgCF+83gRdVMTJsUeiyAo=
github.com/docker/cli v28.3.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli-docs-tool v0.10.0 h1:bOD6mKynPQgojQi3s2jgcUWGp/Ebqy1SeCr9VfKQLLU=
github.com/docker/cli-docs-tool v0.10.0/go.mod h1:5EM5zPnT2E7yCLERZmrDA234Vwn09fzRHP4aX1qwp1U=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v28.3.2+incompatible h1:wn66NJ6pWB1vBZIilP8G3qQPqHy5XymfYn5vsqeA5oA=
github.com/docker/docker v28.3.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI=
github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.9.3 h1:gAm/VtF9wgqJMoxzT3Gj5p4AqIjCBS4wrsOh9yRqcz8=
github.com/docker/docker-credential-helpers v0.9.3/go.mod h1:x+4Gbw9aGmChi3qTLZj8Dfn0TD20M/fuWy0E5+WDeCo=
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=

View File

@ -20,6 +20,7 @@ import (
"github.com/docker/cli/cli/streams"
)
// Streams defines the standard streams (stdin, stdout, stderr) used by the CLI.
type Streams interface {
Out() *streams.Out
Err() *streams.Out

View File

@ -17,8 +17,6 @@
package api
import (
"fmt"
"github.com/hashicorp/go-version"
"github.com/docker/compose/v2/internal"
@ -65,9 +63,6 @@ var ComposeVersion string
func init() {
v, err := version.NewVersion(internal.Version)
if err == nil {
segments := v.Segments()
if len(segments) > 2 {
ComposeVersion = fmt.Sprintf("%d.%d.%d", segments[0], segments[1], segments[2])
}
ComposeVersion = v.Core().String()
}
}

35
pkg/api/labels_test.go Normal file
View File

@ -0,0 +1,35 @@
/*
Copyright 2020 Docker Compose CLI authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package api
import (
"testing"
"github.com/docker/compose/v2/internal"
"github.com/hashicorp/go-version"
"gotest.tools/v3/assert"
)
func TestComposeVersionInitialization(t *testing.T) {
v, err := version.NewVersion(internal.Version)
if err != nil {
assert.Equal(t, "", ComposeVersion, "ComposeVersion should be empty for a non-semver internal version (e.g. 'devel')")
} else {
expected := v.Core().String()
assert.Equal(t, expected, ComposeVersion, "ComposeVersion should be the core of internal.Version")
}
}

View File

@ -33,6 +33,8 @@ import (
const (
TransformerLabel = "com.docker.compose.bridge"
DefaultTransformerImage = "docker/compose-bridge-kubernetes"
templatesPath = "/templates"
)
type CreateTransformerOptions struct {
@ -73,7 +75,7 @@ func CreateTransformer(ctx context.Context, dockerCli command.Cli, options Creat
if err != nil {
return err
}
content, stat, err := dockerCli.Client().CopyFromContainer(ctx, created.ID, "/templates")
content, stat, err := dockerCli.Client().CopyFromContainer(ctx, created.ID, templatesPath)
if err != nil {
return err
}
@ -82,7 +84,7 @@ func CreateTransformer(ctx context.Context, dockerCli command.Cli, options Creat
}()
srcInfo := archive.CopyInfo{
Path: "/templates",
Path: templatesPath,
Exists: true,
IsDir: stat.Mode.IsDir(),
}

View File

@ -130,14 +130,16 @@ type buildStatus struct {
func (s *composeService) doBuildBake(ctx context.Context, project *types.Project, serviceToBeBuild types.Services, options api.BuildOptions) (map[string]string, error) { //nolint:gocyclo
eg := errgroup.Group{}
ch := make(chan *client.SolveStatus)
if options.Progress == progress.ModeAuto {
options.Progress = os.Getenv("BUILDKIT_PROGRESS")
}
displayMode := progressui.DisplayMode(options.Progress)
out := options.Out
if out == nil {
cout := s.dockerCli.Out()
if !cout.IsTerminal() {
if !s.dockerCli.Out().IsTerminal() {
displayMode = progressui.PlainMode
}
out = cout
out = os.Stdout // should be s.dockerCli.Out(), but NewDisplay require access to the underlying *File
}
display, err := progressui.NewDisplay(out, displayMode)
if err != nil {

View File

@ -195,7 +195,7 @@ func (m *modelAPI) SetModelVariables(ctx context.Context, project *types.Project
if modelConfig != nil && modelConfig.ModelVariable != "" {
variable = modelConfig.ModelVariable
} else {
variable = varPrefix
variable = varPrefix + "_MODEL"
}
service.Environment[variable] = &model.Model

View File

@ -28,7 +28,6 @@ import (
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/docker/api/types/filters"
"golang.org/x/sync/errgroup"
)
func (s *composeService) Start(ctx context.Context, projectName string, options api.StartOptions) error {
@ -52,18 +51,6 @@ func (s *composeService) start(ctx context.Context, projectName string, options
}
}
// use an independent context tied to the errgroup for background attach operations
// the primary context is still used for other operations
// this means that once any attach operation fails, all other attaches are cancelled,
// but an attach failing won't interfere with the rest of the start
eg, attachCtx := errgroup.WithContext(ctx)
if listener != nil {
_, err := s.attach(attachCtx, project, listener, options.AttachTo)
if err != nil {
return err
}
}
var containers Containers
containers, err := s.apiClient().ContainerList(ctx, containerType.ListOptions{
Filters: filters.NewArgs(
@ -111,7 +98,7 @@ func (s *composeService) start(ctx context.Context, projectName string, options
}
}
return eg.Wait()
return nil
}
// getDependencyCondition checks if service is depended on by other services

View File

@ -21,6 +21,7 @@ import (
"fmt"
"os"
"os/signal"
"slices"
"sync/atomic"
"syscall"
@ -34,6 +35,7 @@ import (
"github.com/eiannone/keyboard"
"github.com/hashicorp/go-multierror"
"github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
)
func (s *composeService) Up(ctx context.Context, project *types.Project, options api.UpOptions) error { //nolint:gocyclo
@ -205,29 +207,44 @@ func (s *composeService) Up(ctx context.Context, project *types.Project, options
})
}
// use an independent context tied to the errgroup for background attach operations
// the primary context is still used for other operations
// this means that once any attach operation fails, all other attaches are cancelled,
// but an attach failing won't interfere with the rest of the start
_, attachCtx := errgroup.WithContext(ctx)
containers, err := s.attach(attachCtx, project, printer.HandleEvent, options.Start.AttachTo)
if err != nil {
return err
}
attached := make([]string, len(containers))
for i, ctr := range containers {
attached[i] = ctr.ID
}
monitor.withListener(func(event api.ContainerEvent) {
if event.Type != api.ContainerEventStarted {
return
}
if event.Restarting || event.Container.Labels[api.ContainerReplaceLabel] != "" {
eg.Go(func() error {
ctr, err := s.apiClient().ContainerInspect(ctx, event.ID)
if err != nil {
return err
}
err = s.doLogContainer(ctx, options.Start.Attach, event.Source, ctr, api.LogOptions{
Follow: true,
Since: ctr.State.StartedAt,
})
if errdefs.IsNotImplemented(err) {
// container may be configured with logging_driver: none
// as container already started, we might miss the very first logs. But still better than none
return s.doAttachContainer(ctx, event.Service, event.ID, event.Source, printer.HandleEvent)
}
return err
})
if slices.Contains(attached, event.ID) {
return
}
eg.Go(func() error {
ctr, err := s.apiClient().ContainerInspect(ctx, event.ID)
if err != nil {
return err
}
err = s.doLogContainer(ctx, options.Start.Attach, event.Source, ctr, api.LogOptions{
Follow: true,
Since: ctr.State.StartedAt,
})
if errdefs.IsNotImplemented(err) {
// container may be configured with logging_driver: none
// as container already started, we might miss the very first logs. But still better than none
return s.doAttachContainer(ctx, event.Service, event.ID, event.Source, printer.HandleEvent)
}
return err
})
})
eg.Go(func() error {

89
pkg/progress/json_test.go Normal file
View File

@ -0,0 +1,89 @@
/*
Copyright 2024 Docker Compose CLI authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package progress
import (
"bytes"
"context"
"encoding/json"
"testing"
"gotest.tools/v3/assert"
)
func TestJsonWriter_Event(t *testing.T) {
var out bytes.Buffer
w := &jsonWriter{
out: &out,
done: make(chan bool),
dryRun: true,
}
event := Event{
ID: "service1",
ParentID: "project",
Text: "Creating",
StatusText: "Working",
Current: 50,
Total: 100,
Percent: 50,
}
w.Event(event)
var actual jsonMessage
err := json.Unmarshal(out.Bytes(), &actual)
assert.NilError(t, err)
expected := jsonMessage{
DryRun: true,
ID: event.ID,
ParentID: event.ParentID,
Text: event.Text,
Status: event.StatusText,
Current: event.Current,
Total: event.Total,
Percent: event.Percent,
}
assert.DeepEqual(t, expected, actual)
}
func TestJsonWriter_TailMsgf(t *testing.T) {
var out bytes.Buffer
w := &jsonWriter{
out: &out,
done: make(chan bool),
dryRun: false,
}
go func() {
_ = w.Start(context.Background())
}()
w.TailMsgf("hello %s", "world")
w.Stop()
var actual jsonMessage
err := json.Unmarshal(out.Bytes(), &actual)
assert.NilError(t, err)
expected := jsonMessage{
Tail: true,
Text: "hello world",
}
assert.DeepEqual(t, expected, actual)
}