Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion cmd/compose/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -508,29 +508,42 @@ func RootCommand(dockerCli command.Cli, backendOptions *BackendOptions) *cobra.C
ui.Mode = ui.ModeTTY
}

var ep ui.EventProcessor
switch opts.Progress {
case "", ui.ModeAuto:
if ansi == "never" {
switch {
case ansi == "never":
ui.Mode = ui.ModePlain
ep = ui.NewPlainWriter(dockerCli.Err())
case dockerCli.Out().IsTerminal():
ep = ui.NewTTYWriter(dockerCli.Err())
default:
ep = ui.NewPlainWriter(dockerCli.Err())
}
case ui.ModeTTY:
if ansi == "never" {
return fmt.Errorf("can't use --progress tty while ANSI support is disabled")
}
ui.Mode = ui.ModeTTY
ep = ui.NewTTYWriter(dockerCli.Err())

case ui.ModePlain:
if ansi == "always" {
return fmt.Errorf("can't use --progress plain while ANSI support is forced")
}
ui.Mode = ui.ModePlain
ep = ui.NewPlainWriter(dockerCli.Err())
case ui.ModeQuiet, "none":
ui.Mode = ui.ModeQuiet
ep = ui.NewQuietWriter()
case ui.ModeJSON:
ui.Mode = ui.ModeJSON
logrus.SetFormatter(&logrus.JSONFormatter{})
ep = ui.NewJSONWriter(dockerCli.Err())
default:
return fmt.Errorf("unsupported --progress value %q", opts.Progress)
}
backendOptions.Add(compose.WithEventProcessor(ep))

// (4) options validation / normalization
if opts.WorkDir != "" {
Expand Down
2 changes: 1 addition & 1 deletion cmd/compose/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/compose-spec/compose-go/v2/dotenv"
"github.com/compose-spec/compose-go/v2/format"
"github.com/docker/compose/v2/pkg/compose"
"github.com/docker/compose/v2/pkg/progress"
xprogress "github.com/moby/buildkit/util/progress/progressui"
"github.com/sirupsen/logrus"

Expand All @@ -38,7 +39,6 @@ import (

"github.com/docker/cli/cli"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/progress"
"github.com/docker/compose/v2/pkg/utils"
)

Expand Down
2 changes: 1 addition & 1 deletion cmd/compose/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ import (
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/cli/cli/command"
"github.com/docker/compose/v2/pkg/compose"
ui "github.com/docker/compose/v2/pkg/progress"
xprogress "github.com/moby/buildkit/util/progress/progressui"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"

"github.com/docker/compose/v2/cmd/formatter"
"github.com/docker/compose/v2/pkg/api"
ui "github.com/docker/compose/v2/pkg/progress"
"github.com/docker/compose/v2/pkg/utils"
)

Expand Down
12 changes: 4 additions & 8 deletions pkg/compose/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,13 @@ func (s *composeService) Build(ctx context.Context, project *types.Project, opti
if err != nil {
return err
}
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
return progress.Run(ctx, func(ctx context.Context) error {
return tracing.SpanWrapFunc("project/build", tracing.ProjectOptions(ctx, project),
func(ctx context.Context) error {
_, err := s.build(ctx, project, options, nil)
return err
})(ctx)
}, s.stdinfo(), "Building")
}, "build", s.events)
}

//nolint:gocyclo
Expand Down Expand Up @@ -199,22 +199,17 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
return -1
}

