Skip to content

Commit 6ef6114

Browse files
authored
Merge pull request #186 from buildpack/lifecycle-semver
Parse lifecycle version as semver
2 parents eea7a39 + 14491be commit 6ef6114

26 files changed

+1465
-35
lines changed

acceptance/acceptance_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,6 +912,7 @@ func isCommandRunning(cmd *exec.Cmd) bool {
912912
return true
913913
}
914914

915+
// FIXME : buf needs a mutex
915916
func terminateAtStep(t *testing.T, cmd *exec.Cmd, buf *bytes.Buffer, pattern string) {
916917
t.Helper()
917918
var interruptSignal os.Signal

build/lifecycle.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"sync"
77
"time"
88

9+
"github.com/Masterminds/semver"
910
"github.com/docker/docker/client"
1011
"github.com/google/go-containerregistry/pkg/name"
1112
"github.com/pkg/errors"
@@ -75,10 +76,10 @@ func (l *Lifecycle) Execute(ctx context.Context, opts LifecycleOptions) error {
7576
l.logger.Verbose("Build cache %s cleared", style.Symbol(buildCache.Name()))
7677
}
7778

78-
if lifecycleVersion := l.builder.GetLifecycleVersion(); lifecycleVersion == "" {
79+
if lifecycleVersion := l.builder.GetLifecycleVersion(); lifecycleVersion == nil {
7980
l.logger.Verbose("Warning: lifecycle version unknown")
8081
} else {
81-
l.logger.Verbose("Executing lifecycle version %s", style.Symbol(lifecycleVersion))
82+
l.logger.Verbose("Executing lifecycle version %s", style.Symbol(lifecycleVersion.String()))
8283
}
8384

8485
l.logger.Verbose(style.Step("DETECTING"))
@@ -154,5 +155,8 @@ func randString(n int) string {
154155
}
155156

156157
func (l *Lifecycle) supportsVolumeCache() bool {
157-
return l.builder.GetLifecycleVersion() >= "0.2.0"
158+
if l.builder.GetLifecycleVersion() == nil {
159+
return false
160+
}
161+
return l.builder.GetLifecycleVersion().Compare(semver.MustParse("0.2.0")) >= 0
158162
}

builder/builder.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"time"
1313

1414
"github.com/BurntSushi/toml"
15+
"github.com/Masterminds/semver"
1516
"github.com/buildpack/imgutil"
1617
"github.com/pkg/errors"
1718

@@ -82,7 +83,7 @@ func (b *Builder) Description() string {
8283
return b.metadata.Description
8384
}
8485

85-
func (b *Builder) GetLifecycleVersion() string {
86+
func (b *Builder) GetLifecycleVersion() *semver.Version {
8687
return b.metadata.Lifecycle.Version
8788
}
8889

builder/builder_test.go

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"path/filepath"
88
"testing"
99

10+
"github.com/Masterminds/semver"
1011
"github.com/buildpack/imgutil/fakes"
1112
"github.com/fatih/color"
1213
"github.com/sclevine/spec"
@@ -193,15 +194,15 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) {
193194
when("#SetLifecycle", func() {
194195
it.Before(func() {
195196
h.AssertNil(t, subject.SetLifecycle(lifecycle.Metadata{
196-
Version: "1.2.3",
197+
Version: semver.MustParse("1.2.3"),
197198
Dir: filepath.Join("testdata", "lifecycle"),
198199
}))
199200
h.AssertNil(t, subject.Save())
200201
h.AssertEq(t, baseImage.IsSaved(), true)
201202
})
202203

203204
it("should set the lifecycle version successfully", func() {
204-
h.AssertEq(t, subject.GetLifecycleVersion(), "1.2.3")
205+
h.AssertEq(t, subject.GetLifecycleVersion().String(), "1.2.3")
205206
})
206207

207208
it("should add the lifecycle binaries as an image layer", func() {
@@ -244,6 +245,15 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) {
244245
h.HasFileMode(0755),
245246
)
246247
})
248+
249+
it("sets the lifecycle version on the metadata", func() {
250+
label, err := baseImage.Label("io.buildpacks.builder.metadata")
251+
h.AssertNil(t, err)
252+
253+
var metadata builder.Metadata
254+
h.AssertNil(t, json.Unmarshal([]byte(label), &metadata))
255+
h.AssertEq(t, metadata.Lifecycle.Version.String(), "1.2.3")
256+
})
247257
})
248258

249259
when("#AddBuildpack", func() {
@@ -348,7 +358,10 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) {
348358

349359
when("base image already has metadata", func() {
350360
it.Before(func() {
351-
h.AssertNil(t, baseImage.SetLabel("io.buildpacks.builder.metadata", `{"buildpacks": [{"id": "prev.id"}], "groups": [{"buildpacks": [{"id": "prev.id"}]}], "stack": {"runImage": {"image": "prev/run", "mirrors": ["prev/mirror"]}}}`))
361+
h.AssertNil(t, baseImage.SetLabel(
362+
"io.buildpacks.builder.metadata",
363+
`{"buildpacks": [{"id": "prev.id"}], "groups": [{"buildpacks": [{"id": "prev.id"}]}], "stack": {"runImage": {"image": "prev/run", "mirrors": ["prev/mirror"]}}, "lifecycle": {"version": "6.6.6"}}`,
364+
))
352365

353366
var err error
354367
subject, err = builder.New(baseImage, "some/builder")
@@ -377,6 +390,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) {
377390
h.AssertEq(t, metadata.Groups[0].Buildpacks[0].ID, "prev.id")
378391
h.AssertEq(t, metadata.Stack.RunImage.Image, "prev/run")
379392
h.AssertEq(t, metadata.Stack.RunImage.Mirrors[0], "prev/mirror")
393+
h.AssertEq(t, subject.GetLifecycleVersion().String(), "6.6.6")
380394

381395
// adds new buildpack
382396
h.AssertEq(t, metadata.Buildpacks[1].ID, "some-buildpack-id")

create_builder.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66

7+
"github.com/Masterminds/semver"
78
"github.com/buildpack/imgutil"
89
"github.com/pkg/errors"
910

@@ -24,6 +25,11 @@ func (c *Client) CreateBuilder(ctx context.Context, opts CreateBuilderOptions) e
2425
return errors.Wrap(err, "invalid builder config")
2526
}
2627

28+
lifecycleVersion, err := processLifecycleVersion(opts.BuilderConfig.Lifecycle.Version)
29+
if err != nil {
30+
return errors.Wrap(err, "invalid builder config")
31+
}
32+
2733
if err := c.validateRunImageConfig(ctx, opts); err != nil {
2834
return err
2935
}
@@ -70,7 +76,7 @@ func (c *Client) CreateBuilder(ctx context.Context, opts CreateBuilderOptions) e
7076

7177
builderImage.SetStackInfo(opts.BuilderConfig.Stack)
7278

73-
lifecycleMd, err := c.lifecycleFetcher.Fetch(opts.BuilderConfig.Lifecycle.Version, opts.BuilderConfig.Lifecycle.URI)
79+
lifecycleMd, err := c.lifecycleFetcher.Fetch(lifecycleVersion, opts.BuilderConfig.Lifecycle.URI)
7480
if err != nil {
7581
return errors.Wrap(err, "fetching lifecycle")
7682
}
@@ -82,6 +88,17 @@ func (c *Client) CreateBuilder(ctx context.Context, opts CreateBuilderOptions) e
8288
return builderImage.Save()
8389
}
8490

91+
func processLifecycleVersion(version string) (*semver.Version, error) {
92+
if version == "" {
93+
return nil, nil
94+
}
95+
v, err := semver.NewVersion(version)
96+
if err != nil {
97+
return nil, errors.Wrap(err, "lifecycle.version must be a valid semver")
98+
}
99+
return v, nil
100+
}
101+
85102
func validateBuilderConfig(conf builder.Config) error {
86103
if conf.Stack.ID == "" {
87104
return errors.New("stack.id is required")

create_builder_test.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"runtime"
1111
"testing"
1212

13+
"github.com/Masterminds/semver"
1314
"github.com/buildpack/imgutil/fakes"
1415
"github.com/fatih/color"
1516
"github.com/golang/mock/gomock"
@@ -82,7 +83,11 @@ func testCreateBuilder(t *testing.T, when spec.G, it spec.S) {
8283

8384
mockBPFetcher.EXPECT().FetchBuildpack(gomock.Any()).Return(bp, nil).AnyTimes()
8485

85-
mockLifecycleFetcher.EXPECT().Fetch(gomock.Any(), gomock.Any()).Return(lifecycle.Metadata{Dir: filepath.Join("testdata", "lifecycle"), Version: "3.4.5"}, nil).AnyTimes()
86+
mockLifecycleFetcher.EXPECT().Fetch(gomock.Any(), gomock.Any()).
87+
Return(lifecycle.Metadata{
88+
Dir: filepath.Join("testdata", "lifecycle"),
89+
Version: semver.MustParse("3.4.5"),
90+
}, nil).AnyTimes()
8691

8792
logOut, logErr = &bytes.Buffer{}, &bytes.Buffer{}
8893

@@ -150,6 +155,12 @@ func testCreateBuilder(t *testing.T, when spec.G, it spec.S) {
150155
err := subject.CreateBuilder(context.TODO(), opts)
151156
h.AssertError(t, err, "stack.run-image is required")
152157
})
158+
159+
it("should fail when lifecycle version is not a semver", func() {
160+
opts.BuilderConfig.Lifecycle.Version = "not-semver"
161+
err := subject.CreateBuilder(context.TODO(), opts)
162+
h.AssertError(t, err, "lifecycle.version must be a valid semver")
163+
})
153164
})
154165

155166
when("validating the run image config", func() {
@@ -201,7 +212,7 @@ func testCreateBuilder(t *testing.T, when spec.G, it spec.S) {
201212
Optional: false,
202213
}},
203214
}})
204-
h.AssertEq(t, builderImage.GetLifecycleVersion(), "3.4.5")
215+
h.AssertEq(t, builderImage.GetLifecycleVersion().String(), "3.4.5")
205216

206217
layerTar, err := fakeBuildImage.FindLayerWithPath("/lifecycle")
207218
h.AssertNil(t, err)

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ module github.com/buildpack/pack
22

33
require (
44
github.com/BurntSushi/toml v0.3.1
5+
github.com/Masterminds/semver v1.4.2
56
github.com/buildpack/imgutil v0.0.0-20190509214933-76de939dfb34
67
github.com/buildpack/lifecycle v0.1.1-0.20190510142604-8612386b1cea
78
github.com/dgodd/dockerdial v1.0.1

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7O
33
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
44
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
55
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
6+
github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc=
7+
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
68
github.com/Microsoft/go-winio v0.4.11 h1:zoIOcVf0xPN1tnMVbTtEdI+P8OofVk3NObnwOQ6nK2Q=
79
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
810
github.com/Microsoft/go-winio v0.4.12 h1:xAfWHN1IrQ0NJ9TBC0KBZoqLjzDTr1ML+4MywiUOryc=

inspect_builder.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ func (c *Client) InspectBuilder(name string, daemon bool) (*BuilderInfo, error)
4848
localMirrors = runImageConfig.Mirrors
4949
}
5050

51+
var lifecycleVersion string
52+
if ver := bldr.GetLifecycleVersion(); ver != nil {
53+
lifecycleVersion = ver.String()
54+
}
55+
5156
return &BuilderInfo{
5257
Description: bldr.Description(),
5358
Stack: bldr.StackID,
@@ -56,6 +61,6 @@ func (c *Client) InspectBuilder(name string, daemon bool) (*BuilderInfo, error)
5661
LocalRunImageMirrors: localMirrors,
5762
Buildpacks: bldr.GetBuildpacks(),
5863
Groups: bldr.GetOrder(),
59-
LifecycleVersion: bldr.GetLifecycleVersion(),
64+
LifecycleVersion: lifecycleVersion,
6065
}, nil
6166
}

inspect_builder_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ func testInspectBuilder(t *testing.T, when spec.G, it spec.S) {
103103
]
104104
}
105105
],
106-
"lifecycle": {"version": "some-lifecycle-version"}
106+
"lifecycle": {"version": "1.2.3"}
107107
}`))
108108
})
109109

@@ -159,7 +159,7 @@ func testInspectBuilder(t *testing.T, when spec.G, it spec.S) {
159159
it("sets the lifecycle version", func() {
160160
builderInfo, err := client.InspectBuilder("some/builder", useDaemon)
161161
h.AssertNil(t, err)
162-
h.AssertEq(t, builderInfo.LifecycleVersion, "some-lifecycle-version")
162+
h.AssertEq(t, builderInfo.LifecycleVersion, "1.2.3")
163163
})
164164
})
165165
})

0 commit comments

Comments
 (0)