mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-24 20:28:02 +08:00
build: display build details link
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
86
util/desktop/desktop.go
Normal file
86
util/desktop/desktop.go
Normal file
@@ -0,0 +1,86 @@
|
||||
package desktop
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/containerd/console"
|
||||
)
|
||||
|
||||
var (
|
||||
bbEnabledOnce sync.Once
|
||||
bbEnabled bool
|
||||
)
|
||||
|
||||
func BuildBackendEnabled() bool {
|
||||
bbEnabledOnce.Do(func() {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, err = os.Stat(filepath.Join(home, ".docker", "desktop-build", ".lastaccess"))
|
||||
bbEnabled = err == nil
|
||||
})
|
||||
return bbEnabled
|
||||
}
|
||||
|
||||
func BuildDetailsOutput(refs map[string]string, term bool) string {
|
||||
if len(refs) == 0 {
|
||||
return ""
|
||||
}
|
||||
refURL := func(ref string) string {
|
||||
return fmt.Sprintf("docker-desktop://dashboard/build/%s", ref)
|
||||
}
|
||||
var out bytes.Buffer
|
||||
out.WriteString("View build details: ")
|
||||
multiTargets := len(refs) > 1
|
||||
for target, ref := range refs {
|
||||
if multiTargets {
|
||||
out.WriteString(fmt.Sprintf("\n %s: ", target))
|
||||
}
|
||||
if term {
|
||||
out.WriteString(hyperlink(refURL(ref)))
|
||||
} else {
|
||||
out.WriteString(refURL(ref))
|
||||
}
|
||||
}
|
||||
return out.String()
|
||||
}
|
||||
|
||||
func PrintBuildDetails(w io.Writer, refs map[string]string, term bool) {
|
||||
if out := BuildDetailsOutput(refs, term); out != "" {
|
||||
fmt.Fprintf(w, "\n%s\n", out)
|
||||
}
|
||||
}
|
||||
|
||||
func hyperlink(url string) string {
|
||||
// create an escape sequence using the OSC 8 format: https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
|
||||
return fmt.Sprintf("\033]8;;%s\033\\%s\033]8;;\033\\", url, url)
|
||||
}
|
||||
|
||||
type ErrorWithBuildRef struct {
|
||||
Ref string
|
||||
Err error
|
||||
Msg string
|
||||
}
|
||||
|
||||
func (e *ErrorWithBuildRef) Error() string {
|
||||
return e.Err.Error()
|
||||
}
|
||||
|
||||
func (e *ErrorWithBuildRef) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
func (e *ErrorWithBuildRef) Print(w io.Writer) error {
|
||||
var term bool
|
||||
if _, err := console.ConsoleFromFile(os.Stderr); err == nil {
|
||||
term = true
|
||||
}
|
||||
fmt.Fprintf(w, "\n%s", BuildDetailsOutput(map[string]string{"default": e.Ref}, term))
|
||||
return nil
|
||||
}
|
@@ -33,6 +33,11 @@ type Printer struct {
|
||||
warnings []client.VertexWarning
|
||||
logMu sync.Mutex
|
||||
logSourceMap map[digest.Digest]interface{}
|
||||
|
||||
// TODO: remove once we can use result context to pass build ref
|
||||
// see https://github.com/docker/buildx/pull/1861
|
||||
buildRefsMu sync.Mutex
|
||||
buildRefs map[string]string
|
||||
}
|
||||
|
||||
func (p *Printer) Wait() error {
|
||||
@@ -143,6 +148,19 @@ func NewPrinter(ctx context.Context, w io.Writer, out console.File, mode string,
|
||||
return pw, nil
|
||||
}
|
||||
|
||||
func (p *Printer) WriteBuildRef(target string, ref string) {
|
||||
p.buildRefsMu.Lock()
|
||||
defer p.buildRefsMu.Unlock()
|
||||
if p.buildRefs == nil {
|
||||
p.buildRefs = map[string]string{}
|
||||
}
|
||||
p.buildRefs[target] = ref
|
||||
}
|
||||
|
||||
func (p *Printer) BuildRefs() map[string]string {
|
||||
return p.buildRefs
|
||||
}
|
||||
|
||||
type printerOpts struct {
|
||||
displayOpts []progressui.DisplaySolveStatusOpt
|
||||
|
||||
|
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
type Writer interface {
|
||||
Write(*client.SolveStatus)
|
||||
WriteBuildRef(string, string)
|
||||
ValidateLogSource(digest.Digest, interface{}) bool
|
||||
ClearLogSource(interface{})
|
||||
}
|
||||
@@ -41,6 +42,10 @@ func Write(w Writer, name string, f func() error) {
|
||||
})
|
||||
}
|
||||
|
||||
func WriteBuildRef(w Writer, target string, ref string) {
|
||||
w.WriteBuildRef(target, ref)
|
||||
}
|
||||
|
||||
func NewChannel(w Writer) (chan *client.SolveStatus, chan struct{}) {
|
||||
ch := make(chan *client.SolveStatus)
|
||||
done := make(chan struct{})
|
||||
|
Reference in New Issue
Block a user