cw := progress.ContextWriter(ctx)
err = InDependencyOrder(ctx, project, func(ctx context.Context, name string) error {
service, ok := serviceToBuild[name]
if !ok {
return nil
}
serviceName := fmt.Sprintf("Service %s", name)

if !buildkitEnabled {
trace.SpanFromContext(ctx).SetAttributes(attribute.String("builder", "classic"))
cw.Event(progress.BuildingEvent(serviceName))
id, err := s.doBuildClassic(ctx, project, service, options)
if err != nil {
return err
}
cw.Event(progress.BuiltEvent(serviceName))
builtDigests[getServiceIndex(name)] = id

if options.Push {
Expand All @@ -231,6 +226,7 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
if err != nil {
return err
}
s.events.On(progress.BuildingEvent(buildOptions.Tags[0]))

trace.SpanFromContext(ctx).SetAttributes(attribute.String("builder", "buildkit"))
digest, err := s.doBuildBuildkit(ctx, name, buildOptions, w, nodes)
Expand Down Expand Up @@ -260,7 +256,7 @@ func (s *composeService) build(ctx context.Context, project *types.Project, opti
service := project.Services[names[i]]
imageRef := api.GetImageNameOrDefault(service, project.Name)
imageIDs[imageRef] = imageDigest
cw.Event(progress.BuiltEvent(names[i]))
s.events.On(progress.BuiltEvent(imageRef))
}
}
return imageIDs, err
Expand Down
20 changes: 10 additions & 10 deletions pkg/compose/build_bake.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,8 @@ func (s *composeService) doBuildBake(ctx context.Context, project *types.Project
}

image := api.GetImageNameOrDefault(service, project.Name)
s.events.On(progress.BuildingEvent(image))

expectedImages[serviceName] = image

pull := service.Build.Pull || options.Pull
Expand Down Expand Up @@ -340,7 +342,7 @@ func (s *composeService) doBuildBake(ctx context.Context, project *types.Project
logrus.Debugf("Executing bake with args: %v", args)

if s.dryRun {
return dryRunBake(ctx, cfg), nil
return s.dryRunBake(cfg), nil
}
cmd := exec.CommandContext(ctx, buildx.Path, args...)

Expand Down Expand Up @@ -417,7 +419,6 @@ func (s *composeService) doBuildBake(ctx context.Context, project *types.Project
return nil, err
}

cw := progress.ContextWriter(ctx)
results := map[string]string{}
for name := range serviceToBeBuild {
image := expectedImages[name]
Expand All @@ -427,7 +428,7 @@ func (s *composeService) doBuildBake(ctx context.Context, project *types.Project
return nil, fmt.Errorf("build result not found in Bake metadata for service %s", name)
}
results[image] = built.Digest
cw.Event(progress.BuiltEvent(image))
s.events.On(progress.BuiltEvent(image))
}
return results, nil
}
Expand Down Expand Up @@ -565,27 +566,26 @@ func dockerFilePath(ctxName string, dockerfile string) string {
return dockerfile
}

func dryRunBake(ctx context.Context, cfg bakeConfig) map[string]string {
w := progress.ContextWriter(ctx)
func (s composeService) dryRunBake(cfg bakeConfig) map[string]string {
bakeResponse := map[string]string{}
for name, target := range cfg.Targets {
dryRunUUID := fmt.Sprintf("dryRun-%x", sha1.Sum([]byte(name)))
displayDryRunBuildEvent(w, name, dryRunUUID, target.Tags[0])
s.displayDryRunBuildEvent(name, dryRunUUID, target.Tags[0])
bakeResponse[name] = dryRunUUID
}
for name := range bakeResponse {
w.Event(progress.BuiltEvent(name))
s.events.On(progress.BuiltEvent(name))
}
return bakeResponse
}

func displayDryRunBuildEvent(w progress.Writer, name string, dryRunUUID, tag string) {
w.Event(progress.Event{
func (s composeService) displayDryRunBuildEvent(name, dryRunUUID, tag string) {
s.events.On(progress.Event{
ID: name + " ==>",
Status: progress.Done,
Text: fmt.Sprintf("==> writing image %s", dryRunUUID),
})
w.Event(progress.Event{
s.events.On(progress.Event{
ID: name + " ==> ==>",
Status: progress.Done,
Text: fmt.Sprintf(`naming to %s`, tag),
Expand Down
8 changes: 3 additions & 5 deletions pkg/compose/build_buildkit.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import (
"github.com/docker/buildx/util/confutil"
"github.com/docker/buildx/util/dockerutil"
buildx "github.com/docker/buildx/util/progress"
"github.com/docker/compose/v2/pkg/progress"
"github.com/moby/buildkit/client"
)

Expand All @@ -40,7 +39,7 @@ func (s *composeService) doBuildBuildkit(ctx context.Context, service string, op
err error
)
if s.dryRun {
response = s.dryRunBuildResponse(ctx, service, opts)
response = s.dryRunBuildResponse(service, opts)
} else {
response, err = build.Build(ctx, nodes,
map[string]build.Options{service: opts},
Expand All @@ -66,11 +65,10 @@ func (s *composeService) doBuildBuildkit(ctx context.Context, service string, op
return "", fmt.Errorf("buildkit response is missing expected result for %s", service)
}

func (s composeService) dryRunBuildResponse(ctx context.Context, name string, options build.Options) map[string]*client.SolveResponse {
w := progress.ContextWriter(ctx)
func (s composeService) dryRunBuildResponse(name string, options build.Options) map[string]*client.SolveResponse {
buildResponse := map[string]*client.SolveResponse{}
dryRunUUID := fmt.Sprintf("dryRun-%x", sha1.Sum([]byte(name)))
displayDryRunBuildEvent(w, name, dryRunUUID, options.Tags[0])
s.displayDryRunBuildEvent(name, dryRunUUID, options.Tags[0])
buildResponse[name] = &client.SolveResponse{ExporterResponse: map[string]string{
"containerimage.digest": dryRunUUID,
}}
Expand Down
3 changes: 3 additions & 0 deletions pkg/compose/build_classic.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command/image/build"
"github.com/docker/compose/v2/pkg/api"
progress2 "github.com/docker/compose/v2/pkg/progress"
buildtypes "github.com/docker/docker/api/types/build"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/registry"
Expand Down Expand Up @@ -183,6 +184,7 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj

ctx, cancel := context.WithCancel(ctx)
defer cancel()
s.events.On(progress2.BuildingEvent(imageName))
response, err := s.apiClient().ImageBuild(ctx, body, buildOpts)
if err != nil {
return "", err
Expand Down Expand Up @@ -211,6 +213,7 @@ func (s *composeService) doBuildClassic(ctx context.Context, project *types.Proj
}
return "", err
}
s.events.On(progress2.BuiltEvent(imageName))
return imageID, nil
}

Expand Down
12 changes: 5 additions & 7 deletions pkg/compose/commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ import (
)

func (s *composeService) Commit(ctx context.Context, projectName string, options api.CommitOptions) error {
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
return progress.Run(ctx, func(ctx context.Context) error {
return s.commit(ctx, projectName, options)
}, s.stdinfo(), "Committing")
}, "commit", s.events)
}

func (s *composeService) commit(ctx context.Context, projectName string, options api.CommitOptions) error {
Expand All @@ -40,20 +40,18 @@ func (s *composeService) commit(ctx context.Context, projectName string, options
return err
}

w := progress.ContextWriter(ctx)

name := getCanonicalContainerName(ctr)
msg := fmt.Sprintf("Commit %s", name)

w.Event(progress.Event{
s.events.On(progress.Event{
ID: name,
Text: msg,
Status: progress.Working,
StatusText: "Committing",
})

if s.dryRun {
w.Event(progress.Event{
s.events.On(progress.Event{
ID: name,
Text: msg,
Status: progress.Done,
Expand All @@ -74,7 +72,7 @@ func (s *composeService) commit(ctx context.Context, projectName string, options
return err
}

w.Event(progress.Event{
s.events.On(progress.Event{
ID: name,
Text: msg,
Status: progress.Done,
Expand Down
15 changes: 15 additions & 0 deletions pkg/compose/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/docker/cli/cli/config/configfile"
"github.com/docker/cli/cli/flags"
"github.com/docker/cli/cli/streams"
"github.com/docker/compose/v2/pkg/progress"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
"github.com/docker/docker/api/types/network"
Expand Down Expand Up @@ -94,6 +95,9 @@ func NewComposeService(dockerCli command.Cli, options ...Option) (api.Compose, e
return defaultValue, nil
}
}
if s.events == nil {
s.events = progress.NewQuietWriter()
}

// If custom streams were provided, wrap the Docker CLI to use them
if s.outStream != nil || s.errStream != nil || s.inStream != nil {
Expand Down Expand Up @@ -191,10 +195,21 @@ func WithDryRun(s *composeService) error {

type Prompt func(message string, defaultValue bool) (bool, error)

// WithEventProcessor configure component to get notified on Compose operation and progress events.
// Typically used to configure a progress UI
func WithEventProcessor(bus progress.EventProcessor) Option {
return func(s *composeService) error {
s.events = bus
return nil
}
}

type composeService struct {
dockerCli command.Cli
// prompt is used to interact with user and confirm actions
prompt Prompt
// eventBus collects tasks execution events
events progress.EventProcessor

// Optional overrides for specific components (for SDK users)
outStream io.Writer
Expand Down
Loading