Skip to content
Closed
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: 4 additions & 11 deletions build/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strings"

"github.com/docker/buildx/util/gitutil"
"github.com/docker/buildx/util/osutil"
"github.com/moby/buildkit/client"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
Expand Down Expand Up @@ -46,7 +47,7 @@ func getGitAttributes(ctx context.Context, contextPath string, dockerfilePath st
if filepath.IsAbs(contextPath) {
wd = contextPath
} else {
wd, _ = filepath.Abs(filepath.Join(getWd(), contextPath))
wd, _ = filepath.Abs(filepath.Join(osutil.GetWd(), contextPath))
}
wd = gitutil.SanitizePath(wd)

Expand Down Expand Up @@ -104,7 +105,7 @@ func getGitAttributes(ctx context.Context, contextPath string, dockerfilePath st
dockerfilePath = filepath.Join(wd, "Dockerfile")
}
if !filepath.IsAbs(dockerfilePath) {
dockerfilePath = filepath.Join(getWd(), dockerfilePath)
dockerfilePath = filepath.Join(osutil.GetWd(), dockerfilePath)
}
if r, err := filepath.Rel(root, dockerfilePath); err == nil && !strings.HasPrefix(r, "..") {
res["label:"+DockerfileLabel] = r
Expand All @@ -124,7 +125,7 @@ func getGitAttributes(ctx context.Context, contextPath string, dockerfilePath st
if err != nil {
continue
}
if lp, err := getLongPathName(dir); err == nil {
if lp, err := osutil.GetLongPathName(dir); err == nil {
dir = lp
}
dir = gitutil.SanitizePath(dir)
Expand All @@ -134,11 +135,3 @@ func getGitAttributes(ctx context.Context, contextPath string, dockerfilePath st
}
}, nil
}

func getWd() string {
wd, _ := os.Getwd()
if lp, err := getLongPathName(wd); err == nil {
return lp
}
return wd
}
9 changes: 0 additions & 9 deletions build/git_unix.go

This file was deleted.

97 changes: 89 additions & 8 deletions commands/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ package commands
import (
"bytes"
"context"
"crypto/sha256"
"encoding/base64"
"encoding/csv"
"encoding/hex"
"encoding/json"
"fmt"
"io"
Expand All @@ -13,6 +15,7 @@ import (
"path/filepath"
"strconv"
"strings"
"sync"

"github.com/containerd/console"
"github.com/docker/buildx/build"
Expand All @@ -29,8 +32,10 @@ import (
"github.com/docker/buildx/util/buildflags"
"github.com/docker/buildx/util/cobrautil"
"github.com/docker/buildx/util/desktop"
"github.com/docker/buildx/util/gitutil"
"github.com/docker/buildx/util/ioset"
"github.com/docker/buildx/util/metricutil"
"github.com/docker/buildx/util/osutil"
"github.com/docker/buildx/util/progress"
"github.com/docker/buildx/util/tracing"
"github.com/docker/cli-docs-tool/annotation"
Expand All @@ -52,6 +57,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"go.opentelemetry.io/otel/attribute"
"google.golang.org/grpc/codes"
)

Expand Down Expand Up @@ -211,6 +217,88 @@ func (o *buildOptions) toDisplayMode() (progressui.DisplayMode, error) {
return progress, nil
}

func (o *buildOptions) newBuilder(dockerCli command.Cli) (*builder.Builder, error) {
contextPathHash := o.contextPath
if absContextPath, err := filepath.Abs(contextPathHash); err == nil {
contextPathHash = absContextPath
}
return builder.New(dockerCli,
builder.WithName(o.builder),
builder.WithContextPathHash(contextPathHash),
)
}

func (o *buildOptions) Attributes(dockerCli command.Cli) attribute.Set {
return attribute.NewSet(
attribute.String("driver.name", o.builder),
attribute.Stringer("driver.type", &buildOptionsDriverType{buildOptions: o, dockerCli: dockerCli}),
attribute.Stringer("build.options.hash", &buildOptionsHash{buildOptions: o}),
)
}

// buildOptionsDriverType retrieves the builder type as part of the String method
// to comply with the fmt.Stringer interface.
type buildOptionsDriverType struct {
*buildOptions
dockerCli command.Cli
result string
resultOnce sync.Once
}

func (o *buildOptionsDriverType) String() string {
o.resultOnce.Do(func() {
driverType := "unknown"
if b, err := o.newBuilder(o.dockerCli); err == nil {
driverType = b.Driver
}
o.result = driverType
})
return o.result
}

// buildOptionsHash computes a hash for the buildOptions when the String method is invoked.
// This is done so we can delay the computation of the hash until needed by OTEL using
// the fmt.Stringer interface.
type buildOptionsHash struct {
*buildOptions
result string
resultOnce sync.Once
}

func (o *buildOptionsHash) String() string {
o.resultOnce.Do(func() {
target := o.target
contextPath := o.contextPath
dockerfile := o.dockerfileName
vcs := getVCSPath(o.contextPath)

h := sha256.New()
for _, s := range []string{vcs, target, contextPath, dockerfile} {
_, _ = io.WriteString(h, s)
h.Write([]byte{0})
}
o.result = hex.EncodeToString(h.Sum(nil))
})
return o.result
}

// getVCSPath returns the vcs:source attribute for a context path.
func getVCSPath(contextPath string) string {
var wd string
if filepath.IsAbs(contextPath) {
wd = contextPath
} else {
wd, _ = filepath.Abs(filepath.Join(osutil.GetWd(), contextPath))
}
wd = gitutil.SanitizePath(wd)

var vcs string
if gitc, err := gitutil.New(gitutil.WithWorkingDir(wd)); err == nil {
vcs, _ = gitc.RemoteURL()
}
return vcs
}

func runBuild(ctx context.Context, dockerCli command.Cli, options buildOptions) (err error) {
mp, err := metricutil.NewMeterProvider(ctx, dockerCli)
if err != nil {
Expand Down Expand Up @@ -238,14 +326,7 @@ func runBuild(ctx context.Context, dockerCli command.Cli, options buildOptions)
}
}

contextPathHash := options.contextPath
if absContextPath, err := filepath.Abs(contextPathHash); err == nil {
contextPathHash = absContextPath
}
b, err := builder.New(dockerCli,
builder.WithName(options.builder),
builder.WithContextPathHash(contextPathHash),
)
b, err := options.newBuilder(dockerCli)
if err != nil {
return err
}
Expand Down
33 changes: 33 additions & 0 deletions util/metricutil/resource_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package metricutil

import (
"testing"

"github.com/stretchr/testify/assert"
"go.opentelemetry.io/otel"
)

func TestResource(t *testing.T) {
setErrorHandler(t)

// Ensure resource creation doesn't result in an error.
// This is because the schema urls for the various attributes need to be
// the same, but it's really easy to import the wrong package when upgrading
// otel to anew version and the buildx CLI swallows any visible errors.
res := Resource()

// Ensure an attribute is present.
assert.True(t, res.Set().HasValue("telemetry.sdk.version"), "resource attribute missing")
}

func setErrorHandler(tb testing.TB) {
tb.Helper()

errorHandler := otel.GetErrorHandler()
otel.SetErrorHandler(otel.ErrorHandlerFunc(func(err error) {
tb.Errorf("otel error: %s", err)
}))
tb.Cleanup(func() {
otel.SetErrorHandler(errorHandler)
})
}
15 changes: 15 additions & 0 deletions util/osutil/path.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package osutil

import "os"

// GetWd retrieves the current working directory.
//
// On Windows, this function will return the long path name
// version of the path.
func GetWd() string {
wd, _ := os.Getwd()
if lp, err := GetLongPathName(wd); err == nil {
return lp
}
return wd
}
9 changes: 9 additions & 0 deletions util/osutil/path_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//go:build !windows
// +build !windows

package osutil

// GetLongPathName is a no-op on non-Windows platforms.
func GetLongPathName(path string) (string, error) {
return path, nil
}
6 changes: 3 additions & 3 deletions build/git_windows.go → util/osutil/path_windows.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package build
package osutil

import "golang.org/x/sys/windows"

// getLongPathName converts Windows short pathnames to full pathnames.
// GetLongPathName converts Windows short pathnames to full pathnames.
// For example C:\Users\ADMIN~1 --> C:\Users\Administrator.
func getLongPathName(path string) (string, error) {
func GetLongPathName(path string) (string, error) {
// See https://groups.google.com/forum/#!topic/golang-dev/1tufzkruoTg
p, err := windows.UTF16FromString(path)
if err != nil {
Expand Down