From e050897f488fb0ca27417939d65b941698fdd29d Mon Sep 17 00:00:00 2001 From: Tonis Tiigi Date: Mon, 16 Jun 2025 13:42:31 -0700 Subject: [PATCH 1/4] vendor: update buildkit v0.23.0-rc2 Signed-off-by: Tonis Tiigi (cherry picked from commit cb29cd0efbdce2a4d8b70305ad17e2977c8b5afd) --- 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 0f473e9eb7cf..2cb1d9a1f662 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,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.23.0-rc1 + github.com/moby/buildkit v0.23.0-rc2 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 bf8e7885afac..13397c4860ae 100644 --- a/go.sum +++ b/go.sum @@ -250,8 +250,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.23.0-rc1 h1:RIAEITsycLbXUt//rEPEfZUFnKUcm1cvpuWOfOidiWU= -github.com/moby/buildkit v0.23.0-rc1/go.mod h1:v5jMDvQgUyidk3wu3NvVAAd5JJo83nfet9Gf/o0+EAQ= +github.com/moby/buildkit v0.23.0-rc2 h1:LJIyp/w3/yzVKXngKnkvBw3mvsoE2HkvjAk4+RIBcX8= +github.com/moby/buildkit v0.23.0-rc2/go.mod h1:v5jMDvQgUyidk3wu3NvVAAd5JJo83nfet9Gf/o0+EAQ= 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 406181a007db..357bc54f4f1f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -447,7 +447,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.23.0-rc1 +# github.com/moby/buildkit v0.23.0-rc2 ## explicit; go 1.23.0 github.com/moby/buildkit/api/services/control github.com/moby/buildkit/api/types From 51db06ee9a5c98cc5277ef03bd22d9e4b478a2ab Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Mon, 16 Jun 2025 15:59:02 +0200 Subject: [PATCH 2/4] history: slsa v1 support Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> (cherry picked from commit 4a22b92775c64f06b12bbd7e1b63cb089b3862f2) --- commands/history/inspect.go | 25 +++++++++++++++++-------- commands/history/inspect_attachment.go | 22 ++++++++++++++-------- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/commands/history/inspect.go b/commands/history/inspect.go index fe05db75c707..920143fb9c19 100644 --- a/commands/history/inspect.go +++ b/commands/history/inspect.go @@ -426,23 +426,32 @@ workers0: } provIndex := slices.IndexFunc(attachments, func(a attachment) bool { - return descrType(a.descr) == slsa02.PredicateSLSAProvenance + return strings.HasPrefix(descrType(a.descr), "https://slsa.dev/provenance/") }) if provIndex != -1 { prov := attachments[provIndex] + predType := descrType(prov.descr) dt, err := content.ReadBlob(ctx, store, prov.descr) if err != nil { return errors.Errorf("failed to read provenance %s: %v", prov.descr.Digest, err) } - var pred provenancetypes.ProvenancePredicateSLSA02 - if err := json.Unmarshal(dt, &pred); err != nil { + var pred *provenancetypes.ProvenancePredicateSLSA1 + if predType == slsa02.PredicateSLSAProvenance { + var pred02 *provenancetypes.ProvenancePredicateSLSA02 + if err := json.Unmarshal(dt, &pred02); err != nil { + return errors.Errorf("failed to unmarshal provenance %s: %v", prov.descr.Digest, err) + } + pred = provenancetypes.ConvertSLSA02ToSLSA1(pred02) + } else if err := json.Unmarshal(dt, &pred); err != nil { return errors.Errorf("failed to unmarshal provenance %s: %v", prov.descr.Digest, err) } - for _, m := range pred.Materials { - out.Materials = append(out.Materials, materialOutput{ - URI: m.URI, - Digests: digestSetToDigests(m.Digest), - }) + if pred != nil { + for _, m := range pred.BuildDefinition.ResolvedDependencies { + out.Materials = append(out.Materials, materialOutput{ + URI: m.URI, + Digests: digestSetToDigests(m.Digest), + }) + } } } diff --git a/commands/history/inspect_attachment.go b/commands/history/inspect_attachment.go index 8fb01191dfdb..80cc02e5f4d2 100644 --- a/commands/history/inspect_attachment.go +++ b/commands/history/inspect_attachment.go @@ -11,6 +11,7 @@ import ( "github.com/docker/cli/cli/command" intoto "github.com/in-toto/in-toto-golang/in_toto" slsa02 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2" + slsa1 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v1" "github.com/opencontainers/go-digest" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" @@ -76,25 +77,30 @@ func runAttachment(ctx context.Context, dockerCli command.Cli, opts attachmentOp return err } - typ := opts.typ - switch typ { + types := make(map[string]struct{}) + switch opts.typ { case "index": - typ = ocispecs.MediaTypeImageIndex + types[ocispecs.MediaTypeImageIndex] = struct{}{} case "manifest": - typ = ocispecs.MediaTypeImageManifest + types[ocispecs.MediaTypeImageManifest] = struct{}{} case "image": - typ = ocispecs.MediaTypeImageConfig + types[ocispecs.MediaTypeImageConfig] = struct{}{} case "provenance": - typ = slsa02.PredicateSLSAProvenance + types[slsa1.PredicateSLSAProvenance] = struct{}{} + types[slsa02.PredicateSLSAProvenance] = struct{}{} case "sbom": - typ = intoto.PredicateSPDX + types[intoto.PredicateSPDX] = struct{}{} + default: + if opts.typ != "" { + types[opts.typ] = struct{}{} + } } for _, a := range attachments { if opts.platform != "" && (a.platform == nil || platforms.FormatAll(*a.platform) != opts.platform) { continue } - if typ != "" && descrType(a.descr) != typ { + if _, ok := types[descrType(a.descr)]; opts.typ != "" && !ok { continue } ra, err := store.ReaderAt(ctx, a.descr) From 35d10a96553dfa9935cb40a219eab6fdacc2beca Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Mon, 16 Jun 2025 11:37:27 +0200 Subject: [PATCH 3/4] bake: multi ips support for extra hosts Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> (cherry picked from commit 989978a42b59d03d862405c74fc0cdc6e8eb18ae) --- bake/compose.go | 6 ++---- bake/compose_test.go | 3 ++- build/utils.go | 26 ++++++++++++++++---------- build/utils_test.go | 5 +++++ tests/bake.go | 3 +++ tests/build.go | 19 +++++++++++++++++++ 6 files changed, 47 insertions(+), 15 deletions(-) diff --git a/bake/compose.go b/bake/compose.go index b913d560d8ee..84c1fd4fe1b9 100644 --- a/bake/compose.go +++ b/bake/compose.go @@ -125,10 +125,8 @@ func ParseCompose(cfgs []composetypes.ConfigFile, envs map[string]string) (*Conf extraHosts := map[string]*string{} if s.Build.ExtraHosts != nil { for k, v := range s.Build.ExtraHosts { - for _, ip := range v { - vv := ip - extraHosts[k] = &vv - } + vv := strings.Join(v, ",") + extraHosts[k] = &vv } } diff --git a/bake/compose_test.go b/bake/compose_test.go index 6e08fdc414df..9a5e97de2532 100644 --- a/bake/compose_test.go +++ b/bake/compose_test.go @@ -34,6 +34,7 @@ services: - type=local,dest=path/to/cache extra_hosts: - "somehost:162.242.195.82" + - "somehost:162.242.195.83" - "myhostv6:::1" ssh: - key=/path/to/key @@ -79,7 +80,7 @@ secrets: require.Equal(t, ptrstr("123"), c.Targets[1].Args["buildno"]) require.Equal(t, []string{"type=local,src=path/to/cache"}, stringify(c.Targets[1].CacheFrom)) require.Equal(t, []string{"type=local,dest=path/to/cache"}, stringify(c.Targets[1].CacheTo)) - require.Equal(t, map[string]*string{"myhostv6": ptrstr("::1"), "somehost": ptrstr("162.242.195.82")}, c.Targets[1].ExtraHosts) + require.Equal(t, map[string]*string{"myhostv6": ptrstr("::1"), "somehost": ptrstr("162.242.195.82,162.242.195.83")}, c.Targets[1].ExtraHosts) require.Equal(t, "none", *c.Targets[1].NetworkMode) require.Equal(t, []string{"default", "key=/path/to/key"}, stringify(c.Targets[1].SSH)) require.Equal(t, []string{ diff --git a/build/utils.go b/build/utils.go index 3d095ae62215..52d501886719 100644 --- a/build/utils.go +++ b/build/utils.go @@ -77,24 +77,30 @@ func toBuildkitExtraHosts(ctx context.Context, inp []string, nodeDriver *driver. } // If the IP Address is a "host-gateway", replace this value with the // IP address provided by the worker's label. + var ips []string if ip == mobyHostGatewayName { hgip, err := nodeDriver.HostGatewayIP(ctx) if err != nil { return "", errors.Wrap(err, "unable to derive the IP value for host-gateway") } - ip = hgip.String() + ips = append(ips, hgip.String()) } else { - // If the address is enclosed in square brackets, extract it (for IPv6, but - // permit it for IPv4 as well; we don't know the address family here, but it's - // unambiguous). - if len(ip) > 2 && ip[0] == '[' && ip[len(ip)-1] == ']' { - ip = ip[1 : len(ip)-1] - } - if net.ParseIP(ip) == nil { - return "", errors.Errorf("invalid host %s", h) + for _, v := range strings.Split(ip, ",") { + // If the address is enclosed in square brackets, extract it + // (for IPv6, but permit it for IPv4 as well; we don't know the + // address family here, but it's unambiguous). + if len(v) > 2 && v[0] == '[' && v[len(v)-1] == ']' { + v = v[1 : len(v)-1] + } + if net.ParseIP(v) == nil { + return "", errors.Errorf("invalid host %s", h) + } + ips = append(ips, v) } } - hosts = append(hosts, host+"="+ip) + for _, v := range ips { + hosts = append(hosts, host+"="+v) + } } return strings.Join(hosts, ","), nil } diff --git a/build/utils_test.go b/build/utils_test.go index 02b597b91bd9..3983af966881 100644 --- a/build/utils_test.go +++ b/build/utils_test.go @@ -72,6 +72,11 @@ func TestToBuildkitExtraHosts(t *testing.T) { doc: "IPv6 localhost, non-canonical, eq sep", input: []string{`ipv6local=0:0:0:0:0:0:0:1`}, }, + { + doc: "Multi IPs", + input: []string{`myhost=162.242.195.82,162.242.195.83`}, + expectedOut: `myhost=162.242.195.82,myhost=162.242.195.83`, + }, { doc: "IPv6 localhost, non-canonical, eq sep, brackets", input: []string{`ipv6local=[0:0:0:0:0:0:0:1]`}, diff --git a/tests/bake.go b/tests/bake.go index fa6e2f4dd481..0ce6d216c8b9 100644 --- a/tests/bake.go +++ b/tests/bake.go @@ -2167,11 +2167,14 @@ func testBakeExtraHosts(t *testing.T, sb integration.Sandbox) { dockerfile := []byte(` FROM busybox RUN cat /etc/hosts | grep myhost | grep 1.2.3.4 +RUN cat /etc/hosts | grep myhostmulti | grep 162.242.195.81 +RUN cat /etc/hosts | grep myhostmulti | grep 162.242.195.82 `) bakefile := []byte(` target "default" { extra-hosts = { myhost = "1.2.3.4" + myhostmulti = "162.242.195.81,162.242.195.82" } } `) diff --git a/tests/build.go b/tests/build.go index 2e2b9e02916e..e179163cf92a 100644 --- a/tests/build.go +++ b/tests/build.go @@ -77,6 +77,7 @@ var buildTests = []func(t *testing.T, sb integration.Sandbox){ testBuildDefaultLoad, testBuildCall, testCheckCallOutput, + testBuildExtraHosts, } func testBuild(t *testing.T, sb integration.Sandbox) { @@ -1322,6 +1323,24 @@ cOpy Dockerfile . }) } +func testBuildExtraHosts(t *testing.T, sb integration.Sandbox) { + dockerfile := []byte(` +FROM busybox +RUN cat /etc/hosts | grep myhost | grep 1.2.3.4 +RUN cat /etc/hosts | grep myhostmulti | grep 162.242.195.81 +RUN cat /etc/hosts | grep myhostmulti | grep 162.242.195.82 +`) + dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600)) + cmd := buildxCmd(sb, withArgs("build", + "--add-host=myhost=1.2.3.4", + "--add-host=myhostmulti=162.242.195.81", + "--add-host=myhostmulti=162.242.195.82", + "--output=type=cacheonly", dir), + ) + out, err := cmd.CombinedOutput() + require.NoError(t, err, string(out)) +} + func createTestProject(t *testing.T) string { dockerfile := []byte(` FROM busybox:latest AS base From e785cc4bf7f5a4b9d63c8b3f28d226fcd534ad48 Mon Sep 17 00:00:00 2001 From: "Jonathan A. Sternberg" Date: Mon, 16 Jun 2025 12:24:04 -0500 Subject: [PATCH 4/4] progress: ensure bake waits for progress to finish printing on error conditions Some minor fixes to the printer and how bake invokes it. Bake previously had a race condition that could result in the display not updating on an error condition, but it was much rarer because the channel communication was much closer. The refactor added a proxy for the status channel so there was more of an opportunity to surface the race condition. When bake exits with an error when reading the bakefiles, it doesn't wait for the printer to finish so it is possible for the printer to update the display after an error is printed. This adds an extra `Wait` in a defer to make sure the printer is finished. `Wait` has also been fixed to allow it to be called multiple times and have the same behavior. Previously, it only waited for the done channel once so only the first wait would block. The `onclose` method is now called every time the display is paused or stopped. That was the previous behavior and it's been restored here. The display only gets refreshed if we aren't exiting. There's no point in initializing another display if we're about to exit. The metric writer attached to the printer was erroneously removed. It is now assigned properly. Signed-off-by: Jonathan A. Sternberg (cherry picked from commit 7660acf9c7c80e7dbc33a120c7b053e7759af368) --- commands/bake.go | 6 ++++++ util/progress/printer.go | 21 +++++++++++---------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/commands/bake.go b/commands/bake.go index 571385058598..b325c0e16e3e 100644 --- a/commands/bake.go +++ b/commands/bake.go @@ -162,7 +162,13 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba attributes := bakeMetricAttributes(dockerCli, driverType, url, cmdContext, targets, &in) progressMode := progressui.DisplayMode(cFlags.progress) + var printer *progress.Printer + defer func() { + if printer != nil { + printer.Wait() + } + }() makePrinter := func() error { var err error diff --git a/util/progress/printer.go b/util/progress/printer.go index 85208b7e200e..38b90c493f8f 100644 --- a/util/progress/printer.go +++ b/util/progress/printer.go @@ -51,8 +51,8 @@ type Printer struct { func (p *Printer) Wait() error { p.closeOnce.Do(func() { close(p.status) - <-p.done }) + <-p.done return p.err } @@ -144,6 +144,7 @@ func NewPrinter(ctx context.Context, out console.File, mode progressui.DisplayMo interrupt: make(chan interruptRequest), state: printerStateRunning, done: make(chan struct{}), + metrics: opt.mw, } go pw.run(ctx, d) @@ -155,21 +156,21 @@ func (p *Printer) run(ctx context.Context, d progressui.Display) { defer close(p.interrupt) var ss []*client.SolveStatus - for p.state != printerStateDone { + for { switch p.state { case printerStatePaused: ss, p.err = p.bufferDisplay(ctx, ss) case printerStateRunning: - var warnings []client.VertexWarning - warnings, ss, p.err = p.updateDisplay(ctx, d, ss) - p.warnings = append(p.warnings, warnings...) - - d, _ = p.newDisplay() + p.warnings, ss, p.err = p.updateDisplay(ctx, d, ss) + if p.opt.onclose != nil { + p.opt.onclose() + } } - } - if p.opt.onclose != nil { - p.opt.onclose() + if p.state == printerStateDone { + break + } + d, _ = p.newDisplay() } }