From 99320bf99c363959f7f3bbbd49fb247df6d6c3e7 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Wed, 3 Sep 2025 16:14:35 +0200 Subject: [PATCH 1/3] vendor: update buildkit to v0.24.0 Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- vendor/modules.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 04274e95d8b0..2964591133f3 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/hashicorp/hcl/v2 v2.23.0 github.com/in-toto/in-toto-golang v0.9.0 github.com/mitchellh/hashstructure/v2 v2.0.2 - github.com/moby/buildkit v0.24.0-rc2 + github.com/moby/buildkit v0.24.0 github.com/moby/go-archive v0.1.0 github.com/moby/sys/atomicwriter v0.1.0 github.com/moby/sys/mountinfo v0.7.2 diff --git a/go.sum b/go.sum index 647ea0ee2ad5..64e357da1bcb 100644 --- a/go.sum +++ b/go.sum @@ -255,8 +255,8 @@ github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZX github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/mitchellh/mapstructure v0.0.0-20150613213606-2caf8efc9366/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/moby/buildkit v0.24.0-rc2 h1:1Z9+R162yauf3SYvn8cGjBPnglMDK4bO+00dNlJSgZI= -github.com/moby/buildkit v0.24.0-rc2/go.mod h1:4qovICAdR2H4C7+EGMRva5zgHW1gyhT4/flHI7F5F9k= +github.com/moby/buildkit v0.24.0 h1:qYfTl7W1SIJzWDIDCcPT8FboHIZCYfi++wvySi3eyFE= +github.com/moby/buildkit v0.24.0/go.mod h1:4qovICAdR2H4C7+EGMRva5zgHW1gyhT4/flHI7F5F9k= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ= diff --git a/vendor/modules.txt b/vendor/modules.txt index 0eebe28cca41..9946de58ad79 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -450,7 +450,7 @@ github.com/mitchellh/go-wordwrap # github.com/mitchellh/hashstructure/v2 v2.0.2 ## explicit; go 1.14 github.com/mitchellh/hashstructure/v2 -# github.com/moby/buildkit v0.24.0-rc2 +# github.com/moby/buildkit v0.24.0 ## explicit; go 1.23.0 github.com/moby/buildkit/api/services/control github.com/moby/buildkit/api/types From c9639314a068167ab0a008ab9771076cea68d021 Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Tue, 2 Sep 2025 09:45:48 -0700 Subject: [PATCH 2/3] git querystring frontend capability detection Signed-off-by: Tonis Tiigi --- build/opt.go | 23 ++++++++++++++++++++++- commands/build.go | 5 +++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/build/opt.go b/build/opt.go index 56879b379fe0..73227f3ec86b 100644 --- a/build/opt.go +++ b/build/opt.go @@ -38,6 +38,7 @@ import ( "github.com/moby/buildkit/solver/pb" "github.com/moby/buildkit/util/apicaps" "github.com/moby/buildkit/util/entitlements" + "github.com/moby/buildkit/util/gitutil" "github.com/opencontainers/go-digest" "github.com/pkg/errors" "github.com/tonistiigi/fsutil" @@ -404,6 +405,7 @@ func loadInputs(ctx context.Context, d *driver.DriverHandle, inp *Inputs, pw pro dockerfileName = inp.DockerfilePath dockerfileSrcName = inp.DockerfilePath toRemove []string + caps = map[string]struct{}{} ) switch { @@ -469,6 +471,12 @@ func loadInputs(ctx context.Context, d *driver.DriverHandle, inp *Inputs, pw pro target.FrontendAttrs["dockerfilekey"] = "dockerfile" } target.FrontendAttrs["context"] = inp.ContextPath + + gitRef, err := gitutil.ParseURL(inp.ContextPath) + if err == nil && len(gitRef.Query) > 0 { + caps["moby.buildkit.frontend.gitquerystring"] = struct{}{} + } + default: return nil, errors.Errorf("unable to prepare context: path %q not found", inp.ContextPath) } @@ -516,7 +524,7 @@ func loadInputs(ctx context.Context, d *driver.DriverHandle, inp *Inputs, pw pro target.FrontendAttrs["filename"] = dockerfileName for k, v := range inp.NamedContexts { - target.FrontendAttrs["frontend.caps"] = "moby.buildkit.frontend.contexts+forward" + caps["moby.buildkit.frontend.contexts+forward"] = struct{}{} if v.State != nil { target.FrontendAttrs["context:"+k] = "input:" + k if target.FrontendInputs == nil { @@ -528,6 +536,12 @@ func loadInputs(ctx context.Context, d *driver.DriverHandle, inp *Inputs, pw pro if IsRemoteURL(v.Path) || strings.HasPrefix(v.Path, "docker-image://") || strings.HasPrefix(v.Path, "target:") { target.FrontendAttrs["context:"+k] = v.Path + gitRef, err := gitutil.ParseURL(v.Path) + if err == nil && len(gitRef.Query) > 0 { + if _, ok := caps["moby.buildkit.frontend.gitquerystring"]; !ok { + caps["moby.buildkit.frontend.gitquerystring+forward"] = struct{}{} + } + } continue } @@ -557,6 +571,7 @@ func loadInputs(ctx context.Context, d *driver.DriverHandle, inp *Inputs, pw pro target.FrontendAttrs["context:"+k] = "oci-layout://" + storeName + ":" + tag + "@" + dig continue } + st, err := os.Stat(v.Path) if err != nil { return nil, errors.Wrapf(err, "failed to get build context %v", k) @@ -580,6 +595,12 @@ func loadInputs(ctx context.Context, d *driver.DriverHandle, inp *Inputs, pw pro } } + if len(caps) > 0 { + keys := slices.Collect(maps.Keys(caps)) + slices.Sort(keys) + target.FrontendAttrs["frontend.caps"] = strings.Join(keys, ",") + } + inp.DockerfileMappingSrc = dockerfileSrcName inp.DockerfileMappingDst = dockerfileName return release, nil diff --git a/commands/build.go b/commands/build.go index 16a395b859a9..30565fe6e166 100644 --- a/commands/build.go +++ b/commands/build.go @@ -692,6 +692,11 @@ func wrapBuildError(err error, bake bool) error { msg += " Named contexts are supported since Dockerfile v1.4. Use #syntax directive in Dockerfile or update to latest BuildKit." return &wrapped{err, msg} } + if st.Code() == codes.Unimplemented && strings.Contains(st.Message(), "unsupported frontend capability moby.buildkit.frontend.gitquerystring") { + msg := "current frontend does not support Git URLs with query string components." + msg += " Git URLs with query string are supported since Dockerfile v1.18 and BuildKit v0.24. Use BUILDKIT_SYNTAX build-arg, #syntax directive in Dockerfile or update to latest BuildKit." + return &wrapped{err, msg} + } } return err } From db10f5fffacf648e537364de0785bf0b36aa676e Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Wed, 3 Sep 2025 10:39:08 +0200 Subject: [PATCH 3/3] test: git query string Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- tests/build.go | 159 ++++++++++++++++++++++++++++++++++---- tests/integration_test.go | 1 + 2 files changed, 144 insertions(+), 16 deletions(-) diff --git a/tests/build.go b/tests/build.go index b77b4e42e10a..557c63b00b0b 100644 --- a/tests/build.go +++ b/tests/build.go @@ -115,28 +115,155 @@ COPY --from=base /etc/bar /bar } func testBuildRemote(t *testing.T, sb integration.Sandbox) { - dockerfile := []byte(` + t.Run("default branch", func(t *testing.T) { + dockerfile := []byte(` FROM busybox:latest COPY foo /foo `) - dir := tmpdir( - t, - fstest.CreateFile("Dockerfile", dockerfile, 0600), - fstest.CreateFile("foo", []byte("foo"), 0600), - ) - dirDest := t.TempDir() + dir := tmpdir( + t, + fstest.CreateFile("Dockerfile", dockerfile, 0600), + fstest.CreateFile("foo", []byte("foo"), 0600), + ) + dirDest := t.TempDir() - git, err := gitutil.New(gitutil.WithWorkingDir(dir)) - require.NoError(t, err) + git, err := gitutil.New(gitutil.WithWorkingDir(dir)) + require.NoError(t, err) - gittestutil.GitInit(git, t) - gittestutil.GitAdd(git, t, "Dockerfile", "foo") - gittestutil.GitCommit(git, t, "initial commit") - addr := gittestutil.GitServeHTTP(git, t) + gittestutil.GitInit(git, t) + gittestutil.GitAdd(git, t, "Dockerfile", "foo") + gittestutil.GitCommit(git, t, "initial commit") + addr := gittestutil.GitServeHTTP(git, t) - out, err := buildCmd(sb, withDir(dir), withArgs("--output=type=local,dest="+dirDest, addr)) - require.NoError(t, err, out) - require.FileExists(t, filepath.Join(dirDest, "foo")) + out, err := buildCmd(sb, withDir(dir), withArgs("--output=type=local,dest="+dirDest, addr)) + require.NoError(t, err, out) + require.FileExists(t, filepath.Join(dirDest, "foo")) + }) + + t.Run("tag ref with url fragment", func(t *testing.T) { + dockerfile := []byte(` +FROM busybox:latest +COPY foo /foo +`) + dir := tmpdir( + t, + fstest.CreateFile("Dockerfile", dockerfile, 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, "Dockerfile", "foo") + gittestutil.GitCommit(git, t, "initial commit") + gittestutil.GitTag(git, t, "v0.1.0") + addr := gittestutil.GitServeHTTP(git, t) + addr = addr + "#v0.1.0" // tag + + out, err := buildCmd(sb, withDir(dir), withArgs("--output=type=local,dest="+dirDest, addr)) + require.NoError(t, err, out) + require.FileExists(t, filepath.Join(dirDest, "foo")) + }) + + t.Run("tag ref with query string", func(t *testing.T) { + dockerfile := []byte(` +FROM busybox:latest +COPY foo /foo +`) + dir := tmpdir( + t, + fstest.CreateFile("Dockerfile", dockerfile, 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, "Dockerfile", "foo") + gittestutil.GitCommit(git, t, "initial commit") + gittestutil.GitTag(git, t, "v0.1.0") + addr := gittestutil.GitServeHTTP(git, t) + addr = addr + "?tag=v0.1.0" // tag + + out, err := buildCmd(sb, withDir(dir), withArgs("--output=type=local,dest="+dirDest, addr)) + if matchesBuildKitVersion(t, sb, ">= 0.24.0-0") { + require.NoError(t, err, out) + require.FileExists(t, filepath.Join(dirDest, "foo")) + } else { + require.Error(t, err) + require.Contains(t, out, "current frontend does not support Git URLs with query string components") + } + }) + + t.Run("tag ref with query string frontend 1.17", func(t *testing.T) { + dockerfile := []byte(` +# syntax=docker/dockerfile:1.17 +FROM busybox:latest +COPY foo /foo +`) + dir := tmpdir( + t, + fstest.CreateFile("Dockerfile", dockerfile, 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, "Dockerfile", "foo") + gittestutil.GitCommit(git, t, "initial commit") + gittestutil.GitTag(git, t, "v0.1.0") + addr := gittestutil.GitServeHTTP(git, t) + addr = addr + "?tag=v0.1.0" // tag + + out, err := buildCmd(sb, withDir(dir), withArgs("--output=type=local,dest="+dirDest, addr)) + if matchesBuildKitVersion(t, sb, ">= 0.24.0-0") { + require.NoError(t, err, out) + require.FileExists(t, filepath.Join(dirDest, "foo")) + } else { + require.Error(t, err) + require.Contains(t, out, "current frontend does not support Git URLs with query string components") + } + }) + + t.Run("tag ref with query string frontend 1.18.0", func(t *testing.T) { + dockerfile := []byte(` +# syntax=docker/dockerfile-upstream:1.18.0 +FROM busybox:latest +COPY foo /foo +`) + dir := tmpdir( + t, + fstest.CreateFile("Dockerfile", dockerfile, 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, "Dockerfile", "foo") + gittestutil.GitCommit(git, t, "initial commit") + gittestutil.GitTag(git, t, "v0.1.0") + addr := gittestutil.GitServeHTTP(git, t) + addr = addr + "?tag=v0.1.0" // tag + + out, err := buildCmd(sb, withDir(dir), withArgs("--output=type=local,dest="+dirDest, addr)) + if matchesBuildKitVersion(t, sb, ">= 0.24.0-0") { + require.NoError(t, err, out) + require.FileExists(t, filepath.Join(dirDest, "foo")) + } else { + require.Error(t, err) + require.Contains(t, out, "current frontend does not support Git URLs with query string components") + } + }) } func testBuildLocalState(t *testing.T, sb integration.Sandbox) { diff --git a/tests/integration_test.go b/tests/integration_test.go index e77a1a434ed1..e337206da835 100644 --- a/tests/integration_test.go +++ b/tests/integration_test.go @@ -49,6 +49,7 @@ func testIntegration(t *testing.T, funcs ...func(t *testing.T, sb integration.Sa } } mirroredImages["moby/buildkit:buildx-stable-1"] = buildkitImage + mirroredImages["docker/dockerfile-upstream:1.18.0"] = "docker.io/docker/dockerfile-upstream:1.18.0" mirrors := integration.WithMirroredImages(mirroredImages) tests := integration.TestFuncs(funcs...)