Update to BuildKit 0.12
* Supersedes https://github.com/moby/moby/pull/44530
* Supersedes https://github.com/moby/moby/pull/46035

**- What I did**
Update containerd (library) to v1.7 and BuildKit to v0.12.

Make changes to the code to adjust to the new dependency versions, and fix some TODOs that were waiting on these updates. Leave some new TODOs as well, mostly related to the builder-next code and having to re-implement some things instead of re-using them from BuildKit.

**- How I did it**
With help from my IDE, and with assistance from others (@tonistiigi, @crazy-max, @rumpl) where I ran out of skill and/or time.

**- How to verify it**
CI ✅ 

**- Description for the changelog**
* Update buildkit to `v0.12.2`.
* Update containerd to `v1.7.6`.

**- A picture of a cute animal (not mandatory but encouraged)**
![](https://cdn.discordapp.com/attachments/1132712576812318750/1139648380230975508/20230811_215535.jpg)

integration/build/build_traces_test.go
package build

import (
	"context"
	"fmt"
	"testing"
	"time"

	"github.com/docker/docker/client/buildkit"
	"github.com/docker/docker/testutil"
	moby_buildkit_v1 "github.com/moby/buildkit/api/services/control"
	"github.com/moby/buildkit/client"
	"github.com/moby/buildkit/client/llb"
	"github.com/moby/buildkit/util/progress/progressui"
	"go.opentelemetry.io/otel"
	"golang.org/x/sync/errgroup"
	"gotest.tools/v3/assert"
	"gotest.tools/v3/poll"
	"gotest.tools/v3/skip"
)

type testWriter struct {
	*testing.T
}

func (t *testWriter) Write(p []byte) (int, error) {
	t.Log(string(p))
	return len(p), nil
}

func TestBuildkitHistoryTracePropagation(t *testing.T) {
	skip.If(t, testEnv.DaemonInfo.OSType == "windows", "buildkit is not supported on Windows")

	ctx := testutil.StartSpan(baseContext, t)

	opts := buildkit.ClientOpts(testEnv.APIClient())
	bc, err := client.New(ctx, "", opts...)
	assert.NilError(t, err)
	defer bc.Close()

	def, err := llb.Scratch().Marshal(ctx)
	assert.NilError(t, err)

	eg, ctxGo := errgroup.WithContext(ctx)
	ch := make(chan *client.SolveStatus)

	ctxHistory, cancel := context.WithCancel(ctx)
	defer cancel()

	sub, err := bc.ControlClient().ListenBuildHistory(ctxHistory, &moby_buildkit_v1.BuildHistoryRequest{ActiveOnly: true})
	assert.NilError(t, err)
	sub.CloseSend()

	defer func() {
		cancel()
		<-sub.Context().Done()
	}()

	eg.Go(func() error {
		_, err := progressui.DisplaySolveStatus(ctxGo, "test", nil, &testWriter{t}, ch)
		return err
	})

	eg.Go(func() error {
		_, err := bc.Solve(ctxGo, def, client.SolveOpt{}, ch)
		return err
	})
	assert.NilError(t, eg.Wait())

	he, err := sub.Recv()
	assert.NilError(t, err)
	assert.Assert(t, he != nil)
	cancel()

	// Traces for history records are recorded asynchronously, so we need to wait for it to be available.
	if he.Record.Trace != nil {
		return
	}

	// Split this into a new span so it doesn't clutter up the trace reporting GUI.
	ctx, span := otel.Tracer("").Start(ctx, "Wait for trace to propagate to history record")
	defer span.End()

	t.Log("Waiting for trace to be available")
	poll.WaitOn(t, func(logger poll.LogT) poll.Result {
		ctx, cancel := context.WithCancel(ctx)
		defer cancel()

		sub, err := bc.ControlClient().ListenBuildHistory(ctx, &moby_buildkit_v1.BuildHistoryRequest{Ref: he.Record.Ref})
		if err != nil {
			return poll.Error(err)
		}
		sub.CloseSend()

		defer func() {
			cancel()
			<-sub.Context().Done()
		}()

		msg, err := sub.Recv()
		if err != nil {
			return poll.Error(err)
		}

		if msg.Record.Ref != he.Record.Ref {
			return poll.Error(fmt.Errorf("got incorrect history record"))
		}
		if msg.Record.Trace != nil {
			return poll.Success()
		}
		return poll.Continue("trace not available yet")
	}, poll.WithDelay(time.Second), poll.WithTimeout(30*time.Second))

}

package build

import (
	"context"
	"fmt"
	"testing"
	"time"

	"github.com/docker/docker/client/buildkit"
	"github.com/docker/docker/testutil"
	moby_buildkit_v1 "github.com/moby/buildkit/api/services/control"
	"github.com/moby/buildkit/client"
	"github.com/moby/buildkit/client/llb"
	"github.com/moby/buildkit/util/progress/progressui"
	"go.opentelemetry.io/otel"
	"golang.org/x/sync/errgroup"
	"gotest.tools/v3/assert"
	"gotest.tools/v3/poll"
	"gotest.tools/v3/skip"
)

type testWriter struct {
	*testing.T
}

func (t *testWriter) Write(p []byte) (int, error) {
	t.Log(string(p))
	return len(p), nil
}

func TestBuildkitHistoryTracePropagation(t *testing.T) {
	skip.If(t, testEnv.DaemonInfo.OSType == "windows", "buildkit is not supported on Windows")

	ctx := testutil.StartSpan(baseContext, t)

	opts := buildkit.ClientOpts(testEnv.APIClient())
	bc, err := client.New(ctx, "", opts...)
	assert.NilError(t, err)
	defer bc.Close()

	def, err := llb.Scratch().Marshal(ctx)
	assert.NilError(t, err)

	eg, ctxGo := errgroup.WithContext(ctx)
	ch := make(chan *client.SolveStatus)

	ctxHistory, cancel := context.WithCancel(ctx)
	defer cancel()

	sub, err := bc.ControlClient().ListenBuildHistory(ctxHistory, &moby_buildkit_v1.BuildHistoryRequest{ActiveOnly: true})
	assert.NilError(t, err)
	sub.CloseSend()

	defer func() {
		cancel()
		<-sub.Context().Done()
	}()

	eg.Go(func() error {
		_, err := progressui.DisplaySolveStatus(ctxGo, nil, &testWriter{t}, ch, progressui.WithPhase("test"))
		return err
	})

	eg.Go(func() error {
		_, err := bc.Solve(ctxGo, def, client.SolveOpt{}, ch)
		return err
	})
	assert.NilError(t, eg.Wait())

	he, err := sub.Recv()
	assert.NilError(t, err)
	assert.Assert(t, he != nil)
	cancel()

	// Traces for history records are recorded asynchronously, so we need to wait for it to be available.
	if he.Record.Trace != nil {
		return
	}

	// Split this into a new span so it doesn't clutter up the trace reporting GUI.
	ctx, span := otel.Tracer("").Start(ctx, "Wait for trace to propagate to history record")
	defer span.End()

	t.Log("Waiting for trace to be available")
	poll.WaitOn(t, func(logger poll.LogT) poll.Result {
		ctx, cancel := context.WithCancel(ctx)
		defer cancel()

		sub, err := bc.ControlClient().ListenBuildHistory(ctx, &moby_buildkit_v1.BuildHistoryRequest{Ref: he.Record.Ref})
		if err != nil {
			return poll.Error(err)
		}
		sub.CloseSend()

		defer func() {
			cancel()
			<-sub.Context().Done()
		}()

		msg, err := sub.Recv()
		if err != nil {
			return poll.Error(err)
		}

		if msg.Record.Ref != he.Record.Ref {
			return poll.Error(fmt.Errorf("got incorrect history record"))
		}
		if msg.Record.Trace != nil {
			return poll.Success()
		}
		return poll.Continue("trace not available yet")
	}, poll.WithDelay(time.Second), poll.WithTimeout(30*time.Second))

}

Should this go into the buildkit update commit?