diff --git a/builder.go b/builder.go index 748b97ac2..16900d82f 100644 --- a/builder.go +++ b/builder.go @@ -100,15 +100,11 @@ func (b *Builder) Build() (*BuildMetadata, error) { labels = append(labels, br.Labels...) plan = plan.filter(br.MetRequires) - replacedDefault := processMap.add(br.Processes) - if err != nil { - return nil, err - } + warning := processMap.add(br.Processes) - if replacedDefault != "" { - warning := fmt.Sprintf("Warning: redefining the following default process type with a process not marked as default: %s", replacedDefault) + if warning != "" { if _, err := b.Out.Write([]byte(warning)); err != nil { - return nil, err + return nil, err } } slices = append(slices, br.Slices...) @@ -217,25 +213,21 @@ func newProcessMap() processMap { // This function adds the processes from listToAdd to processMap // it sets m.defaultType to the last default process -// if a non-default process overrides a default process, it returns its type and unset m.defaultType +// if a non-default process overrides a default process, it returns a warning and unset m.defaultType func (m *processMap) add(listToAdd []launch.Process) string { - result := "" + warning := "" for _, procToAdd := range listToAdd { if procToAdd.Default { m.defaultType = procToAdd.Type - result = "" - } else { - existingProc, ok := m.typeToProcess[procToAdd.Type] - if ok && existingProc.Type == m.defaultType { // existingProc.Default = true - // non-default process overrides a default process - m.defaultType = "" - result = procToAdd.Type - } + warning = "" + } else if procToAdd.Type == m.defaultType { + // non-default process overrides a default process + m.defaultType = "" + warning = fmt.Sprintf("Warning: redefining the following default process type with a process not marked as default: %s\n", procToAdd.Type) } m.typeToProcess[procToAdd.Type] = procToAdd } - - return result + return warning } // list returns a sorted array of processes. @@ -249,9 +241,7 @@ func (m processMap) list() []launch.Process { sort.Strings(keys) result := []launch.Process{} for _, key := range keys { - processWithNoDefault := m.typeToProcess[key] - processWithNoDefault.Default = false // we set the default to false so it won't be part of metadata.toml - result = append(result, processWithNoDefault) + result = append(result, m.typeToProcess[key].NoDefault()) // we set the default to false so it won't be part of metadata.toml } return result } diff --git a/builder_test.go b/builder_test.go index 2d5f1f1c3..d7d4988f7 100644 --- a/builder_test.go +++ b/builder_test.go @@ -721,5 +721,100 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { }) }) }) + + when("platform api < 0.6", func() { + it.Before(func() { + builder.PlatformAPI = api.MustParse("0.5") + }) + + when("there is a web process", func() { + when("buildpack API >= 0.6", func() { + it.Before(func() { + builder.Group.Group = []lifecycle.GroupBuildpack{ + {ID: "A", Version: "v1", API: latestBuildpackAPI.String()}, + } + }) + it("shouldn't set it as a default process", func() { + bpA := testmock.NewMockBuildpack(mockCtrl) + buildpackStore.EXPECT().Lookup("A", "v1").Return(bpA, nil) + bpA.EXPECT().Build(gomock.Any(), config).Return(lifecycle.BuildResult{ + Processes: []launch.Process{ + { + Type: "web", + Command: "web-cmd", + Args: []string{"web-arg"}, + Direct: false, + BuildpackID: "A", + Default: false, + }, + }, + }, nil) + + metadata, err := builder.Build() + if err != nil { + t.Fatalf("Unexpected error:\n%s\n", err) + } + + if s := cmp.Diff(metadata.Processes, []launch.Process{ + { + Type: "web", + Command: "web-cmd", + Args: []string{"web-arg"}, + Direct: false, + BuildpackID: "A", + Default: false, + }, + }); s != "" { + t.Fatalf("Unexpected:\n%s\n", s) + } + h.AssertEq(t, metadata.BuildpackDefaultProcessType, "") + }) + }) + + when("buildpack api < 0.6", func() { + it.Before(func() { + builder.Group.Group = []lifecycle.GroupBuildpack{ + {ID: "A", Version: "v1", API: "0.5"}, + } + }) + + it("shouldn't set it as a default process", func() { + bpA := testmock.NewMockBuildpack(mockCtrl) + buildpackStore.EXPECT().Lookup("A", "v1").Return(bpA, nil) + bpA.EXPECT().Build(gomock.Any(), config).Return(lifecycle.BuildResult{ + Processes: []launch.Process{ + { + Type: "web", + Command: "web-cmd", + Args: []string{"web-arg"}, + Direct: false, + BuildpackID: "A", + Default: false, + }, + }, + }, nil) + + metadata, err := builder.Build() + if err != nil { + t.Fatalf("Unexpected error:\n%s\n", err) + } + + if s := cmp.Diff(metadata.Processes, []launch.Process{ + { + Type: "web", + Command: "web-cmd", + Args: []string{"web-arg"}, + Direct: false, + BuildpackID: "A", + Default: false, + }, + }); s != "" { + t.Fatalf("Unexpected:\n%s\n", s) + } + h.AssertEq(t, metadata.BuildpackDefaultProcessType, "") + }) + }) + }) + }) }) } diff --git a/exporter_test.go b/exporter_test.go index 60cb7c896..bf81a14e0 100644 --- a/exporter_test.go +++ b/exporter_test.go @@ -400,7 +400,6 @@ version = "4.5.6" expectedJSON := ` { "bom": null, - "buildpack-default-process-type": "", "buildpacks": [ { "id": "buildpack.id", @@ -458,7 +457,6 @@ version = "4.5.6" } } ], - "buildpack-default-process-type": "", "buildpacks": [ { "id": "buildpack.id", @@ -486,8 +484,7 @@ version = "4.5.6" "direct": true, "command": "/some/command", "args": ["some", "command", "args"], - "buildpackID": "buildpack.id", - "default": false + "buildpackID": "buildpack.id" } ] } @@ -949,7 +946,7 @@ version = "4.5.6" _, err := exporter.Export(opts) h.AssertNil(t, err) - checkEntrypoint(t, fakeAppImage, filepath.Join(rootDir, "cnb", "process", "some-process-type"+execExt)) + assertHasEntrypoint(t, fakeAppImage, filepath.Join(rootDir, "cnb", "process", "some-process-type"+execExt)) }) it("doesn't set CNB_PROCESS_TYPE", func() { @@ -984,7 +981,7 @@ version = "4.5.6" _, err := exporter.Export(opts) h.AssertNil(t, err) assertLogEntry(t, logHandler, "no default process type") - checkEntrypoint(t, fakeAppImage, filepath.Join(rootDir, "cnb", "lifecycle", "launcher"+execExt)) + assertHasEntrypoint(t, fakeAppImage, filepath.Join(rootDir, "cnb", "lifecycle", "launcher"+execExt)) }) }) @@ -1011,7 +1008,7 @@ version = "4.5.6" it("sets the ENTRYPOINT to this process type", func() { _, err := exporter.Export(opts) h.AssertNil(t, err) - checkEntrypoint(t, fakeAppImage, filepath.Join(rootDir, "cnb", "process", "some-process-type"+execExt)) + assertHasEntrypoint(t, fakeAppImage, filepath.Join(rootDir, "cnb", "process", "some-process-type"+execExt)) }) it("doesn't set CNB_PROCESS_TYPE", func() { @@ -1039,7 +1036,7 @@ version = "4.5.6" _, err := exporter.Export(opts) h.AssertNil(t, err) assertLogEntry(t, logHandler, "default process type 'some-non-existing-process-type' not present in list [some-process-type]") - checkEntrypoint(t, fakeAppImage, filepath.Join(rootDir, "cnb", "lifecycle", "launcher"+execExt)) + assertHasEntrypoint(t, fakeAppImage, filepath.Join(rootDir, "cnb", "lifecycle", "launcher"+execExt)) }) }) @@ -1047,7 +1044,7 @@ version = "4.5.6" it("sets the ENTRYPOINT to the only process", func() { _, err := exporter.Export(opts) h.AssertNil(t, err) - checkEntrypoint(t, fakeAppImage, filepath.Join(rootDir, "cnb", "process", "some-process-type"+execExt)) + assertHasEntrypoint(t, fakeAppImage, filepath.Join(rootDir, "cnb", "process", "some-process-type"+execExt)) }) }) }) @@ -1323,7 +1320,7 @@ version = "4.5.6" }) } -func checkEntrypoint(t *testing.T, image *fakes.Image, entrypointPath string) { +func assertHasEntrypoint(t *testing.T, image *fakes.Image, entrypointPath string) { ep, err := image.Entrypoint() h.AssertNil(t, err) h.AssertEq(t, len(ep), 1) diff --git a/launch/launch.go b/launch/launch.go index 868bac619..3d0c3e408 100644 --- a/launch/launch.go +++ b/launch/launch.go @@ -11,10 +11,15 @@ type Process struct { Command string `toml:"command" json:"command"` Args []string `toml:"args" json:"args"` Direct bool `toml:"direct" json:"direct"` - Default bool `toml:"default, omitzero" json:"default"` + Default bool `toml:"default,omitempty" json:"default,omitempty"` BuildpackID string `toml:"buildpack-id" json:"buildpackID"` } +func (p Process) NoDefault() Process { + p.Default = false + return p +} + // ProcessPath returns the absolute path to the symlink for a given process type func ProcessPath(pType string) string { return filepath.Join(ProcessDir, pType+exe) @@ -34,18 +39,6 @@ func (m Metadata) FindProcessType(pType string) (Process, bool) { return Process{}, false } -func (m Metadata) FindLastDefaultProcessType() (Process, bool) { - defaultFound := false - var lastDefaultProcess Process - for _, p := range m.Processes { - if p.Default { - lastDefaultProcess = p - defaultFound = true - } - } - return lastDefaultProcess, defaultFound -} - type Buildpack struct { API string `toml:"api"` ID string `toml:"id"` diff --git a/metadata.go b/metadata.go index b37067a7a..848d3fd97 100644 --- a/metadata.go +++ b/metadata.go @@ -22,7 +22,7 @@ type BuildMetadata struct { Launcher LauncherMetadata `toml:"-" json:"launcher"` Processes []launch.Process `toml:"processes" json:"processes"` Slices []layers.Slice `toml:"slices" json:"-"` - BuildpackDefaultProcessType string `toml:"buildpack-default-process-type, omitempty" json:"buildpack-default-process-type"` + BuildpackDefaultProcessType string `toml:"buildpack-default-process-type,omitempty" json:"buildpack-default-process-type,omitempty"` } type LauncherMetadata struct {