fix empty provenance metadata for multi-platform builds
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
This commit is contained in:
+23
-23
@@ -60,29 +60,7 @@ func fetchProvenance(ctx context.Context, c *client.Client, ref string, mode con
|
|||||||
if ev.Record == nil {
|
if ev.Record == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if ev.Record.Result != nil {
|
if len(ev.Record.Results) > 0 {
|
||||||
desc, predicateType := lookupProvenance(ev.Record.Result)
|
|
||||||
if desc == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
eg.Go(func() error {
|
|
||||||
dt, err := content.ReadBlob(ctx, store, *desc)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to load provenance blob from build record")
|
|
||||||
}
|
|
||||||
prv, err := encodeProvenance(dt, predicateType, mode)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
mu.Lock()
|
|
||||||
if out == nil {
|
|
||||||
out = make(map[string]string)
|
|
||||||
}
|
|
||||||
out["buildx.build.provenance"] = prv
|
|
||||||
mu.Unlock()
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
} else if ev.Record.Results != nil {
|
|
||||||
for platform, res := range ev.Record.Results {
|
for platform, res := range ev.Record.Results {
|
||||||
desc, predicateType := lookupProvenance(res)
|
desc, predicateType := lookupProvenance(res)
|
||||||
if desc == nil {
|
if desc == nil {
|
||||||
@@ -106,6 +84,28 @@ func fetchProvenance(ctx context.Context, c *client.Client, ref string, mode con
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
} else if ev.Record.Result != nil {
|
||||||
|
desc, predicateType := lookupProvenance(ev.Record.Result)
|
||||||
|
if desc == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
eg.Go(func() error {
|
||||||
|
dt, err := content.ReadBlob(ctx, store, *desc)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to load provenance blob from build record")
|
||||||
|
}
|
||||||
|
prv, err := encodeProvenance(dt, predicateType, mode)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
mu.Lock()
|
||||||
|
if out == nil {
|
||||||
|
out = make(map[string]string)
|
||||||
|
}
|
||||||
|
out["buildx.build.provenance"] = prv
|
||||||
|
mu.Unlock()
|
||||||
|
return nil
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out, eg.Wait()
|
return out, eg.Wait()
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ var buildTests = []func(t *testing.T, sb integration.Sandbox){
|
|||||||
testBuildShmSize,
|
testBuildShmSize,
|
||||||
testBuildUlimit,
|
testBuildUlimit,
|
||||||
testBuildMetadataProvenance,
|
testBuildMetadataProvenance,
|
||||||
|
testBuildMetadataProvenanceMultiplatform,
|
||||||
testBuildMetadataWarnings,
|
testBuildMetadataWarnings,
|
||||||
testBuildMultiExporters,
|
testBuildMultiExporters,
|
||||||
testBuildLoadPush,
|
testBuildLoadPush,
|
||||||
@@ -967,6 +968,101 @@ func buildMetadataProvenance(t *testing.T, sb integration.Sandbox, metadataMode
|
|||||||
require.Equal(t, provenancetypes.BuildKitBuildType02, prv.BuildType)
|
require.Equal(t, provenancetypes.BuildKitBuildType02, prv.BuildType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testBuildMetadataProvenanceMultiplatform(t *testing.T, sb integration.Sandbox) {
|
||||||
|
t.Run("default", func(t *testing.T) {
|
||||||
|
buildMetadataProvenanceMultiplatform(t, sb, "")
|
||||||
|
})
|
||||||
|
t.Run("max", func(t *testing.T) {
|
||||||
|
buildMetadataProvenanceMultiplatform(t, sb, "max")
|
||||||
|
})
|
||||||
|
t.Run("min", func(t *testing.T) {
|
||||||
|
buildMetadataProvenanceMultiplatform(t, sb, "min")
|
||||||
|
})
|
||||||
|
t.Run("disabled", func(t *testing.T) {
|
||||||
|
buildMetadataProvenanceMultiplatform(t, sb, "disabled")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildMetadataProvenanceMultiplatform(t *testing.T, sb integration.Sandbox, metadataMode string) {
|
||||||
|
if isMobyWorker(sb) {
|
||||||
|
t.Skip("multi-platform build is not supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
dockerfile := []byte(`
|
||||||
|
FROM --platform=$BUILDPLATFORM busybox:latest AS base
|
||||||
|
COPY foo /etc/foo
|
||||||
|
RUN cp /etc/foo /etc/bar
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
COPY --from=base /etc/bar /bar
|
||||||
|
`)
|
||||||
|
dir := tmpdir(
|
||||||
|
t,
|
||||||
|
fstest.CreateFile("Dockerfile", dockerfile, 0600),
|
||||||
|
fstest.CreateFile("foo", []byte("foo"), 0600),
|
||||||
|
)
|
||||||
|
|
||||||
|
registry, err := sb.NewRegistry()
|
||||||
|
if errors.Is(err, integration.ErrRequirements) {
|
||||||
|
t.Skip(err.Error())
|
||||||
|
}
|
||||||
|
require.NoError(t, err)
|
||||||
|
target := registry + "/buildx/registry:latest"
|
||||||
|
|
||||||
|
cmd := buildxCmd(sb,
|
||||||
|
withArgs("build",
|
||||||
|
"--platform=linux/amd64,linux/arm64",
|
||||||
|
"--metadata-file", filepath.Join(dir, "md.json"),
|
||||||
|
fmt.Sprintf("--output=type=image,name=%s,push=true", target),
|
||||||
|
dir,
|
||||||
|
),
|
||||||
|
withEnv("BUILDX_METADATA_PROVENANCE="+metadataMode),
|
||||||
|
)
|
||||||
|
|
||||||
|
out, err := cmd.CombinedOutput()
|
||||||
|
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)
|
||||||
|
|
||||||
|
img := imgs.Find("linux/amd64")
|
||||||
|
require.NotNil(t, img)
|
||||||
|
img = imgs.Find("linux/arm64")
|
||||||
|
require.NotNil(t, img)
|
||||||
|
|
||||||
|
dt, err := os.ReadFile(filepath.Join(dir, "md.json"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
type mdT struct {
|
||||||
|
BuildRef string `json:"buildx.build.ref"`
|
||||||
|
BuildProvenanceAmd64 map[string]any `json:"buildx.build.provenance/linux/amd64"`
|
||||||
|
BuildProvenanceArm64 map[string]any `json:"buildx.build.provenance/linux/arm64"`
|
||||||
|
}
|
||||||
|
var md mdT
|
||||||
|
err = json.Unmarshal(dt, &md)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.NotEmpty(t, md.BuildRef)
|
||||||
|
if metadataMode == "disabled" {
|
||||||
|
require.Empty(t, md.BuildProvenanceAmd64)
|
||||||
|
require.Empty(t, md.BuildProvenanceArm64)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
require.NotEmpty(t, md.BuildProvenanceAmd64)
|
||||||
|
require.NotEmpty(t, md.BuildProvenanceArm64)
|
||||||
|
|
||||||
|
for _, prov := range []map[string]any{md.BuildProvenanceAmd64, md.BuildProvenanceArm64} {
|
||||||
|
dtprv, err := json.Marshal(prov)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var prv provenancetypes.ProvenancePredicateSLSA02
|
||||||
|
require.NoError(t, json.Unmarshal(dtprv, &prv))
|
||||||
|
require.Equal(t, provenancetypes.BuildKitBuildType02, prv.BuildType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func testBuildMetadataWarnings(t *testing.T, sb integration.Sandbox) {
|
func testBuildMetadataWarnings(t *testing.T, sb integration.Sandbox) {
|
||||||
t.Run("default", func(t *testing.T) {
|
t.Run("default", func(t *testing.T) {
|
||||||
buildMetadataWarnings(t, sb, "")
|
buildMetadataWarnings(t, sb, "")
|
||||||
|
|||||||
Reference in New Issue
Block a user