Skip to content

Commit

Permalink
Don't print empty bom for platform 0.9
Browse files Browse the repository at this point in the history
Signed-off-by: Natalie Arellano <[email protected]>
  • Loading branch information
natalieparellano committed Mar 11, 2022
1 parent 7707bea commit db5d4af
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 70 deletions.
1 change: 0 additions & 1 deletion builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ func (b *Builder) Build() (*platform.BuildMetadata, error) {
if err := encoding.WriteJSON(filepath.Join(b.LayersDir, "sbom", "launch", "sbom.legacy.json"), launchBOM); err != nil {
return nil, errors.Wrap(err, "encoding launch bom")
}
launchBOM = []buildpack.BOMEntry{} // zero out bom in <layers>/config/metadata.toml
if err := encoding.WriteJSON(filepath.Join(b.LayersDir, "sbom", "build", "sbom.legacy.json"), buildBOM); err != nil {
return nil, errors.Wrap(err, "encoding build bom")
}
Expand Down
7 changes: 2 additions & 5 deletions builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) {

when("build metadata", func() {
when("bom", func() {
it("should be empty", func() {
it("saves the aggregated legacy boms to <layers>/sbom/", func() {
builder.Group.Group = []buildpack.GroupBuildpack{
{ID: "A", Version: "v1", API: "0.5", Homepage: "Buildpack A Homepage"},
{ID: "B", Version: "v2", API: "0.2"},
Expand Down Expand Up @@ -347,13 +347,10 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) {
},
}, nil)

metadata, err := builder.Build()
_, err := builder.Build()
if err != nil {
t.Fatalf("Unexpected error:\n%s\n", err)
}
if s := cmp.Diff(metadata.BOM, []buildpack.BOMEntry{}); s != "" {
t.Fatalf("Unexpected:\n%s\n", s)
}

t.Log("saves the aggregated legacy launch bom to <layers>/sbom/launch/sbom.legacy.json")
var foundLaunch []buildpack.BOMEntry
Expand Down
1 change: 1 addition & 0 deletions cmd/lifecycle/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ func (ba buildArgs) build(group buildpack.Group, plan platform.BuildPlan) error
return cmd.FailErrCode(err, ba.platform.CodeFor(platform.BuildError), "build")
}

md.PlatformAPI = ba.platform.API() // TODO: test
if err := encoding.WriteTOML(launch.GetMetadataFilePath(ba.layersDir), md); err != nil {
return cmd.FailErr(err, "write build metadata")
}
Expand Down
3 changes: 2 additions & 1 deletion exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ func (e *Exporter) Export(opts ExportOptions) (platform.ExportReport, error) {
if _, err := toml.DecodeFile(launch.GetMetadataFilePath(opts.LayersDir), buildMD); err != nil {
return platform.ExportReport{}, errors.Wrap(err, "read build metadata")
}
buildMD.PlatformAPI = e.PlatformAPI

// buildpack-provided layers
if err := e.addBuildpackLayers(opts, &meta); err != nil {
Expand Down Expand Up @@ -459,7 +460,7 @@ func (e *Exporter) addOrReuseLayer(image imgutil.Image, layer layers.Layer, prev
}

func (e *Exporter) makeBuildReport(layersDir string) (platform.BuildReport, error) {
if e.PlatformAPI.LessThan("0.5") {
if e.PlatformAPI.LessThan("0.5") || e.PlatformAPI.AtLeast("0.9") {
return platform.BuildReport{}, nil
}
var out []buildpack.BOMEntry
Expand Down
174 changes: 121 additions & 53 deletions exporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -411,9 +411,60 @@ func testExporter(t *testing.T, when spec.G, it spec.S) {
h.AssertEq(t, meta.Stack.RunImage.Mirrors, []string{"registry.example.com/some/run", "other.example.com/some/run"})
})

when("metadata.toml is missing bom and has empty process list", func() {
it.Before(func() {
err := ioutil.WriteFile(filepath.Join(opts.LayersDir, "config", "metadata.toml"), []byte(`
when("build metadata", func() {
when("platform api >= 0.9", func() {
it("bom is omitted in the build label", func() {
_, err := exporter.Export(opts)
h.AssertNil(t, err)

metadataJSON, err := fakeAppImage.Label("io.buildpacks.build.metadata")
h.AssertNil(t, err)

expectedJSON := `{
"buildpacks": [
{
"id": "buildpack.id",
"version": "1.2.3",
"homepage": "buildpack homepage"
},
{
"id": "other.buildpack.id",
"version": "4.5.6",
"homepage": "other buildpack homepage"
}
],
"launcher": {
"version": "1.2.3",
"source": {
"git": {
"repository": "github.com/buildpacks/lifecycle",
"commit": "asdf1234"
}
}
},
"processes": [
{
"type": "some-process-type",
"direct": true,
"command": "/some/command",
"args": ["some", "command", "args"],
"buildpackID": "buildpack.id"
}
]
}
`
h.AssertJSONEq(t, expectedJSON, metadataJSON)
})
})

when("platform api < 0.9", func() {
it.Before(func() {
exporter.PlatformAPI = api.MustParse("0.8")
})

when("metadata.toml is missing bom and has empty process list", func() {
it.Before(func() {
err := ioutil.WriteFile(filepath.Join(opts.LayersDir, "config", "metadata.toml"), []byte(`
processes = []
[[buildpacks]]
Expand All @@ -424,19 +475,19 @@ version = "1.2.3"
id = "other.buildpack.id"
version = "4.5.6"
`),
os.ModePerm,
)
h.AssertNil(t, err)
})
os.ModePerm,
)
h.AssertNil(t, err)
})

it("BOM is null and processes is an empty array in the label", func() {
_, err := exporter.Export(opts)
h.AssertNil(t, err)
it("bom is null and processes is an empty array in the build label", func() {
_, err := exporter.Export(opts)
h.AssertNil(t, err)

metadataJSON, err := fakeAppImage.Label("io.buildpacks.build.metadata")
h.AssertNil(t, err)
metadataJSON, err := fakeAppImage.Label("io.buildpacks.build.metadata")
h.AssertNil(t, err)

expectedJSON := `
expectedJSON := `
{
"bom": null,
"buildpacks": [
Expand All @@ -461,18 +512,18 @@ version = "4.5.6"
"processes": []
}
`
h.AssertJSONEq(t, expectedJSON, metadataJSON)
})
})
h.AssertJSONEq(t, expectedJSON, metadataJSON)
})
})

it("combines metadata.toml with launcher config to create build label", func() {
_, err := exporter.Export(opts)
h.AssertNil(t, err)
it("combines metadata.toml with launcher config to create the build label", func() {
_, err := exporter.Export(opts)
h.AssertNil(t, err)

metadataJSON, err := fakeAppImage.Label("io.buildpacks.build.metadata")
h.AssertNil(t, err)
metadataJSON, err := fakeAppImage.Label("io.buildpacks.build.metadata")
h.AssertNil(t, err)

expectedJSON := `{
expectedJSON := `{
"bom": [
{
"name": "Spring Auto-reconfiguration",
Expand Down Expand Up @@ -528,7 +579,9 @@ version = "4.5.6"
]
}
`
h.AssertJSONEq(t, expectedJSON, metadataJSON)
h.AssertJSONEq(t, expectedJSON, metadataJSON)
})
})
})

when("there is project metadata", func() {
Expand Down Expand Up @@ -1171,7 +1224,7 @@ version = "4.5.6"
})

when("report.toml", func() {
when("checking the image manifest", func() {
when("manifest size", func() {
var fakeRemoteManifestSize int64
it.Before(func() {
opts.LayersDir = filepath.Join("testdata", "exporter", "empty-metadata", "layers")
Expand Down Expand Up @@ -1265,6 +1318,7 @@ version = "4.5.6"
it.Before(func() {
opts.LayersDir = filepath.Join("testdata", "exporter", "empty-metadata", "layers")
})

it("outputs the imageID", func() {
_, err := exporter.Export(opts)
h.AssertNil(t, err)
Expand All @@ -1279,46 +1333,60 @@ version = "4.5.6"
h.AssertEq(t, report.Image.ImageID, "some-image-id")
})
})
})

when("build.toml", func() {
when("platform api >= 0.5", func() {
when("valid", func() {
it.Before(func() {
opts.LayersDir = filepath.Join("testdata", "exporter", "build-metadata", "layers")
})
when("build bom", func() {
it.Before(func() {
opts.LayersDir = filepath.Join("testdata", "exporter", "build-metadata", "layers")
})

it("adds build bom entries to the report", func() {
when("platform api >= 0.9", func() {
it("does not add build bom entries to the report", func() {
report, err := exporter.Export(opts)
h.AssertNil(t, err)

h.AssertEq(t, report.Build.BOM, []buildpack.BOMEntry{
{
Require: buildpack.Require{
Name: "dep1",
Metadata: map[string]interface{}{"version": string("v1")},
},
Buildpack: buildpack.GroupBuildpack{ID: "buildpack.id", Version: "1.2.3"},
},
{
Require: buildpack.Require{
Name: "dep2",
Metadata: map[string]interface{}{"version": string("v1")},
},
Buildpack: buildpack.GroupBuildpack{ID: "other.buildpack.id", Version: "4.5.6"},
},
})
var empty []buildpack.BOMEntry
h.AssertEq(t, report.Build.BOM, empty)
})
})

when("invalid", func() {
when("platform api 0.5 to 0.8", func() {
it.Before(func() {
opts.LayersDir = filepath.Join("testdata", "exporter", "build-metadata", "bad-layers")
exporter.PlatformAPI = api.MustParse("0.8")
})

it("returns an error", func() {
_, err := exporter.Export(opts)
h.AssertError(t, err, "toml")
when("valid", func() {
it("adds build bom entries to the report", func() {
report, err := exporter.Export(opts)
h.AssertNil(t, err)

h.AssertEq(t, report.Build.BOM, []buildpack.BOMEntry{
{
Require: buildpack.Require{
Name: "dep1",
Metadata: map[string]interface{}{"version": string("v1")},
},
Buildpack: buildpack.GroupBuildpack{ID: "buildpack.id", Version: "1.2.3"},
},
{
Require: buildpack.Require{
Name: "dep2",
Metadata: map[string]interface{}{"version": string("v1")},
},
Buildpack: buildpack.GroupBuildpack{ID: "other.buildpack.id", Version: "4.5.6"},
},
})
})
})

when("invalid", func() {
it.Before(func() {
opts.LayersDir = filepath.Join("testdata", "exporter", "build-metadata", "bad-layers")
})

it("returns an error", func() {
_, err := exporter.Export(opts)
h.AssertError(t, err, "toml")
})
})
})
})
Expand Down
10 changes: 10 additions & 0 deletions internal/encoding/utils.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
package encoding

import (
"bytes"
"encoding/json"
"os"
"path/filepath"

"github.com/BurntSushi/toml"
)

func MarshalJSON(v interface{}) ([]byte, error) { // TODO: test
buf := new(bytes.Buffer)
encoder := toml.NewEncoder(buf)
if err := encoder.Encode(v); err != nil {
return nil, err
}
return buf.Bytes(), nil
}

func WriteJSON(path string, data interface{}) error {
if err := os.MkdirAll(filepath.Dir(path), 0777); err != nil {
return err
Expand Down
Loading

0 comments on commit db5d4af

Please sign in to comment.