From e206c585bbf8c65dfc628eeb73af33a785375967 Mon Sep 17 00:00:00 2001 From: Justin Chadwell Date: Fri, 4 Aug 2023 15:12:34 +0100 Subject: [PATCH] build: error on attests on non-multiplatform driver On drivers that do not support multi-platform builds (the default `docker` driver), we do not support building attestations (unless using the containerd store). We need to check this feature before attempting to build using attestations. Also adds a test to ensure that attestations can be pushed to registries at all, and that it adequately fails on the docker driver. Signed-off-by: Justin Chadwell --- build/build.go | 2 +- tests/build.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/build/build.go b/build/build.go index 1cd20ee2..382ad4ec 100644 --- a/build/build.go +++ b/build/build.go @@ -454,7 +454,7 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Op attests[k] = *v } } - supportsAttestations := bopts.LLBCaps.Contains(apicaps.CapID("exporter.image.attestations")) + supportsAttestations := bopts.LLBCaps.Contains(apicaps.CapID("exporter.image.attestations")) && nodeDriver.Features(ctx)[driver.MultiPlatform] if len(attests) > 0 { if !supportsAttestations { return nil, nil, errors.Errorf("attestations are not supported by the current buildkitd") diff --git a/tests/build.go b/tests/build.go index 87021f92..70153554 100644 --- a/tests/build.go +++ b/tests/build.go @@ -35,6 +35,7 @@ var buildTests = []func(t *testing.T, sb integration.Sandbox){ testImageIDOutput, testBuildLocalExport, testBuildRegistryExport, + testBuildRegistryExportAttestations, testBuildTarExport, testBuildMobyFromLocalImage, testBuildDetailsLink, @@ -96,6 +97,40 @@ func testBuildRegistryExport(t *testing.T, sb integration.Sandbox) { require.Equal(t, img.Layers[0]["bar"].Data, []byte("foo")) } +func testBuildRegistryExportAttestations(t *testing.T, sb integration.Sandbox) { + dir := createTestProject(t) + + registry, err := sb.NewRegistry() + if errors.Is(err, integration.ErrRequirements) { + t.Skip(err.Error()) + } + require.NoError(t, err) + target := registry + "/buildx/registry:latest" + + out, err := buildCmd(sb, withArgs(fmt.Sprintf("--output=type=image,name=%s,push=true", target), "--provenance=true", dir)) + if sb.Name() == "docker" { + require.Error(t, err) + require.Contains(t, out, "attestations are not supported") + return + } + require.NoError(t, err, string(out)) + + desc, provider, err := contentutil.ProviderFromRef(target) + require.NoError(t, err) + imgs, err := testutil.ReadImages(sb.Context(), provider, desc) + require.NoError(t, err) + + pk := platforms.Format(platforms.Normalize(platforms.DefaultSpec())) + img := imgs.Find(pk) + require.NotNil(t, img) + require.Len(t, img.Layers, 1) + require.Equal(t, img.Layers[0]["bar"].Data, []byte("foo")) + + att := imgs.FindAttestation(pk) + require.NotNil(t, att) + require.Len(t, att.Layers, 1) +} + func testImageIDOutput(t *testing.T, sb integration.Sandbox) { dockerfile := []byte(`FROM busybox:latest`)