Skip to content

Commit

Permalink
Merge pull request #425 from buildpacks/fix/289-package-meta-buildpack
Browse files Browse the repository at this point in the history
Fix: support meta-buildpack in packages
  • Loading branch information
ameyer-pivotal authored Dec 19, 2019
2 parents 9d2c80e + 29b4189 commit bc8881c
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 19 deletions.
28 changes: 15 additions & 13 deletions internal/buildpackage/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,27 @@ func (p *PackageBuilder) Save(repoName string, publish bool) (imgutil.Image, err
}

stacks := p.buildpack.Descriptor().Stacks
if len(stacks) == 0 {
return nil, errors.Errorf(
"buildpack %s must support at least one stack",
style.Symbol(p.buildpack.Descriptor().Info.FullName()),
)
}

for _, bp := range p.dependencies {
bpd := bp.Descriptor()
stacks = stack.MergeCompatible(stacks, bpd.Stacks)

if len(stacks) == 0 {
return nil, errors.Errorf(
"buildpack %s does not support any stacks from %s",
style.Symbol(p.buildpack.Descriptor().Info.FullName()),
style.Symbol(bpd.Info.FullName()),
)
stacks = bpd.Stacks
} else if len(bpd.Stacks) > 0 { // skip over "meta-buildpacks"
stacks = stack.MergeCompatible(stacks, bpd.Stacks)
if len(stacks) == 0 {
return nil, errors.Errorf(
"buildpack %s does not support any stacks from %s",
style.Symbol(p.buildpack.Descriptor().Info.FullName()),
style.Symbol(bpd.Info.FullName()),
)
}
}
}

if len(stacks) == 0 {
return nil, errors.Errorf("no compatible stacks among provided buildpacks")
}

image, err := p.imageFactory.NewImage(repoName, !publish)
if err != nil {
return nil, errors.Wrapf(err, "creating image")
Expand Down
163 changes: 157 additions & 6 deletions internal/buildpackage/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ func testPackageBuilder(t *testing.T, when spec.G, it spec.S) {
})

