Skip to content

Commit 890e163

Browse files
committed
build: display docker desktop build details link
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
1 parent fef0c67 commit 890e163

File tree

2 files changed

+66
-1
lines changed

2 files changed

+66
-1
lines changed

build/build.go

Lines changed: 12 additions & 1 deletion
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"
@@ -719,7 +720,6 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s
719720
}()
720721

721722
eg, ctx := errgroup.WithContext(ctx)
722-
723723
for k, opt := range opt {
724724
multiDriver := len(m[k]) > 1
725725
hasMobyDriver := false
@@ -799,6 +799,9 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s
799799
var respMu sync.Mutex
800800
results := waitmap.New()
801801

802+
buildDetailsOpts := make(map[string]desktop.BuildDetailsOpt)
803+
defer func() { logrus.Printf(desktop.BuildDetailsOutput(buildDetailsOpts)) }()
804+
802805
multiTarget := len(opt) > 1
803806

804807
for k, opt := range opt {
@@ -822,6 +825,7 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s
822825

823826
for i, dp := range dps {
824827
i, dp, so := i, dp, *dp.so
828+
node := nodes[dp.driverIndex]
825829
if multiDriver {
826830
for i, e := range so.Exports {
827831
switch e.Type {
@@ -929,6 +933,13 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s
929933
printRes = res.Metadata
930934
}
931935
results.Set(resultKey(dp.driverIndex, k), res)
936+
if node.Driver.Features()[driver.HistoryAPI] && desktop.BuildBackendEnabled() {
937+
buildDetailsOpts[k] = desktop.BuildDetailsOpt{
938+
Builder: node.Builder,
939+
Node: node.Name,
940+
Ref: so.Ref,
941+
}
942+
}
932943
if resultHandleFunc != nil {
933944
resultCtx, err := NewResultContext(ctx, cc, so, res)
934945
if err == nil {

util/desktop/desktop.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package desktop
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"os"
7+
"path/filepath"
8+
"sync"
9+
)
10+
11+
var (
12+
bbEnabledOnce sync.Once
13+
bbEnabled bool
14+
)
15+
16+
func BuildBackendEnabled() bool {
17+
bbEnabledOnce.Do(func() {
18+
home, err := os.UserHomeDir()
19+
if err != nil {
20+
return
21+
}
22+
_, err = os.Stat(filepath.Join(home, ".docker", "desktop-build", ".lastaccess"))
23+
bbEnabled = err == nil
24+
})
25+
return bbEnabled
26+
}
27+
28+
type BuildDetailsOpt struct {
29+
Builder string
30+
Node string
31+
Ref string
32+
}
33+
34+
func BuildDetailsOutput(opts map[string]BuildDetailsOpt) string {
35+
var out bytes.Buffer
36+
out.WriteString("Open build details on Docker Desktop: ")
37+
multiTargets := len(opts) > 1
38+
if multiTargets {
39+
out.WriteString("\n")
40+
}
41+
for target, opt := range opts {
42+
url := fmt.Sprintf("docker-desktop://dashboard/build/%s/%s/%s", opt.Builder, opt.Node, opt.Ref)
43+
if multiTargets {
44+
out.WriteString(fmt.Sprintf(" %s: ", target))
45+
}
46+
out.WriteString(hyperlink(url, url))
47+
}
48+
return out.String()
49+
}
50+
51+
func hyperlink(url, text string) string {
52+
// create an escape sequence using the OSC 8 format: https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
53+
return fmt.Sprintf("\033]8;;%s\033\\%s\033]8;;\033\\\n", url, text)
54+
}

0 commit comments

Comments
 (0)