diff --git a/bake/bake.go b/bake/bake.go index dbe839b2f830..df2c550b7527 100644 --- a/bake/bake.go +++ b/bake/bake.go @@ -1044,6 +1044,9 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) { if t.Dockerfile != nil { dockerfilePath = *t.Dockerfile } + if !strings.HasPrefix(dockerfilePath, "cwd://") { + dockerfilePath = path.Clean(dockerfilePath) + } bi := build.Inputs{ ContextPath: contextPath, @@ -1054,6 +1057,17 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) { bi.DockerfileInline = *t.DockerfileInline } updateContext(&bi, inp) + if strings.HasPrefix(bi.DockerfilePath, "cwd://") { + bi.DockerfilePath = path.Clean(strings.TrimPrefix(bi.DockerfilePath, "cwd://")) + if err := checkPath(bi.DockerfilePath); err != nil { + return nil, err + } + var err error + bi.DockerfilePath, err = filepath.Abs(bi.DockerfilePath) + if err != nil { + return nil, err + } + } if strings.HasPrefix(bi.ContextPath, "cwd://") { bi.ContextPath = path.Clean(strings.TrimPrefix(bi.ContextPath, "cwd://")) } diff --git a/bake/bake_test.go b/bake/bake_test.go index a54e66c9230f..37789c9467d8 100644 --- a/bake/bake_test.go +++ b/bake/bake_test.go @@ -3,10 +3,12 @@ package bake import ( "context" "os" + "path/filepath" "sort" "strings" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -379,7 +381,7 @@ services: require.Equal(t, []string{"web_app"}, g["default"].Targets) } -func TestHCLCwdPrefix(t *testing.T) { +func TestHCLContextCwdPrefix(t *testing.T) { fp := File{ Name: "docker-bake.hcl", Data: []byte( @@ -400,11 +402,41 @@ func TestHCLCwdPrefix(t *testing.T) { require.Equal(t, 1, len(m)) require.Contains(t, m, "app") - require.Equal(t, "test", *m["app"].Dockerfile) - require.Equal(t, "foo", *m["app"].Context) + assert.Equal(t, "test", *m["app"].Dockerfile) + assert.Equal(t, "foo", *m["app"].Context) + assert.Equal(t, "foo/test", bo["app"].Inputs.DockerfilePath) + assert.Equal(t, "foo", bo["app"].Inputs.ContextPath) +} + +func TestHCLDockerfileCwdPrefix(t *testing.T) { + fp := File{ + Name: "docker-bake.hcl", + Data: []byte( + `target "app" { + context = "." + dockerfile = "cwd://Dockerfile.app" + }`), + } + ctx := context.TODO() + + cwd, err := os.Getwd() + require.NoError(t, err) - require.Equal(t, "foo/test", bo["app"].Inputs.DockerfilePath) - require.Equal(t, "foo", bo["app"].Inputs.ContextPath) + m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil) + require.NoError(t, err) + + bo, err := TargetsToBuildOpt(m, &Input{}) + require.NoError(t, err) + + require.Equal(t, 1, len(g)) + require.Equal(t, []string{"app"}, g["default"].Targets) + + require.Equal(t, 1, len(m)) + require.Contains(t, m, "app") + assert.Equal(t, "cwd://Dockerfile.app", *m["app"].Dockerfile) + assert.Equal(t, ".", *m["app"].Context) + assert.Equal(t, filepath.Join(cwd, "Dockerfile.app"), bo["app"].Inputs.DockerfilePath) + assert.Equal(t, ".", bo["app"].Inputs.ContextPath) } func TestOverrideMerge(t *testing.T) { diff --git a/build/build.go b/build/build.go index 083b1da7b7e3..93950c0e70a1 100644 --- a/build/build.go +++ b/build/build.go @@ -1332,6 +1332,10 @@ func LoadInputs(ctx context.Context, d *driver.DriverHandle, inp Inputs, pw prog case IsRemoteURL(inp.ContextPath): if inp.DockerfilePath == "-" { dockerfileReader = inp.InStream + } else if filepath.IsAbs(inp.DockerfilePath) { + dockerfileDir = filepath.Dir(inp.DockerfilePath) + dockerfileName = filepath.Base(inp.DockerfilePath) + target.FrontendAttrs["dockerfilekey"] = "dockerfile" } target.FrontendAttrs["context"] = inp.ContextPath default: diff --git a/tests/bake.go b/tests/bake.go index b76a8bb8a2f2..975e45281eb7 100644 --- a/tests/bake.go +++ b/tests/bake.go @@ -1,6 +1,7 @@ package tests import ( + "os" "path/filepath" "testing" @@ -25,6 +26,7 @@ var bakeTests = []func(t *testing.T, sb integration.Sandbox){ testBakeRemoteContextSubdir, testBakeRemoteCmdContextEscapeRoot, testBakeRemoteCmdContextEscapeRelative, + testBakeRemoteDockerfileCwd, } func testBakeLocal(t *testing.T, sb integration.Sandbox) { @@ -287,3 +289,62 @@ EOT require.NoError(t, err, out) require.FileExists(t, filepath.Join(dirDest, "foo")) } + +func testBakeRemoteDockerfileCwd(t *testing.T, sb integration.Sandbox) { + bakefile := []byte(` +target "default" { + context = "." + dockerfile = "cwd://Dockerfile.app" +} +`) + dockerfile := []byte(` +FROM scratch +COPY bar /bar + `) + dockerfileApp := []byte(` +FROM scratch +COPY foo /foo + `) + + dirSpec := tmpdir( + t, + fstest.CreateFile("docker-bake.hcl", bakefile, 0600), + fstest.CreateFile("Dockerfile", dockerfile, 0600), + fstest.CreateFile("foo", []byte("foo"), 0600), + fstest.CreateFile("bar", []byte("bar"), 0600), + ) + dirSrc := tmpdir( + t, + fstest.CreateFile("Dockerfile.app", dockerfileApp, 0600), + ) + dirDest := t.TempDir() + + git, err := gitutil.New(gitutil.WithWorkingDir(dirSpec)) + require.NoError(t, err) + + gitutil.GitInit(git, t) + gitutil.GitAdd(git, t, "docker-bake.hcl") + gitutil.GitAdd(git, t, "Dockerfile") + gitutil.GitAdd(git, t, "foo") + gitutil.GitAdd(git, t, "bar") + gitutil.GitCommit(git, t, "initial commit") + addr := gitutil.GitServeHTTP(git, t) + + out, err := bakeCmd( + sb, + withDir(dirSrc), + withArgs(addr, "--set", "*.output=type=local,dest="+dirDest), + ) + require.NoError(t, err, out) + require.FileExists(t, filepath.Join(dirDest, "foo")) + + err = os.Remove(filepath.Join(dirSrc, "Dockerfile.app")) + require.NoError(t, err) + + out, err = bakeCmd( + sb, + withDir(dirSrc), + withArgs(addr, "--set", "*.output=type=cacheonly"), + ) + require.Error(t, err, out) +}