mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-05-18 00:47:48 +08:00

This adds a build duration metric for the build command with attributes related to the buildx driver, the error type (if any), and which options were used to perform the build from a subset of the options. This also refactors some of the utility methods used by the git tool to determine filepaths into its own separate package so they can be reused in another place. Also adds a test to ensure the resource is initialized correctly and doesn't error. The otel handler logging message is suppressed on buildx invocations so we never see the error if there's a problem with the schema url. It's so easy to mess up the schema url when upgrading OTEL that we need a proper test to make sure we haven't broken the functionality. Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
138 lines
3.4 KiB
Go
138 lines
3.4 KiB
Go
package build
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
"strconv"
|
|
"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"
|
|
)
|
|
|
|
const DockerfileLabel = "com.docker.image.source.entrypoint"
|
|
|
|
func getGitAttributes(ctx context.Context, contextPath string, dockerfilePath string) (map[string]string, func(*client.SolveOpt), error) {
|
|
res := make(map[string]string)
|
|
if contextPath == "" {
|
|
return nil, nil, nil
|
|
}
|
|
|
|
setGitLabels := false
|
|
if v, ok := os.LookupEnv("BUILDX_GIT_LABELS"); ok {
|
|
if v == "full" { // backward compatibility with old "full" mode
|
|
setGitLabels = true
|
|
} else if v, err := strconv.ParseBool(v); err == nil {
|
|
setGitLabels = v
|
|
}
|
|
}
|
|
setGitInfo := true
|
|
if v, ok := os.LookupEnv("BUILDX_GIT_INFO"); ok {
|
|
if v, err := strconv.ParseBool(v); err == nil {
|
|
setGitInfo = v
|
|
}
|
|
}
|
|
|
|
if !setGitLabels && !setGitInfo {
|
|
return nil, nil, nil
|
|
}
|
|
|
|
// figure out in which directory the git command needs to run in
|
|
var wd string
|
|
if filepath.IsAbs(contextPath) {
|
|
wd = contextPath
|
|
} else {
|
|
wd, _ = filepath.Abs(filepath.Join(osutil.GetWd(), contextPath))
|
|
}
|
|
wd = osutil.SanitizePath(wd)
|
|
|
|
gitc, err := gitutil.New(gitutil.WithContext(ctx), gitutil.WithWorkingDir(wd))
|
|
if err != nil {
|
|
if st, err1 := os.Stat(path.Join(wd, ".git")); err1 == nil && st.IsDir() {
|
|
return res, nil, errors.Wrap(err, "git was not found in the system")
|
|
}
|
|
return nil, nil, nil
|
|
}
|
|
|
|
if !gitc.IsInsideWorkTree() {
|
|
if st, err := os.Stat(path.Join(wd, ".git")); err == nil && st.IsDir() {
|
|
return res, nil, errors.New("failed to read current commit information with git rev-parse --is-inside-work-tree")
|
|
}
|
|
return nil, nil, nil
|
|
}
|
|
|
|
root, err := gitc.RootDir()
|
|
if err != nil {
|
|
return res, nil, errors.Wrap(err, "failed to get git root dir")
|
|
}
|
|
|
|
if sha, err := gitc.FullCommit(); err != nil && !gitutil.IsUnknownRevision(err) {
|
|
return res, nil, errors.Wrap(err, "failed to get git commit")
|
|
} else if sha != "" {
|
|
checkDirty := false
|
|
if v, ok := os.LookupEnv("BUILDX_GIT_CHECK_DIRTY"); ok {
|
|
if v, err := strconv.ParseBool(v); err == nil {
|
|
checkDirty = v
|
|
}
|
|
}
|
|
if checkDirty && gitc.IsDirty() {
|
|
sha += "-dirty"
|
|
}
|
|
if setGitLabels {
|
|
res["label:"+specs.AnnotationRevision] = sha
|
|
}
|
|
if setGitInfo {
|
|
res["vcs:revision"] = sha
|
|
}
|
|
}
|
|
|
|
if rurl, err := gitc.RemoteURL(); err == nil && rurl != "" {
|
|
if setGitLabels {
|
|
res["label:"+specs.AnnotationSource] = rurl
|
|
}
|
|
if setGitInfo {
|
|
res["vcs:source"] = rurl
|
|
}
|
|
}
|
|
|
|
if setGitLabels && root != "" {
|
|
if dockerfilePath == "" {
|
|
dockerfilePath = filepath.Join(wd, "Dockerfile")
|
|
}
|
|
if !filepath.IsAbs(dockerfilePath) {
|
|
dockerfilePath = filepath.Join(osutil.GetWd(), dockerfilePath)
|
|
}
|
|
if r, err := filepath.Rel(root, dockerfilePath); err == nil && !strings.HasPrefix(r, "..") {
|
|
res["label:"+DockerfileLabel] = r
|
|
}
|
|
}
|
|
|
|
return res, func(so *client.SolveOpt) {
|
|
if !setGitInfo || root == "" {
|
|
return
|
|
}
|
|
for k, dir := range so.LocalDirs {
|
|
dir, err = filepath.EvalSymlinks(dir)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
dir, err = filepath.Abs(dir)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if lp, err := osutil.GetLongPathName(dir); err == nil {
|
|
dir = lp
|
|
}
|
|
dir = osutil.SanitizePath(dir)
|
|
if r, err := filepath.Rel(root, dir); err == nil && !strings.HasPrefix(r, "..") {
|
|
so.FrontendAttrs["vcs:localdir:"+k] = r
|
|
}
|
|
}
|
|
}, nil
|
|
}
|