bake: add file-relative path opt-in
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
This commit is contained in:
+53
-3
@@ -23,6 +23,7 @@ import (
|
||||
"github.com/docker/buildx/bake/hclparser"
|
||||
"github.com/docker/buildx/build"
|
||||
"github.com/docker/buildx/util/buildflags"
|
||||
"github.com/docker/buildx/util/osutil"
|
||||
"github.com/docker/buildx/util/platformutil"
|
||||
"github.com/docker/buildx/util/progress"
|
||||
"github.com/docker/buildx/util/urlutil"
|
||||
@@ -46,6 +47,10 @@ type File struct {
|
||||
Data []byte
|
||||
}
|
||||
|
||||
type ParseOpt struct {
|
||||
FileRelativePaths bool
|
||||
}
|
||||
|
||||
type Override struct {
|
||||
Value string
|
||||
ArrValue []string
|
||||
@@ -197,8 +202,8 @@ func ListTargets(files []File) ([]string, error) {
|
||||
return dedupSlice(targets), nil
|
||||
}
|
||||
|
||||
func ReadTargets(ctx context.Context, files []File, targets, overrides []string, defaults, vars map[string]string, ent *EntitlementConf) (map[string]*Target, map[string]*Group, error) {
|
||||
c, _, err := ParseFiles(files, defaults, vars)
|
||||
func ReadTargets(ctx context.Context, files []File, targets, overrides []string, defaults, vars map[string]string, ent *EntitlementConf, opts ...ParseOpt) (map[string]*Target, map[string]*Group, error) {
|
||||
c, _, err := ParseFiles(files, defaults, vars, opts...)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -337,7 +342,7 @@ func (c Config) matchNames(pattern string) ([]string, error) {
|
||||
return names, nil
|
||||
}
|
||||
|
||||
func ParseFiles(files []File, defaults, vars map[string]string) (_ *Config, _ *hclparser.ParseMeta, err error) {
|
||||
func ParseFiles(files []File, defaults, vars map[string]string, opts ...ParseOpt) (_ *Config, _ *hclparser.ParseMeta, err error) {
|
||||
defer func() {
|
||||
err = formatHCLError(err, files)
|
||||
}()
|
||||
@@ -413,9 +418,54 @@ func ParseFiles(files []File, defaults, vars map[string]string) (_ *Config, _ *h
|
||||
pm = *res
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
if opt.FileRelativePaths {
|
||||
rebaseContextPaths(&c, files)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return &c, &pm, nil
|
||||
}
|
||||
|
||||
func rebaseContextPaths(c *Config, files []File) {
|
||||
base, ok := firstLocalFileDir(files)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
for _, t := range c.Targets {
|
||||
if t.Context != nil {
|
||||
contextPath := rebaseContextPath(base, *t.Context)
|
||||
t.Context = &contextPath
|
||||
}
|
||||
for k, v := range t.Contexts {
|
||||
t.Contexts[k] = rebaseContextPath(base, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func firstLocalFileDir(files []File) (string, bool) {
|
||||
if len(files) == 0 || files[0].Name == "-" || urlutil.IsRemoteURL(files[0].Name) {
|
||||
return "", false
|
||||
}
|
||||
return filepath.Dir(files[0].Name), true
|
||||
}
|
||||
|
||||
func rebaseContextPath(base, p string) string {
|
||||
if p == "" || isSpecialContextPath(p) || filepath.IsAbs(p) {
|
||||
return p
|
||||
}
|
||||
return osutil.SanitizePath(filepath.Join(base, filepath.FromSlash(p)))
|
||||
}
|
||||
|
||||
func isSpecialContextPath(p string) bool {
|
||||
return strings.HasPrefix(p, "cwd://") ||
|
||||
strings.HasPrefix(p, "target:") ||
|
||||
strings.HasPrefix(p, "docker-image:") ||
|
||||
strings.HasPrefix(p, "oci-layout://") ||
|
||||
urlutil.IsRemoteURL(p)
|
||||
}
|
||||
|
||||
func dedupeConfig(c Config) Config {
|
||||
c2 := c
|
||||
c2.Groups = make([]*Group, 0, len(c2.Groups))
|
||||
|
||||
@@ -763,6 +763,99 @@ func TestHCLDockerfileCwdPrefix(t *testing.T) {
|
||||
assert.Equal(t, ".", bo["app"].Inputs.ContextPath)
|
||||
}
|
||||
|
||||
func TestContextPathRebase(t *testing.T) {
|
||||
fp := File{
|
||||
Name: filepath.Join("subdir", "docker-bake.hcl"),
|
||||
Data: []byte(`
|
||||
target "base" {
|
||||
context = "base"
|
||||
}
|
||||
|
||||
target "app" {
|
||||
context = "."
|
||||
dockerfile = "Dockerfile.app"
|
||||
contexts = {
|
||||
shared = "../shared"
|
||||
cwd = "cwd://local"
|
||||
linked = "target:base"
|
||||
image = "docker-image://alpine:latest"
|
||||
layout = "oci-layout://layout"
|
||||
}
|
||||
}`),
|
||||
}
|
||||
|
||||
m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, nil, nil, nil, &EntitlementConf{}, ParseOpt{
|
||||
FileRelativePaths: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, filepath.ToSlash(filepath.Clean("subdir")), *m["app"].Context)
|
||||
require.Equal(t, "Dockerfile.app", *m["app"].Dockerfile)
|
||||
require.Equal(t, filepath.ToSlash(filepath.Clean("shared")), m["app"].Contexts["shared"])
|
||||
require.Equal(t, "cwd://local", m["app"].Contexts["cwd"])
|
||||
require.Equal(t, "target:base", m["app"].Contexts["linked"])
|
||||
require.Equal(t, "docker-image://alpine:latest", m["app"].Contexts["image"])
|
||||
require.Equal(t, "oci-layout://layout", m["app"].Contexts["layout"])
|
||||
require.Equal(t, filepath.ToSlash(filepath.Clean("subdir/base")), *m["base"].Context)
|
||||
|
||||
bo, err := TargetsToBuildOpt(m, &Input{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, filepath.ToSlash(filepath.Clean("subdir")), bo["app"].Inputs.ContextPath)
|
||||
require.Equal(t, filepath.Join("subdir", "Dockerfile.app"), bo["app"].Inputs.DockerfilePath)
|
||||
require.Equal(t, filepath.ToSlash(filepath.Clean("shared")), bo["app"].Inputs.NamedContexts["shared"].Path)
|
||||
}
|
||||
|
||||
func TestOverridesNotRebased(t *testing.T) {
|
||||
fp := File{
|
||||
Name: filepath.Join("subdir", "docker-bake.hcl"),
|
||||
Data: []byte(`
|
||||
target "app" {
|
||||
context = "."
|
||||
contexts = {
|
||||
shared = "../shared"
|
||||
}
|
||||
}`),
|
||||
}
|
||||
|
||||
m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"app"}, []string{
|
||||
"app.context=override",
|
||||
"app.contexts.shared=override-shared",
|
||||
}, nil, nil, &EntitlementConf{}, ParseOpt{
|
||||
FileRelativePaths: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, "override", *m["app"].Context)
|
||||
require.Equal(t, "override-shared", m["app"].Contexts["shared"])
|
||||
}
|
||||
|
||||
func TestComposePathRebase(t *testing.T) {
|
||||
fp := File{
|
||||
Name: filepath.Join("tests", "docker-compose.yml"),
|
||||
Data: []byte(`
|
||||
services:
|
||||
debian:
|
||||
build:
|
||||
context: ./dockerfiles/debian
|
||||
additional_contexts:
|
||||
shared: ../shared
|
||||
`),
|
||||
}
|
||||
|
||||
m, _, err := ReadTargets(context.TODO(), []File{fp}, []string{"debian"}, nil, nil, nil, &EntitlementConf{}, ParseOpt{
|
||||
FileRelativePaths: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, filepath.ToSlash(filepath.Clean("tests/dockerfiles/debian")), *m["debian"].Context)
|
||||
require.Equal(t, filepath.ToSlash(filepath.Clean("shared")), m["debian"].Contexts["shared"])
|
||||
|
||||
bo, err := TargetsToBuildOpt(m, &Input{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, filepath.ToSlash(filepath.Clean("tests/dockerfiles/debian")), bo["debian"].Inputs.ContextPath)
|
||||
require.Equal(t, filepath.Join("tests", "dockerfiles", "debian", "Dockerfile"), bo["debian"].Inputs.DockerfilePath)
|
||||
}
|
||||
|
||||
func TestOverrideMerge(t *testing.T) {
|
||||
fp := File{
|
||||
Name: "docker-bake.hcl",
|
||||
|
||||
Reference in New Issue
Block a user