-
Notifications
You must be signed in to change notification settings - Fork 11
/
build.go
115 lines (92 loc) · 3.27 KB
/
build.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package yarn
import (
"path/filepath"
"time"
"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(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)
Deliver(dependency postal.Dependency, cnbPath, layerPath, platformPath string) error
GenerateBillOfMaterials(dependencies ...postal.Dependency) []packit.BOMEntry
}
func Build(
entryResolver EntryResolver,
dependencyManager DependencyManager,
clock chronos.Clock,
logger scribe.Emitter,
) packit.BuildFunc {
return func(context packit.BuildContext) (packit.BuildResult, error) {
logger.Title("%s %s", context.BuildpackInfo.Name, context.BuildpackInfo.Version)
yarnLayer, err := context.Layers.Get(YarnLayerName)
if err != nil {
return packit.BuildResult{}, err
}
entry, _ := entryResolver.Resolve("yarn", context.Plan.Entries, nil)
version, ok := entry.Metadata["version"].(string)
if !ok {
version = "default"
}
dependency, err := dependencyManager.Resolve(
filepath.Join(context.CNBPath, "buildpack.toml"),
entry.Name,
version,
context.Stack)
if err != nil {
return packit.BuildResult{}, err
}
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{
Layers: []packit.Layer{yarnLayer},
Build: buildMetadata,
Launch: launchMetadata,
}, nil
}
logger.Process("Executing build process")
yarnLayer, err = yarnLayer.Reset()
if err != nil {
return packit.BuildResult{}, err
}
yarnLayer.Launch, yarnLayer.Build, yarnLayer.Cache = launch, build, build
logger.Subprocess("Installing Yarn")
duration, err := clock.Measure(func() error {
return dependencyManager.Deliver(dependency, context.CNBPath, yarnLayer.Path, context.Platform.Path)
})
if err != nil {
return packit.BuildResult{}, err
}
logger.Action("Completed in %s", duration.Round(time.Millisecond))
logger.Break()
yarnLayer.Metadata = map[string]interface{}{
DependencyCacheKey: dependency.SHA256,
"built_at": clock.Now().Format(time.RFC3339Nano),
}
return packit.BuildResult{
Layers: []packit.Layer{yarnLayer},
Build: buildMetadata,
Launch: launchMetadata,
}, nil
}
}