Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions buildpack/descriptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,23 +61,28 @@ func ReadGroup(path string) (Group, error) {
return group, err
}

func ReadOrder(path string) (Order, error) {
var order struct {
Order Order `toml:"order"`
func ReadOrder(path string) (Order, Order, error) {
var order struct { // TODO: move this maybe
Order Order `toml:"order"`
OrderExt Order `toml:"order-ext"`
}
_, err := toml.DecodeFile(path, &order)
return order.Order, err
return order.Order, order.OrderExt, err
}

// TODO: GroupElement is probably a better name for this
// TODO: this struct is the amalgamation of all fields from order.toml & group.toml, which is a bit confusing and ties the code together in weird ways

// A GroupBuildable represents a buildpack or extension referenced in a buildpack.toml's [[order.group]].
// A GroupBuildable buildpack may be a regular buildpack, or a meta buildpack.
type GroupBuildable struct {
API string `toml:"api,omitempty" json:"-"`
Homepage string `toml:"homepage,omitempty" json:"homepage,omitempty"`
API string `toml:"api,omitempty" json:"-"` // group.toml
Homepage string `toml:"homepage,omitempty" json:"homepage,omitempty"` // group.toml
ID string `toml:"id" json:"id"`
Version string `toml:"version" json:"version"`
Extension bool `toml:"extension,omitempty" json:"extension,omitempty"` // TODO: check if this is okay, suggested to RFC
Optional bool `toml:"optional,omitempty" json:"optional,omitempty"`
Extension bool `toml:"extension" json:"extension"` // group.toml
Optional bool `toml:"optional,omitempty" json:"optional,omitempty"` // order.toml
OrderExt Order `toml:"-" json:"-"` // only for use by the Detector
}

func (b GroupBuildable) String() string {
Expand Down
2 changes: 1 addition & 1 deletion buildpack/descriptor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func testDescriptor(t *testing.T, when spec.G, it spec.S) {
`group = [{id = "C"}, {}]`+"\n",
filepath.Join(tmpDir, "order.toml"),
)
actual, err := buildpack.ReadOrder(filepath.Join(tmpDir, "order.toml"))
actual, _, err := buildpack.ReadOrder(filepath.Join(tmpDir, "order.toml"))
if err != nil {
t.Fatalf("Unexpected error:\n%s\n", err)
}
Expand Down
33 changes: 31 additions & 2 deletions cmd/lifecycle/detector.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,43 @@ func (d *detectCmd) Exec() error {
}

func (da detectArgs) detect() (buildpack.Group, platform.BuildPlan, error) {
order, err := buildpack.ReadOrder(da.orderPath)
order, orderExt, err := buildpack.ReadOrder(da.orderPath)
if err != nil {
return buildpack.Group{}, platform.BuildPlan{}, cmd.FailErr(err, "read buildpack order file")
}
if err := da.verifyBuildableApis(order); err != nil {
return buildpack.Group{}, platform.BuildPlan{}, err
}

// TODO: this is pretty horrible, but it "works"
if len(orderExt) > 0 {
// update `Extension` for each group element, as this field is not defined in order.toml
for i, extGroup := range orderExt {
for j, el := range extGroup.Group {
el.Extension = true
extGroup.Group[j] = el
}
orderExt[i] = buildpack.Group{
Group: extGroup.Group,
}
}
// create group element to hold `order-ext`
extGroupElement := buildpack.GroupBuildable{
ID: "some-order-ext-id",
Version: "some-order-ext-version",
Optional: true, // TODO: should this always be true, for the whole order?
OrderExt: orderExt,
}
// add `orderExt` as a "metabuildpack" inside each group
for i, group := range order {
order[i] = buildpack.Group{
Group: append([]buildpack.GroupBuildable{extGroupElement}, group.Group...),
}
}
cmd.DefaultLogger.Infof("XXXXXXXXXX New order: %+v", order)
}
if err := da.verifyBuildableApis(orderExt); err != nil {
return buildpack.Group{}, platform.BuildPlan{}, err
}
detector, err := lifecycle.NewDetector(buildpack.DetectConfig{
AppDir: da.appDir,
PlatformDir: da.platformDir,
Expand Down
9 changes: 7 additions & 2 deletions detector.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

"github.com/pkg/errors"

"github.com/buildpacks/lifecycle/api"
"github.com/buildpacks/lifecycle/buildpack"
"github.com/buildpacks/lifecycle/env"
"github.com/buildpacks/lifecycle/platform"
Expand Down Expand Up @@ -115,7 +116,11 @@ func (d *Detector) detectGroup(group buildpack.Group, done []buildpack.GroupBuil
buildable buildpack.Buildable
err error
)
if groupBuildable.Extension {
if len(groupBuildable.OrderExt) > 0 {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we make d.ExtensionStore.Lookup return a buildable that represents a metabuildpack given a known groupBuildable.ID or similar? That way we can fall into the existing bpDesc.IsMetaBuildpack below?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would probably be better than the current implementation :)

Part of the pain IMO is the fact that GroupBuildable (what was formerly GroupBuildpack) is used everywhere throughout the code, for different reasons - representing the contents of order.toml, representing the contents of group.toml (with a slightly different schema), "printing" the identifier of a buildpack in a label (e.g., to associate a bom entry with a buildpack). I started to look into what might make this code a bit nicer, but it seemed to be a lot of work :/ We might look at it for the "real" implementation.

That aside, I agree with your suggestion. That and #802 (comment) would make the store interface more useful.

// lookup won't return anything, because "order-ext" is defined in order.toml only (no buildpack.toml exists)
groupBuildable.API = api.Buildpack.Latest().String() // TODO: fix
return d.detectOrder(groupBuildable.OrderExt, done, group.Group[i+1:], groupBuildable.Optional, wg)
} else if groupBuildable.Extension {
if !groupBuildable.Optional {
// TODO: warn or error?
groupBuildable.Optional = true
Expand Down Expand Up @@ -366,7 +371,7 @@ type detectTrial []detectOption
func (ts detectTrial) remove(bp buildpack.GroupBuildable) detectTrial {
var out detectTrial
for _, t := range ts {
if t.GroupBuildable != bp {
if t.GroupBuildable.ID != bp.ID || t.GroupBuildable.Version != bp.Version { // TODO: confirm if this works
out = append(out, t)
}
}
Expand Down
12 changes: 4 additions & 8 deletions extender/testdata/layers/order.toml
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
[[order]]
[[order.group]]
[[order-ext]]
[[order-ext.group]]
id = "samples/curl"
version = "0.0.1"
extension = true
optional = true

[[order.group]]
[[order-ext.group]]
id = "samples/rebasable"
version = "0.0.1"
extension = true
optional = true

[[order]]
[[order.group]]
id = "samples/use_curl"
version = "0.0.1"
extension = false
optional = false
1 change: 1 addition & 0 deletions platform/order.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package platform