Skip to content

Commit

Permalink
Update build to use GenerateBillOfMaterials postal function (#135)
Browse files Browse the repository at this point in the history
- Removes PlanRefinery
- Removes YarnLogger in favor of the scribe.Emitter which covers all of
the same functionalities
- Removes the PlanEntryResolver in favor of a draft.Planner which covers
the same functionality with a nil priority plan as well as giving access
to the MergeLayerType function
- Updates to using postal.Deliver as postal.Install is deprecated
  • Loading branch information
ForestEckhardt authored Jul 27, 2021
1 parent d587394 commit 7d032e5
Show file tree
Hide file tree
Showing 13 changed files with 176 additions and 314 deletions.
62 changes: 36 additions & 26 deletions build.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,27 @@ import (
"github.com/paketo-buildpacks/packit"
"github.com/paketo-buildpacks/packit/chronos"
"github.com/paketo-buildpacks/packit/postal"
"github.com/paketo-buildpacks/packit/scribe"
)

//go:generate faux --interface EntryResolver --output fakes/entry_resolver.go
type EntryResolver interface {
Resolve([]packit.BuildpackPlanEntry) packit.BuildpackPlanEntry
Resolve(name string, entries []packit.BuildpackPlanEntry, priorites []interface{}) (packit.BuildpackPlanEntry, []packit.BuildpackPlanEntry)
MergeLayerTypes(name string, entries []packit.BuildpackPlanEntry) (launch, build bool)
}

//go:generate faux --interface DependencyManager --output fakes/dependency_manager.go
type DependencyManager interface {
Resolve(path, id, version, stack string) (postal.Dependency, error)
Install(dependency postal.Dependency, cnbPath, layerPath string) error
}

//go:generate faux --interface BuildPlanRefinery --output fakes/build_plan_refinery.go
type BuildPlanRefinery interface {
BillOfMaterials(postal.Dependency) packit.BuildpackPlanEntry
Deliver(dependency postal.Dependency, cnbPath, layerPath, platformPath string) error
GenerateBillOfMaterials(dependencies ...postal.Dependency) []packit.BOMEntry
}

func Build(
entries EntryResolver,
dependencies DependencyManager,
planRefinery BuildPlanRefinery,
entryResolver EntryResolver,
dependencyManager DependencyManager,
clock chronos.Clock,
logger LogEmitter,
logger scribe.Emitter,
) packit.BuildFunc {
return func(context packit.BuildContext) (packit.BuildResult, error) {
logger.Title("%s %s", context.BuildpackInfo.Name, context.BuildpackInfo.Version)
Expand All @@ -40,30 +37,46 @@ func Build(
return packit.BuildResult{}, err
}

entry := entries.Resolve(context.Plan.Entries)
entryVersion, _ := entry.Metadata["version"].(string)
entry, _ := entryResolver.Resolve("yarn", context.Plan.Entries, nil)
version, ok := entry.Metadata["version"].(string)
if !ok {
version = "default"
}

dependency, err := dependencies.Resolve(
dependency, err := dependencyManager.Resolve(
filepath.Join(context.CNBPath, "buildpack.toml"),
entry.Name,
entryVersion,
version,
context.Stack)
if err != nil {
return packit.BuildResult{}, err
}

bom := planRefinery.BillOfMaterials(dependency)
bom := dependencyManager.GenerateBillOfMaterials(dependency)

launch, build := entryResolver.MergeLayerTypes("yarn", context.Plan.Entries)

var buildMetadata = packit.BuildMetadata{}
var launchMetadata = packit.LaunchMetadata{}
if build {
buildMetadata = packit.BuildMetadata{BOM: bom}
}

if launch {
launchMetadata = packit.LaunchMetadata{BOM: bom}
}

cachedSHA, ok := yarnLayer.Metadata[DependencyCacheKey].(string)
if ok && cachedSHA == dependency.SHA256 {
logger.Process("Reusing cached layer %s", yarnLayer.Path)
logger.Break()

yarnLayer.Launch, yarnLayer.Build, yarnLayer.Cache = launch, build, build

return packit.BuildResult{
Plan: packit.BuildpackPlan{
Entries: []packit.BuildpackPlanEntry{bom},
},
Layers: []packit.Layer{yarnLayer},
Build: buildMetadata,
Launch: launchMetadata,
}, nil
}

Expand All @@ -74,14 +87,12 @@ func Build(
return packit.BuildResult{}, err
}

yarnLayer.Build = entry.Metadata["build"] == true
yarnLayer.Cache = entry.Metadata["build"] == true
yarnLayer.Launch = entry.Metadata["launch"] == true
yarnLayer.Launch, yarnLayer.Build, yarnLayer.Cache = launch, build, build

logger.Subprocess("Installing Yarn")

duration, err := clock.Measure(func() error {
return dependencies.Install(dependency, context.CNBPath, yarnLayer.Path)
return dependencyManager.Deliver(dependency, context.CNBPath, yarnLayer.Path, context.Platform.Path)
})
if err != nil {
return packit.BuildResult{}, err
Expand All @@ -96,10 +107,9 @@ func Build(
}

return packit.BuildResult{
Plan: packit.BuildpackPlan{
Entries: []packit.BuildpackPlanEntry{bom},
},
Layers: []packit.Layer{yarnLayer},
Build: buildMetadata,
Launch: launchMetadata,
}, nil
}
}
111 changes: 57 additions & 54 deletions build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/paketo-buildpacks/packit"
"github.com/paketo-buildpacks/packit/chronos"
"github.com/paketo-buildpacks/packit/postal"
"github.com/paketo-buildpacks/packit/scribe"
"github.com/paketo-buildpacks/yarn"
"github.com/paketo-buildpacks/yarn/fakes"
"github.com/sclevine/spec"
Expand All @@ -28,7 +29,6 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
cnbDir string
timestamp time.Time
entryResolver *fakes.EntryResolver
planRefinery *fakes.BuildPlanRefinery
dependencyManager *fakes.DependencyManager
buffer *bytes.Buffer

Expand All @@ -46,9 +46,6 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
workingDir, err = ioutil.TempDir("", "working-dir")
Expect(err).NotTo(HaveOccurred())

buffer = bytes.NewBuffer(nil)
logEmitter := yarn.NewLogEmitter(buffer)

timestamp = time.Now()
clock := chronos.NewClock(func() time.Time {
return timestamp
Expand All @@ -68,19 +65,20 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
URI: "yarn-dependency-uri",
Version: "yarn-dependency-version",
}

planRefinery = &fakes.BuildPlanRefinery{}
planRefinery.BillOfMaterialsCall.Returns.BuildpackPlanEntry = packit.BuildpackPlanEntry{
Name: "yarn",
Metadata: map[string]interface{}{
"name": "yarn-dependency-name",
"sha256": "yarn-dependency-sha",
"stacks": []string{"some-stack"},
"uri": "yarn-dependency-uri",
dependencyManager.GenerateBillOfMaterialsCall.Returns.BOMEntrySlice = []packit.BOMEntry{
{
Name: "yarn",
Metadata: map[string]interface{}{
"name": "yarn-dependency-name",
"sha256": "yarn-dependency-sha",
"stacks": []string{"some-stack"},
"uri": "yarn-dependency-uri",
},
},
}

build = yarn.Build(entryResolver, dependencyManager, planRefinery, clock, logEmitter)
buffer = bytes.NewBuffer(nil)
build = yarn.Build(entryResolver, dependencyManager, clock, scribe.NewEmitter(buffer))
})

it.After(func() {
Expand All @@ -105,24 +103,12 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
},
},
},
Layers: packit.Layers{Path: layersDir},
Platform: packit.Platform{Path: "platform"},
Layers: packit.Layers{Path: layersDir},
})
Expect(err).NotTo(HaveOccurred())

Expect(result).To(Equal(packit.BuildResult{
Plan: packit.BuildpackPlan{
Entries: []packit.BuildpackPlanEntry{
{
Name: "yarn",
Metadata: map[string]interface{}{
"name": "yarn-dependency-name",
"sha256": "yarn-dependency-sha",
"stacks": []string{"some-stack"},
"uri": "yarn-dependency-uri",
},
},
},
},
Layers: []packit.Layer{
{
Name: "yarn",
Expand All @@ -142,32 +128,40 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
},
}))

Expect(entryResolver.ResolveCall.Receives.BuildpackPlanEntrySlice).To(Equal([]packit.BuildpackPlanEntry{
Expect(entryResolver.ResolveCall.Receives.Name).To(Equal("yarn"))
Expect(entryResolver.ResolveCall.Receives.Entries).To(Equal([]packit.BuildpackPlanEntry{
{Name: "yarn"},
}))

Expect(entryResolver.MergeLayerTypesCall.Receives.Name).To(Equal("yarn"))
Expect(entryResolver.MergeLayerTypesCall.Receives.Entries).To(Equal([]packit.BuildpackPlanEntry{
{Name: "yarn"},
}))

Expect(dependencyManager.ResolveCall.Receives.Path).To(Equal(filepath.Join(cnbDir, "buildpack.toml")))
Expect(dependencyManager.ResolveCall.Receives.Id).To(Equal("yarn"))
Expect(dependencyManager.ResolveCall.Receives.Stack).To(Equal("some-stack"))

Expect(dependencyManager.InstallCall.Receives.Dependency).To(Equal(postal.Dependency{
Expect(dependencyManager.DeliverCall.Receives.Dependency).To(Equal(postal.Dependency{
ID: "yarn",
Name: "yarn-dependency-name",
SHA256: "yarn-dependency-sha",
Stacks: []string{"some-stack"},
URI: "yarn-dependency-uri",
Version: "yarn-dependency-version",
}))
Expect(dependencyManager.InstallCall.Receives.CnbPath).To(Equal(cnbDir))
Expect(dependencyManager.InstallCall.Receives.LayerPath).To(Equal(filepath.Join(layersDir, "yarn")))
Expect(dependencyManager.DeliverCall.Receives.CnbPath).To(Equal(cnbDir))
Expect(dependencyManager.DeliverCall.Receives.LayerPath).To(Equal(filepath.Join(layersDir, "yarn")))
Expect(dependencyManager.DeliverCall.Receives.PlatformPath).To(Equal("platform"))

Expect(planRefinery.BillOfMaterialsCall.Receives.Dependency).To(Equal(postal.Dependency{
Expect(dependencyManager.GenerateBillOfMaterialsCall.Receives.Dependencies).To(Equal([]postal.Dependency{{
ID: "yarn",
Name: "yarn-dependency-name",
SHA256: "yarn-dependency-sha",
Stacks: []string{"some-stack"},
URI: "yarn-dependency-uri",
Version: "yarn-dependency-version",
},
}))

Expect(buffer.String()).To(ContainSubstring("Some Buildpack some-version"))
Expand All @@ -177,14 +171,10 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {

context("when the plan entry requires the dependency during the build an launch phases", func() {
it.Before(func() {
entryResolver.ResolveCall.Returns.BuildpackPlanEntry = packit.BuildpackPlanEntry{
Name: "yarn",
Metadata: map[string]interface{}{
"build": true,
"launch": true,
},
}
entryResolver.MergeLayerTypesCall.Returns.Launch = true
entryResolver.MergeLayerTypesCall.Returns.Build = true
})

it("makes the layer available in those phases", func() {
result, err := build(packit.BuildContext{
CNBPath: cnbDir,
Expand All @@ -205,19 +195,6 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
Expect(err).NotTo(HaveOccurred())

Expect(result).To(Equal(packit.BuildResult{
Plan: packit.BuildpackPlan{
Entries: []packit.BuildpackPlanEntry{
{
Name: "yarn",
Metadata: map[string]interface{}{
"name": "yarn-dependency-name",
"sha256": "yarn-dependency-sha",
"stacks": []string{"some-stack"},
"uri": "yarn-dependency-uri",
},
},
},
},
Layers: []packit.Layer{
{
Name: "yarn",
Expand All @@ -235,6 +212,32 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {
},
},
},
Build: packit.BuildMetadata{
BOM: []packit.BOMEntry{
{
Name: "yarn",
Metadata: map[string]interface{}{
"name": "yarn-dependency-name",
"sha256": "yarn-dependency-sha",
"stacks": []string{"some-stack"},
"uri": "yarn-dependency-uri",
},
},
},
},
Launch: packit.LaunchMetadata{
BOM: []packit.BOMEntry{
{
Name: "yarn",
Metadata: map[string]interface{}{
"name": "yarn-dependency-name",
"sha256": "yarn-dependency-sha",
"stacks": []string{"some-stack"},
"uri": "yarn-dependency-uri",
},
},
},
},
}))
})
})
Expand Down Expand Up @@ -306,7 +309,7 @@ func testBuild(t *testing.T, context spec.G, it spec.S) {

context("when the dependency cannot be installed", func() {
it.Before(func() {
dependencyManager.InstallCall.Returns.Error = errors.New("failed to install dependency")
dependencyManager.DeliverCall.Returns.Error = errors.New("failed to install dependency")
})

it("returns an error", func() {
Expand Down
2 changes: 1 addition & 1 deletion buildpack.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
api = "0.4"
api = "0.5"

[buildpack]
homepage = "https://github.com/paketo-buildpacks/yarn"
Expand Down
33 changes: 0 additions & 33 deletions fakes/build_plan_refinery.go

This file was deleted.

Loading

0 comments on commit 7d032e5

Please sign in to comment.