when("#Save", func() {
when("validate default", func() {
when("default not set", func() {
when("validate buildpack", func() {
when("buildpack not set", func() {
it("returns error", func() {
_, err := subject.Save(fakePackageImage.Name(), false)
h.AssertError(t, err, "buildpack must be set")
Expand All @@ -58,22 +58,66 @@ func testPackageBuilder(t *testing.T, when spec.G, it spec.S) {
})

when("validate stacks", func() {
when("buildpack doesn't have a declared stack", func() {
it("should error", func() {
when("buildpack is meta-buildpack", func() {
it("should succeed", func() {
buildpack, err := ifakes.NewFakeBuildpack(dist.BuildpackDescriptor{
API: api.MustParse("0.2"),
Info: dist.BuildpackInfo{
ID: "bp.1.id",
Version: "bp.1.version",
},
Stacks: nil,
Order: dist.Order{{
Group: []dist.BuildpackRef{
{BuildpackInfo: dist.BuildpackInfo{ID: "bp.nested.id", Version: "bp.nested.version"}},
},
}},
}, 0644)
h.AssertNil(t, err)

subject.SetBuildpack(buildpack)

dependency, err := ifakes.NewFakeBuildpack(dist.BuildpackDescriptor{
API: api.MustParse("0.2"),
Info: dist.BuildpackInfo{
ID: "bp.nested.id",
Version: "bp.nested.version",
},
Stacks: []dist.Stack{
{ID: "stack.id.1", Mixins: []string{"Mixin-A"}},
},
Order: nil,
}, 0644)
h.AssertNil(t, err)

subject.AddDependency(dependency)

_, err = subject.Save("some/package", false)
h.AssertNil(t, err)
})
})

when("buildpack is meta-buildpack and its dependency is missing", func() {
it("should return an error", func() {
buildpack, err := ifakes.NewFakeBuildpack(dist.BuildpackDescriptor{
API: api.MustParse("0.2"),
Info: dist.BuildpackInfo{
ID: "bp.1.id",
Version: "bp.1.version",
},
Stacks: nil,
Order: nil,
Order: dist.Order{{
Group: []dist.BuildpackRef{
{BuildpackInfo: dist.BuildpackInfo{ID: "bp.nested.id", Version: "bp.nested.version"}},
},
}},
}, 0644)
h.AssertNil(t, err)

subject.SetBuildpack(buildpack)

_, err = subject.Save("some/package", false)
h.AssertError(t, err, "buildpack '[email protected]' must support at least one stack")
h.AssertError(t, err, "no compatible stacks among provided buildpacks")
})
})

Expand Down Expand Up @@ -157,6 +201,113 @@ func testPackageBuilder(t *testing.T, when spec.G, it spec.S) {
h.AssertEq(t, metadata.Stacks, []dist.Stack{{ID: "stack.id.1", Mixins: []string{"Mixin-A"}}})
})
})

when("dependency is meta-buildpack", func() {
it("should succeed and compute common stacks", func() {
buildpack, err := ifakes.NewFakeBuildpack(dist.BuildpackDescriptor{
API: api.MustParse("0.2"),
Info: dist.BuildpackInfo{
ID: "bp.1.id",
Version: "bp.1.version",
},
Stacks: nil,
Order: dist.Order{{
Group: []dist.BuildpackRef{
{BuildpackInfo: dist.BuildpackInfo{ID: "bp.nested.id", Version: "bp.nested.version"}},
},
}},
}, 0644)
h.AssertNil(t, err)

subject.SetBuildpack(buildpack)

dependencyOrder, err := ifakes.NewFakeBuildpack(dist.BuildpackDescriptor{
API: api.MustParse("0.2"),
Info: dist.BuildpackInfo{
ID: "bp.nested.id",
Version: "bp.nested.version",
},
Order: dist.Order{{
Group: []dist.BuildpackRef{
{BuildpackInfo: dist.BuildpackInfo{
ID: "bp.nested.nested.id",
Version: "bp.nested.nested.version",
}},
},
}},
}, 0644)
h.AssertNil(t, err)

subject.AddDependency(dependencyOrder)

dependencyNestedNested, err := ifakes.NewFakeBuildpack(dist.BuildpackDescriptor{
API: api.MustParse("0.2"),
Info: dist.BuildpackInfo{
ID: "bp.nested.nested.id",
Version: "bp.nested.nested.version",
},
Stacks: []dist.Stack{
{ID: "stack.id.1", Mixins: []string{"Mixin-A"}},
},
Order: nil,
}, 0644)
h.AssertNil(t, err)

subject.AddDependency(dependencyNestedNested)

img, err := subject.Save("some/package", false)
h.AssertNil(t, err)

metadata := buildpackage.Metadata{}
_, err = dist.GetLabel(img, "io.buildpacks.buildpackage.metadata", &metadata)
h.AssertNil(t, err)

h.AssertEq(t, metadata.Stacks, []dist.Stack{{ID: "stack.id.1", Mixins: []string{"Mixin-A"}}})
})
})

when("dependency is meta-buildpack and its dependency is missing", func() {
it("should return an error", func() {
buildpack, err := ifakes.NewFakeBuildpack(dist.BuildpackDescriptor{
API: api.MustParse("0.2"),
Info: dist.BuildpackInfo{
ID: "bp.1.id",
Version: "bp.1.version",
},
Stacks: nil,
Order: dist.Order{{
Group: []dist.BuildpackRef{
{BuildpackInfo: dist.BuildpackInfo{ID: "bp.nested.id", Version: "bp.nested.version"}},
},
}},
}, 0644)
h.AssertNil(t, err)

subject.SetBuildpack(buildpack)

dependencyOrder, err := ifakes.NewFakeBuildpack(dist.BuildpackDescriptor{
API: api.MustParse("0.2"),
Info: dist.BuildpackInfo{
ID: "bp.nested.id",
Version: "bp.nested.version",
},
Order: dist.Order{{
Group: []dist.BuildpackRef{
{BuildpackInfo: dist.BuildpackInfo{
ID: "bp.nested.nested.id",
Version: "bp.nested.nested.version",
}},
},
}},
}, 0644)
h.AssertNil(t, err)

subject.AddDependency(dependencyOrder)

_, err = subject.Save("some/package", false)
h.AssertError(t, err, "no compatible stacks among provided buildpacks")
})
})
})

it("sets metadata", func() {
Expand Down

0 comments on commit bc8881c

Please sign in to comment.