From 640cbb8d2f841ace4c575e2fec45127040857cc0 Mon Sep 17 00:00:00 2001 From: Tibor Vass Date: Thu, 24 May 2018 22:02:13 +0000 Subject: [PATCH] build: fix output handling with buildkit (quiet option, redirects) With this patch the following become true even with buildkit enabled: 1. `docker build -q .` only outputs the created image's sha256 ID. 2. `docker build -q .` outputs as if no `-q` was specified, if error occurred 3. `docker build . &> out` outputs JSON (instead of TTY characters) Signed-off-by: Tibor Vass --- cli/command/image/build_buildkit.go | 57 ++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/cli/command/image/build_buildkit.go b/cli/command/image/build_buildkit.go index 7f8666c070..f5d2f35be6 100644 --- a/cli/command/image/build_buildkit.go +++ b/cli/command/image/build_buildkit.go @@ -150,7 +150,7 @@ func runBuildBuildKit(dockerCli command.Cli, options buildOptions) error { }) } - eg.Go(func() error { + eg.Go(func() (finalErr error) { defer func() { // make sure the Status ends cleanly on build errors s.Close() }() @@ -209,16 +209,53 @@ func runBuildBuildKit(dockerCli command.Cli, options buildOptions) error { }) t := newTracer() - var auxCb func(jsonmessage.JSONMessage) - if c, err := console.ConsoleFromFile(os.Stderr); err == nil { - // not using shared context to not disrupt display but let is finish reporting errors - auxCb = t.write - eg.Go(func() error { - return progressui.DisplaySolveStatus(context.TODO(), c, t.displayCh) - }) - defer close(t.displayCh) + ssArr := []*client.SolveStatus{} + + displayStatus := func(displayCh chan *client.SolveStatus) { + if c, err := console.ConsoleFromFile(os.Stderr); err == nil { + // not using shared context to not disrupt display but let is finish reporting errors + eg.Go(func() error { + return progressui.DisplaySolveStatus(context.TODO(), c, displayCh) + }) + } else { + // read from t.displayCh and send json to Stderr + eg.Go(func() error { + enc := json.NewEncoder(os.Stderr) + for ss := range displayCh { + if err := enc.Encode(ss); err != nil { + return err + } + } + return nil + }) + } } - err = jsonmessage.DisplayJSONMessagesStream(response.Body, os.Stdout, dockerCli.Out().FD(), dockerCli.Out().IsTerminal(), auxCb) + + if options.quiet { + eg.Go(func() error { + // TODO: make sure t.displayCh closes + for ss := range t.displayCh { + ssArr = append(ssArr, ss) + } + <-done + // TODO: verify that finalErr is indeed set when error occurs + if finalErr != nil { + displayCh := make(chan *client.SolveStatus) + go func() { + for _, ss := range ssArr { + displayCh <- ss + } + close(displayCh) + }() + displayStatus(displayCh) + } + return nil + }) + } else { + displayStatus(t.displayCh) + } + defer close(t.displayCh) + err = jsonmessage.DisplayJSONMessagesStream(response.Body, os.Stdout, dockerCli.Out().FD(), dockerCli.Out().IsTerminal(), t.write) if err != nil { if jerr, ok := err.(*jsonmessage.JSONError); ok { // If no error code is set, default to 1