Skip to content

Commit 3a96df2

Browse files
committed
build: display build details link
Signed-off-by: CrazyMax <[email protected]>
1 parent e7034f6 commit 3a96df2

File tree

7 files changed

+116
-1
lines changed

7 files changed

+116
-1
lines changed

build/build.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/docker/buildx/builder"
2727
"github.com/docker/buildx/driver"
2828
"github.com/docker/buildx/localstate"
29+
"github.com/docker/buildx/util/desktop"
2930
"github.com/docker/buildx/util/dockerutil"
3031
"github.com/docker/buildx/util/imagetools"
3132
"github.com/docker/buildx/util/progress"
@@ -822,6 +823,7 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s
822823

823824
for i, dp := range dps {
824825
i, dp, so := i, dp, *dp.so
826+
node := nodes[dp.driverIndex]
825827
if multiDriver {
826828
for i, e := range so.Exports {
827829
switch e.Type {
@@ -940,6 +942,14 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s
940942
return res, nil
941943
}
942944
}, ch)
945+
if node.Driver.Features(ctx)[driver.HistoryAPI] && desktop.BuildBackendEnabled() {
946+
progress.WriteBuildDetail(w, k, progress.BuildDetail{
947+
Builder: node.Builder,
948+
Node: node.Name,
949+
Ref: so.Ref,
950+
Err: err,
951+
})
952+
}
943953
if err != nil {
944954
return err
945955
}

commands/bake.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,12 @@ func runBake(dockerCli command.Cli, targets []string, in bakeOptions, cFlags com
117117
progressTextDesc = fmt.Sprintf("building with %q instance using %s driver", b.Name, b.Driver)
118118
}
119119

120-
printer, err := progress.NewPrinter(ctx2, os.Stderr, os.Stderr, cFlags.progress,
120+
var printer *progress.Printer
121+
printer, err = progress.NewPrinter(ctx2, os.Stderr, os.Stderr, cFlags.progress,
121122
progress.WithDesc(progressTextDesc, progressConsoleDesc),
123+
progress.WithOnClose(func() {
124+
printBuildDetails(os.Stderr, printer.BuildDetails(), cFlags.progress)
125+
}),
122126
)
123127
if err != nil {
124128
return err

commands/build.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ func runBuild(dockerCli command.Cli, options buildOptions) (err error) {
252252
),
253253
progress.WithOnClose(func() {
254254
printWarnings(os.Stderr, printer.Warnings(), progressMode)
255+
printBuildDetails(os.Stderr, printer.BuildDetails(), progressMode)
255256
}),
256257
)
257258
if err != nil {
@@ -843,3 +844,45 @@ func printValue(printer printFunc, version string, format string, res map[string
843844
}
844845
return printer([]byte(res["result.json"]), os.Stdout)
845846
}
847+
848+
func printBuildDetails(w io.Writer, bds map[string]progress.BuildDetail, mode string) {
849+
if len(bds) == 0 || mode == progress.PrinterModeQuiet {
850+
return
851+
}
852+
853+
bdURL := func(bd progress.BuildDetail) string {
854+
return fmt.Sprintf("docker-desktop://dashboard/build/%s/%s/%s", bd.Builder, bd.Node, bd.Ref)
855+
}
856+
857+
bdWithErr := func(bds map[string]progress.BuildDetail) *progress.BuildDetail {
858+
var canceled map[string]struct{}
859+
for t, bd := range bds {
860+
if bd.Err != nil {
861+
if strings.HasSuffix(bd.Err.Error(), "context canceled") {
862+
if canceled == nil {
863+
canceled = make(map[string]struct{})
864+
}
865+
canceled[t] = struct{}{}
866+
continue
867+
}
868+
return &bd
869+
}
870+
}
871+
return nil
872+
}(bds)
873+
874+
var out bytes.Buffer
875+
out.WriteString("View build details: ")
876+
if bdWithErr != nil {
877+
out.WriteString(bdURL(*bdWithErr))
878+
} else {
879+
multiTargets := len(bds) > 1
880+
for target, bd := range bds {
881+
if multiTargets {
882+
out.WriteString(fmt.Sprintf("\n %s: ", target))
883+
}
884+
out.WriteString(bdURL(bd))
885+
}
886+
}
887+
fmt.Fprintf(w, "\n%s\n", out.String())
888+
}

controller/pb/progress.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ func (w *writer) Write(status *client.SolveStatus) {
1919
w.ch <- ToControlStatus(status)
2020
}
2121

22+
func (w *writer) WriteBuildDetail(target string, bd progress.BuildDetail) {
23+
return
24+
}
25+
2226
func (w *writer) ValidateLogSource(digest.Digest, interface{}) bool {
2327
return true
2428
}

util/desktop/desktop.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package desktop
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
"sync"
7+
)
8+
9+
var (
10+
bbEnabledOnce sync.Once
11+
bbEnabled bool
12+
)
13+
14+
func BuildBackendEnabled() bool {
15+
bbEnabledOnce.Do(func() {
16+
home, err := os.UserHomeDir()
17+
if err != nil {
18+
return
19+
}
20+
_, err = os.Stat(filepath.Join(home, ".docker", "desktop-build", ".lastaccess"))
21+
bbEnabled = err == nil
22+
})
23+
return bbEnabled
24+
}

util/progress/printer.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ type Printer struct {
3333
warnings []client.VertexWarning
3434
logMu sync.Mutex
3535
logSourceMap map[digest.Digest]interface{}
36+
37+
// TODO: remove once we can use result context to pass build ref
38+
// see https://github.com/docker/buildx/pull/1861
39+
buildDetailsMu sync.Mutex
40+
buildDetails map[string]BuildDetail
3641
}
3742

3843
func (p *Printer) Wait() error {
@@ -143,6 +148,26 @@ func NewPrinter(ctx context.Context, w io.Writer, out console.File, mode string,
143148
return pw, nil
144149
}
145150

151+
type BuildDetail struct {
152+
Builder string
153+
Node string
154+
Ref string
155+
Err error
156+
}
157+
158+
func (p *Printer) WriteBuildDetail(target string, bd BuildDetail) {
159+
p.buildDetailsMu.Lock()
160+
if p.buildDetails == nil {
161+
p.buildDetails = map[string]BuildDetail{}
162+
}
163+
p.buildDetails[target] = bd
164+
p.buildDetailsMu.Unlock()
165+
}
166+
167+
func (p *Printer) BuildDetails() map[string]BuildDetail {
168+
return p.buildDetails
169+
}
170+
146171
type printerOpts struct {
147172
displayOpts []progressui.DisplaySolveStatusOpt
148173

util/progress/writer.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
type Writer interface {
1212
Write(*client.SolveStatus)
13+
WriteBuildDetail(string, BuildDetail)
1314
ValidateLogSource(digest.Digest, interface{}) bool
1415
ClearLogSource(interface{})
1516
}
@@ -41,6 +42,10 @@ func Write(w Writer, name string, f func() error) {
4142
})
4243
}
4344

45+
func WriteBuildDetail(w Writer, target string, bd BuildDetail) {
46+
w.WriteBuildDetail(target, bd)
47+
}
48+
4449
func NewChannel(w Writer) (chan *client.SolveStatus, chan struct{}) {
4550
ch := make(chan *client.SolveStatus)
4651
done := make(chan struct{})

0 commit comments

Comments
 (0)