bake: set input:context for remote builds
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
This commit is contained in:
+2
-1
@@ -1306,7 +1306,7 @@ func updateContext(t *build.Inputs, inp *Input) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
st := llb.Scratch().File(llb.Copy(*inp.State, v.Path, "/"), llb.WithCustomNamef("set context %s to %s", k, v.Path))
|
st := llb.Scratch().File(llb.Copy(*inp.State, v.Path, "/"), llb.WithCustomNamef("set context %s to %s", k, v.Path))
|
||||||
t.NamedContexts[k] = build.NamedContext{State: &st}
|
t.NamedContexts[k] = build.NamedContext{State: &st, Path: inp.URL}
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.ContextPath == "." {
|
if t.ContextPath == "." {
|
||||||
@@ -1326,6 +1326,7 @@ func updateContext(t *build.Inputs, inp *Input) {
|
|||||||
llb.WithCustomNamef("set context to %s", t.ContextPath),
|
llb.WithCustomNamef("set context to %s", t.ContextPath),
|
||||||
)
|
)
|
||||||
t.ContextState = &st
|
t.ContextState = &st
|
||||||
|
t.ContextPath = inp.URL
|
||||||
}
|
}
|
||||||
|
|
||||||
func isRemoteContext(t build.Inputs, inp *Input) bool {
|
func isRemoteContext(t build.Inputs, inp *Input) bool {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import (
|
|||||||
"github.com/moby/buildkit/client/llb"
|
"github.com/moby/buildkit/client/llb"
|
||||||
"github.com/moby/buildkit/client/ociindex"
|
"github.com/moby/buildkit/client/ociindex"
|
||||||
"github.com/moby/buildkit/exporter/containerimage/exptypes"
|
"github.com/moby/buildkit/exporter/containerimage/exptypes"
|
||||||
|
"github.com/moby/buildkit/frontend/dockerfile/dfgitutil"
|
||||||
"github.com/moby/buildkit/frontend/dockerui"
|
"github.com/moby/buildkit/frontend/dockerui"
|
||||||
gateway "github.com/moby/buildkit/frontend/gateway/client"
|
gateway "github.com/moby/buildkit/frontend/gateway/client"
|
||||||
"github.com/moby/buildkit/identity"
|
"github.com/moby/buildkit/identity"
|
||||||
@@ -651,6 +652,9 @@ func loadInputs(ctx context.Context, d *driver.DriverHandle, inp *Inputs, pw pro
|
|||||||
}
|
}
|
||||||
target.FrontendInputs["context"] = *inp.ContextState
|
target.FrontendInputs["context"] = *inp.ContextState
|
||||||
target.FrontendInputs["dockerfile"] = *inp.ContextState
|
target.FrontendInputs["dockerfile"] = *inp.ContextState
|
||||||
|
if _, ok, _ := dfgitutil.ParseGitRef(inp.ContextPath); ok {
|
||||||
|
target.FrontendAttrs["input:context"] = inp.ContextPath
|
||||||
|
}
|
||||||
case inp.ContextPath == "-":
|
case inp.ContextPath == "-":
|
||||||
if inp.DockerfilePath == "-" {
|
if inp.DockerfilePath == "-" {
|
||||||
return nil, errors.Errorf("invalid argument: can't use stdin for both build context and dockerfile")
|
return nil, errors.Errorf("invalid argument: can't use stdin for both build context and dockerfile")
|
||||||
@@ -804,6 +808,9 @@ func loadInputs(ctx context.Context, d *driver.DriverHandle, inp *Inputs, pw pro
|
|||||||
caps["moby.buildkit.frontend.contexts+forward"] = struct{}{}
|
caps["moby.buildkit.frontend.contexts+forward"] = struct{}{}
|
||||||
if v.State != nil {
|
if v.State != nil {
|
||||||
target.FrontendAttrs["context:"+k] = "input:" + k
|
target.FrontendAttrs["context:"+k] = "input:" + k
|
||||||
|
if _, ok, _ := dfgitutil.ParseGitRef(v.Path); ok {
|
||||||
|
target.FrontendAttrs["input:git_state_"+k] = v.Path
|
||||||
|
}
|
||||||
if target.FrontendInputs == nil {
|
if target.FrontendInputs == nil {
|
||||||
target.FrontendInputs = make(map[string]llb.State)
|
target.FrontendInputs = make(map[string]llb.State)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ var bakeTests = []func(t *testing.T, sb integration.Sandbox){
|
|||||||
testBakePrintSensitive,
|
testBakePrintSensitive,
|
||||||
testBakePrintOverrideEmpty,
|
testBakePrintOverrideEmpty,
|
||||||
testBakePrintKeepEscaped,
|
testBakePrintKeepEscaped,
|
||||||
|
testBakePrintRemoteContextSubdir,
|
||||||
testBakeLocal,
|
testBakeLocal,
|
||||||
testBakeLocalMulti,
|
testBakeLocalMulti,
|
||||||
testBakeRemote,
|
testBakeRemote,
|
||||||
@@ -529,6 +530,78 @@ EOT
|
|||||||
require.NoError(t, err, string(out))
|
require.NoError(t, err, string(out))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testBakePrintRemoteContextSubdir(t *testing.T, sb integration.Sandbox) {
|
||||||
|
bakefile := []byte(`
|
||||||
|
target default {
|
||||||
|
context = "bar"
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
dockerfile := []byte(`
|
||||||
|
FROM scratch
|
||||||
|
COPY super-cool.txt /
|
||||||
|
`)
|
||||||
|
|
||||||
|
dir := tmpdir(
|
||||||
|
t,
|
||||||
|
fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
|
||||||
|
fstest.CreateDir("bar", 0700),
|
||||||
|
fstest.CreateFile("bar/Dockerfile", dockerfile, 0600),
|
||||||
|
fstest.CreateFile("bar/super-cool.txt", []byte("super cool"), 0600),
|
||||||
|
)
|
||||||
|
|
||||||
|
git, err := gitutil.New(gitutil.WithWorkingDir(dir))
|
||||||
|
require.NoError(t, err)
|
||||||
|
gittestutil.GitInit(git, t)
|
||||||
|
gittestutil.GitAdd(git, t, "docker-bake.hcl", "bar")
|
||||||
|
gittestutil.GitCommit(git, t, "initial commit")
|
||||||
|
addr := gittestutil.GitServeHTTP(git, t)
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
ref string
|
||||||
|
expectedContext string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "no ref",
|
||||||
|
expectedContext: addr,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "branch ref",
|
||||||
|
ref: "main",
|
||||||
|
expectedContext: addr + "#main",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
u := addr
|
||||||
|
if tt.ref != "" {
|
||||||
|
u += "#" + tt.ref
|
||||||
|
}
|
||||||
|
cmd := buildxCmd(sb, withDir("/tmp"), withArgs("bake", u, "--print"))
|
||||||
|
stdout := bytes.Buffer{}
|
||||||
|
stderr := bytes.Buffer{}
|
||||||
|
cmd.Stdout = &stdout
|
||||||
|
cmd.Stderr = &stderr
|
||||||
|
require.NoError(t, cmd.Run(), stdout.String(), stderr.String())
|
||||||
|
require.JSONEq(t, fmt.Sprintf(`{
|
||||||
|
"group": {
|
||||||
|
"default": {
|
||||||
|
"targets": [
|
||||||
|
"default"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"target": {
|
||||||
|
"default": {
|
||||||
|
"context": %q,
|
||||||
|
"dockerfile": "Dockerfile"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`, tt.expectedContext), stdout.String())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func testBakeLocal(t *testing.T, sb integration.Sandbox) {
|
func testBakeLocal(t *testing.T, sb integration.Sandbox) {
|
||||||
dockerfile := []byte(`
|
dockerfile := []byte(`
|
||||||
FROM scratch
|
FROM scratch
|
||||||
|
|||||||
@@ -240,6 +240,72 @@ COPY foo /foo
|
|||||||
require.Equal(t, md.BuildRef, rec.Ref)
|
require.Equal(t, md.BuildRef, rec.Ref)
|
||||||
require.Equal(t, addr+"#main", rec.Name)
|
require.Equal(t, addr+"#main", rec.Name)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("bake git", func(t *testing.T) {
|
||||||
|
bakefile := []byte(`
|
||||||
|
target "default" {
|
||||||
|
dockerfile-inline = <<EOT
|
||||||
|
FROM scratch
|
||||||
|
COPY foo /foo
|
||||||
|
EOT
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
dir := tmpdir(
|
||||||
|
t,
|
||||||
|
fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
|
||||||
|
fstest.CreateFile("foo", []byte("foo"), 0600),
|
||||||
|
)
|
||||||
|
dirDest := t.TempDir()
|
||||||
|
|
||||||
|
git, err := gitutil.New(gitutil.WithWorkingDir(dir))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
gittestutil.GitInit(git, t)
|
||||||
|
gittestutil.GitAdd(git, t, "docker-bake.hcl", "foo")
|
||||||
|
gittestutil.GitCommit(git, t, "initial commit")
|
||||||
|
addr := gittestutil.GitServeHTTP(git, t)
|
||||||
|
|
||||||
|
out, err := bakeCmd(sb, withDir(dir),
|
||||||
|
withArgs(addr, "--set", "*.output=type=local,dest="+dirDest, "--metadata-file", filepath.Join(dir, "md.json")),
|
||||||
|
)
|
||||||
|
require.NoError(t, err, out)
|
||||||
|
require.FileExists(t, filepath.Join(dirDest, "foo"))
|
||||||
|
|
||||||
|
dt, err := os.ReadFile(filepath.Join(dir, "md.json"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
type mdT struct {
|
||||||
|
Default struct {
|
||||||
|
BuildRef string `json:"buildx.build.ref"`
|
||||||
|
} `json:"default"`
|
||||||
|
}
|
||||||
|
var md mdT
|
||||||
|
err = json.Unmarshal(dt, &md)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
refParts := strings.Split(md.Default.BuildRef, "/")
|
||||||
|
require.Len(t, refParts, 3)
|
||||||
|
|
||||||
|
cmd := buildxCmd(sb, withArgs("history", "ls", "--filter=ref="+refParts[2], "--format=json"))
|
||||||
|
bout, err := cmd.Output()
|
||||||
|
require.NoError(t, err, string(bout))
|
||||||
|
|
||||||
|
type recT struct {
|
||||||
|
Ref string `json:"ref"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
CreatedAt *time.Time `json:"created_at"`
|
||||||
|
CompletedAt *time.Time `json:"completed_at"`
|
||||||
|
TotalSteps int32 `json:"total_steps"`
|
||||||
|
CompletedSteps int32 `json:"completed_steps"`
|
||||||
|
CachedSteps int32 `json:"cached_steps"`
|
||||||
|
}
|
||||||
|
var rec recT
|
||||||
|
err = json.Unmarshal(bout, &rec)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, md.Default.BuildRef, rec.Ref)
|
||||||
|
require.Equal(t, addr, rec.Name)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type buildRef struct {
|
type buildRef struct {
|
||||||
|
|||||||
Reference in New Issue
Block a user