mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-05-18 09:17:49 +08:00
build: set local dirs as frontend attributes
Set local dirs metadata if relative to VCS directory so dockerfile path is tracked accurately in case vcs information is not fulfilled. Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
This commit is contained in:
parent
1cdefbe901
commit
02bc4e8992
@ -530,7 +530,7 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s
|
|||||||
for k, opt := range opt {
|
for k, opt := range opt {
|
||||||
multiDriver := len(drivers[k]) > 1
|
multiDriver := len(drivers[k]) > 1
|
||||||
hasMobyDriver := false
|
hasMobyDriver := false
|
||||||
gitattrs, err := getGitAttributes(ctx, opt.Inputs.ContextPath, opt.Inputs.DockerfilePath)
|
gitattrs, addVCSLocalDir, err := getGitAttributes(ctx, opt.Inputs.ContextPath, opt.Inputs.DockerfilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithError(err).Warn("current commit information was not captured by the build")
|
logrus.WithError(err).Warn("current commit information was not captured by the build")
|
||||||
}
|
}
|
||||||
@ -554,6 +554,9 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s
|
|||||||
for k, v := range gitattrs {
|
for k, v := range gitattrs {
|
||||||
so.FrontendAttrs[k] = v
|
so.FrontendAttrs[k] = v
|
||||||
}
|
}
|
||||||
|
if addVCSLocalDir != nil {
|
||||||
|
addVCSLocalDir(so)
|
||||||
|
}
|
||||||
defers = append(defers, release)
|
defers = append(defers, release)
|
||||||
reqn = append(reqn, &reqForNode{
|
reqn = append(reqn, &reqForNode{
|
||||||
resolvedNode: np,
|
resolvedNode: np,
|
||||||
|
52
build/git.go
52
build/git.go
@ -9,16 +9,17 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/buildx/util/gitutil"
|
"github.com/docker/buildx/util/gitutil"
|
||||||
|
"github.com/moby/buildkit/client"
|
||||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const DockerfileLabel = "com.docker.image.source.entrypoint"
|
const DockerfileLabel = "com.docker.image.source.entrypoint"
|
||||||
|
|
||||||
func getGitAttributes(ctx context.Context, contextPath string, dockerfilePath string) (res map[string]string, _ error) {
|
func getGitAttributes(ctx context.Context, contextPath string, dockerfilePath string) (map[string]string, func(*client.SolveOpt), error) {
|
||||||
res = make(map[string]string)
|
res := make(map[string]string)
|
||||||
if contextPath == "" {
|
if contextPath == "" {
|
||||||
return
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
setGitLabels := false
|
setGitLabels := false
|
||||||
@ -37,7 +38,7 @@ func getGitAttributes(ctx context.Context, contextPath string, dockerfilePath st
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !setGitLabels && !setGitInfo {
|
if !setGitLabels && !setGitInfo {
|
||||||
return
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// figure out in which directory the git command needs to run in
|
// figure out in which directory the git command needs to run in
|
||||||
@ -52,20 +53,25 @@ func getGitAttributes(ctx context.Context, contextPath string, dockerfilePath st
|
|||||||
gitc, err := gitutil.New(gitutil.WithContext(ctx), gitutil.WithWorkingDir(wd))
|
gitc, err := gitutil.New(gitutil.WithContext(ctx), gitutil.WithWorkingDir(wd))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if st, err1 := os.Stat(path.Join(wd, ".git")); err1 == nil && st.IsDir() {
|
if st, err1 := os.Stat(path.Join(wd, ".git")); err1 == nil && st.IsDir() {
|
||||||
return res, errors.Wrap(err, "git was not found in the system")
|
return res, nil, errors.Wrap(err, "git was not found in the system")
|
||||||
}
|
}
|
||||||
return
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if !gitc.IsInsideWorkTree() {
|
if !gitc.IsInsideWorkTree() {
|
||||||
if st, err := os.Stat(path.Join(wd, ".git")); err == nil && st.IsDir() {
|
if st, err := os.Stat(path.Join(wd, ".git")); err == nil && st.IsDir() {
|
||||||
return res, errors.New("failed to read current commit information with git rev-parse --is-inside-work-tree")
|
return res, nil, errors.New("failed to read current commit information with git rev-parse --is-inside-work-tree")
|
||||||
}
|
}
|
||||||
return res, nil
|
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) {
|
if sha, err := gitc.FullCommit(); err != nil && !gitutil.IsUnknownRevision(err) {
|
||||||
return res, errors.Wrap(err, "failed to get git commit")
|
return res, nil, errors.Wrap(err, "failed to get git commit")
|
||||||
} else if sha != "" {
|
} else if sha != "" {
|
||||||
checkDirty := false
|
checkDirty := false
|
||||||
if v, ok := os.LookupEnv("BUILDX_GIT_CHECK_DIRTY"); ok {
|
if v, ok := os.LookupEnv("BUILDX_GIT_CHECK_DIRTY"); ok {
|
||||||
@ -93,10 +99,7 @@ func getGitAttributes(ctx context.Context, contextPath string, dockerfilePath st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if setGitLabels {
|
if setGitLabels && root != "" {
|
||||||
if root, err := gitc.RootDir(); err != nil {
|
|
||||||
return res, errors.Wrap(err, "failed to get git root dir")
|
|
||||||
} else if root != "" {
|
|
||||||
if dockerfilePath == "" {
|
if dockerfilePath == "" {
|
||||||
dockerfilePath = filepath.Join(wd, "Dockerfile")
|
dockerfilePath = filepath.Join(wd, "Dockerfile")
|
||||||
}
|
}
|
||||||
@ -104,12 +107,27 @@ func getGitAttributes(ctx context.Context, contextPath string, dockerfilePath st
|
|||||||
cwd, _ := os.Getwd()
|
cwd, _ := os.Getwd()
|
||||||
dockerfilePath = filepath.Join(cwd, dockerfilePath)
|
dockerfilePath = filepath.Join(cwd, dockerfilePath)
|
||||||
}
|
}
|
||||||
dockerfilePath, _ = filepath.Rel(root, dockerfilePath)
|
if r, err := filepath.Rel(root, dockerfilePath); err == nil && !strings.HasPrefix(r, "..") {
|
||||||
if !strings.HasPrefix(dockerfilePath, "..") {
|
res["label:"+DockerfileLabel] = r
|
||||||
res["label:"+DockerfileLabel] = dockerfilePath
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return res, func(so *client.SolveOpt) {
|
||||||
|
if !setGitInfo || root == "" {
|
||||||
return
|
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 r, err := filepath.Rel(root, dir); err == nil && !strings.HasPrefix(r, "..") {
|
||||||
|
so.FrontendAttrs["vcs:localdir:"+k] = r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/docker/buildx/util/gitutil"
|
"github.com/docker/buildx/util/gitutil"
|
||||||
|
"github.com/moby/buildkit/client"
|
||||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -30,7 +31,7 @@ func setupTest(tb testing.TB) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGetGitAttributesNotGitRepo(t *testing.T) {
|
func TestGetGitAttributesNotGitRepo(t *testing.T) {
|
||||||
_, err := getGitAttributes(context.Background(), t.TempDir(), "Dockerfile")
|
_, _, err := getGitAttributes(context.Background(), t.TempDir(), "Dockerfile")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,14 +39,14 @@ func TestGetGitAttributesBadGitRepo(t *testing.T) {
|
|||||||
tmp := t.TempDir()
|
tmp := t.TempDir()
|
||||||
require.NoError(t, os.MkdirAll(path.Join(tmp, ".git"), 0755))
|
require.NoError(t, os.MkdirAll(path.Join(tmp, ".git"), 0755))
|
||||||
|
|
||||||
_, err := getGitAttributes(context.Background(), tmp, "Dockerfile")
|
_, _, err := getGitAttributes(context.Background(), tmp, "Dockerfile")
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetGitAttributesNoContext(t *testing.T) {
|
func TestGetGitAttributesNoContext(t *testing.T) {
|
||||||
setupTest(t)
|
setupTest(t)
|
||||||
|
|
||||||
gitattrs, err := getGitAttributes(context.Background(), "", "Dockerfile")
|
gitattrs, _, err := getGitAttributes(context.Background(), "", "Dockerfile")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Empty(t, gitattrs)
|
assert.Empty(t, gitattrs)
|
||||||
}
|
}
|
||||||
@ -114,7 +115,7 @@ func TestGetGitAttributes(t *testing.T) {
|
|||||||
if tt.envGitInfo != "" {
|
if tt.envGitInfo != "" {
|
||||||
t.Setenv("BUILDX_GIT_INFO", tt.envGitInfo)
|
t.Setenv("BUILDX_GIT_INFO", tt.envGitInfo)
|
||||||
}
|
}
|
||||||
gitattrs, err := getGitAttributes(context.Background(), ".", "Dockerfile")
|
gitattrs, _, err := getGitAttributes(context.Background(), ".", "Dockerfile")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
for _, e := range tt.expected {
|
for _, e := range tt.expected {
|
||||||
assert.Contains(t, gitattrs, e)
|
assert.Contains(t, gitattrs, e)
|
||||||
@ -139,7 +140,7 @@ func TestGetGitAttributesDirty(t *testing.T) {
|
|||||||
require.NoError(t, os.WriteFile(filepath.Join("dir", "Dockerfile"), df, 0644))
|
require.NoError(t, os.WriteFile(filepath.Join("dir", "Dockerfile"), df, 0644))
|
||||||
|
|
||||||
t.Setenv("BUILDX_GIT_LABELS", "true")
|
t.Setenv("BUILDX_GIT_LABELS", "true")
|
||||||
gitattrs, _ := getGitAttributes(context.Background(), ".", "Dockerfile")
|
gitattrs, _, _ := getGitAttributes(context.Background(), ".", "Dockerfile")
|
||||||
assert.Equal(t, 5, len(gitattrs))
|
assert.Equal(t, 5, len(gitattrs))
|
||||||
|
|
||||||
assert.Contains(t, gitattrs, "label:"+DockerfileLabel)
|
assert.Contains(t, gitattrs, "label:"+DockerfileLabel)
|
||||||
@ -154,3 +155,59 @@ func TestGetGitAttributesDirty(t *testing.T) {
|
|||||||
assert.Contains(t, gitattrs, "vcs:revision")
|
assert.Contains(t, gitattrs, "vcs:revision")
|
||||||
assert.True(t, strings.HasSuffix(gitattrs["vcs:revision"], "-dirty"))
|
assert.True(t, strings.HasSuffix(gitattrs["vcs:revision"], "-dirty"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLocalDirs(t *testing.T) {
|
||||||
|
setupTest(t)
|
||||||
|
|
||||||
|
so := &client.SolveOpt{
|
||||||
|
FrontendAttrs: map[string]string{},
|
||||||
|
LocalDirs: map[string]string{
|
||||||
|
"context": ".",
|
||||||
|
"dockerfile": ".",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, addVCSLocalDir, err := getGitAttributes(context.Background(), ".", "Dockerfile")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, addVCSLocalDir)
|
||||||
|
|
||||||
|
addVCSLocalDir(so)
|
||||||
|
require.Contains(t, so.FrontendAttrs, "vcs:localdir:context")
|
||||||
|
assert.Equal(t, ".", so.FrontendAttrs["vcs:localdir:context"])
|
||||||
|
require.Contains(t, so.FrontendAttrs, "vcs:localdir:dockerfile")
|
||||||
|
assert.Equal(t, ".", so.FrontendAttrs["vcs:localdir:dockerfile"])
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLocalDirsSub(t *testing.T) {
|
||||||
|
gitutil.Mktmp(t)
|
||||||
|
|
||||||
|
c, err := gitutil.New()
|
||||||
|
require.NoError(t, err)
|
||||||
|
gitutil.GitInit(c, t)
|
||||||
|
|
||||||
|
df := []byte("FROM alpine:latest\n")
|
||||||
|
assert.NoError(t, os.MkdirAll("app", 0755))
|
||||||
|
assert.NoError(t, os.WriteFile("app/Dockerfile", df, 0644))
|
||||||
|
|
||||||
|
gitutil.GitAdd(c, t, "app/Dockerfile")
|
||||||
|
gitutil.GitCommit(c, t, "initial commit")
|
||||||
|
gitutil.GitSetRemote(c, t, "origin", "git@github.com:docker/buildx.git")
|
||||||
|
|
||||||
|
so := &client.SolveOpt{
|
||||||
|
FrontendAttrs: map[string]string{},
|
||||||
|
LocalDirs: map[string]string{
|
||||||
|
"context": ".",
|
||||||
|
"dockerfile": "app",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, addVCSLocalDir, err := getGitAttributes(context.Background(), ".", "app/Dockerfile")
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, addVCSLocalDir)
|
||||||
|
|
||||||
|
addVCSLocalDir(so)
|
||||||
|
require.Contains(t, so.FrontendAttrs, "vcs:localdir:context")
|
||||||
|
assert.Equal(t, ".", so.FrontendAttrs["vcs:localdir:context"])
|
||||||
|
require.Contains(t, so.FrontendAttrs, "vcs:localdir:dockerfile")
|
||||||
|
assert.Equal(t, "app", so.FrontendAttrs["vcs:localdir:dockerfile"])
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user