Skip to content

Commit

Permalink
Merge pull request buildpacks#1983 from buildpacks/fix/builder-with-e…
Browse files Browse the repository at this point in the history
…xtensions-fails-creator

Allow the build to proceed with /cnb/lifecycle/creator when the order contains extensions
  • Loading branch information
jjbustamante authored Dec 20, 2023
2 parents 18cdd3d + 8fb9749 commit c08b289
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 37 deletions.
4 changes: 2 additions & 2 deletions internal/build/lifecycle_execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,8 @@ func (l *LifecycleExecution) Run(ctx context.Context, phaseFactoryCreator PhaseF
return l.Export(ctx, buildCache, launchCache, kanikoCache, phaseFactory)
}

if l.platformAPI.AtLeast("0.10") && l.hasExtensions() {
return errors.New("builder has an order for extensions which is not supported when using the creator")
if l.platformAPI.AtLeast("0.10") && l.hasExtensions() && !l.opts.UseCreatorWithExtensions {
return errors.New("builder has an order for extensions which is not supported when using the creator; re-run without '--trust-builder' or re-tag builder to avoid trusting it")
}
return l.Create(ctx, buildCache, launchCache, phaseFactory)
}
Expand Down
21 changes: 21 additions & 0 deletions internal/build/lifecycle_execution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ func testLifecycleExecution(t *testing.T, when spec.G, it spec.S) {

extensionsForBuild, extensionsForRun bool
extensionsRunImage string
useCreatorWithExtensions bool
)

var configureDefaultTestLifecycle = func(opts *build.LifecycleOptions) {
Expand All @@ -91,6 +92,7 @@ func testLifecycleExecution(t *testing.T, when spec.G, it spec.S) {
opts.Volumes = providedVolumes
opts.Layout = providedLayout
opts.Keychain = authn.DefaultKeychain
opts.UseCreatorWithExtensions = useCreatorWithExtensions

targetImageRef, err := name.ParseReference(providedTargetImage)
h.AssertNil(t, err)
Expand Down Expand Up @@ -380,6 +382,25 @@ func testLifecycleExecution(t *testing.T, when spec.G, it spec.S) {
})
h.AssertNotNil(t, err)
})

when("use creator with extensions supported by the lifecycle", func() {
useCreatorWithExtensions = true

it("allows the build to proceed (but the creator will error if extensions are detected)", func() {
err := lifecycle.Run(context.Background(), func(execution *build.LifecycleExecution) build.PhaseFactory {
return fakePhaseFactory
})
h.AssertNil(t, err)

h.AssertEq(t, len(fakePhaseFactory.NewCalledWithProvider), 1)

for _, entry := range fakePhaseFactory.NewCalledWithProvider {
if entry.Name() == "creator" {
h.AssertSliceContains(t, entry.ContainerConfig().Cmd, providedTargetImage)
}
}
})
})
})
})
})
Expand Down
1 change: 1 addition & 0 deletions internal/build/lifecycle_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ type LifecycleOptions struct {
Publish bool
TrustBuilder bool
UseCreator bool
UseCreatorWithExtensions bool
Interactive bool
Layout bool
Termui Termui
Expand Down
76 changes: 41 additions & 35 deletions pkg/client/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,10 @@ import (
)

const (
minLifecycleVersionSupportingCreator = "0.7.4"
prevLifecycleVersionSupportingImage = "0.6.1"
minLifecycleVersionSupportingImage = "0.7.5"
minLifecycleVersionSupportingCreator = "0.7.4"
prevLifecycleVersionSupportingImage = "0.6.1"
minLifecycleVersionSupportingImage = "0.7.5"
minLifecycleVersionSupportingCreatorWithExtensions = "0.19.0"
)

// LifecycleExecutor executes the lifecycle which satisfies the Cloud Native Buildpacks Lifecycle specification.
Expand Down Expand Up @@ -513,38 +514,39 @@ func (c *Client) Build(ctx context.Context, opts BuildOptions) error {
}

lifecycleOpts := build.LifecycleOptions{
AppPath: appPath,
Image: imageRef,
Builder: ephemeralBuilder,
BuilderImage: builderRef.Name(),
LifecycleImage: ephemeralBuilder.Name(),
RunImage: runImageName,
ProjectMetadata: projectMetadata,
ClearCache: opts.ClearCache,
Publish: opts.Publish,
TrustBuilder: opts.TrustBuilder(opts.Builder),
UseCreator: useCreator,
DockerHost: opts.DockerHost,
Cache: opts.Cache,
CacheImage: opts.CacheImage,
HTTPProxy: proxyConfig.HTTPProxy,
HTTPSProxy: proxyConfig.HTTPSProxy,
NoProxy: proxyConfig.NoProxy,
Network: opts.ContainerConfig.Network,
AdditionalTags: opts.AdditionalTags,
Volumes: processedVolumes,
DefaultProcessType: opts.DefaultProcessType,
FileFilter: fileFilter,
Workspace: opts.Workspace,
GID: opts.GroupID,
PreviousImage: opts.PreviousImage,
Interactive: opts.Interactive,
Termui: termui.NewTermui(imageName, ephemeralBuilder, runImageName),
ReportDestinationDir: opts.ReportDestinationDir,
SBOMDestinationDir: opts.SBOMDestinationDir,
CreationTime: opts.CreationTime,
Layout: opts.Layout(),
Keychain: c.keychain,
AppPath: appPath,
Image: imageRef,
Builder: ephemeralBuilder,
BuilderImage: builderRef.Name(),
LifecycleImage: ephemeralBuilder.Name(),
RunImage: runImageName,
ProjectMetadata: projectMetadata,
ClearCache: opts.ClearCache,
Publish: opts.Publish,
TrustBuilder: opts.TrustBuilder(opts.Builder),
UseCreator: useCreator,
UseCreatorWithExtensions: supportsCreatorWithExtensions(lifecycleVersion),
DockerHost: opts.DockerHost,
Cache: opts.Cache,
CacheImage: opts.CacheImage,
HTTPProxy: proxyConfig.HTTPProxy,
HTTPSProxy: proxyConfig.HTTPSProxy,
NoProxy: proxyConfig.NoProxy,
Network: opts.ContainerConfig.Network,
AdditionalTags: opts.AdditionalTags,
Volumes: processedVolumes,
DefaultProcessType: opts.DefaultProcessType,
FileFilter: fileFilter,
Workspace: opts.Workspace,
GID: opts.GroupID,
PreviousImage: opts.PreviousImage,
Interactive: opts.Interactive,
Termui: termui.NewTermui(imageName, ephemeralBuilder, runImageName),
ReportDestinationDir: opts.ReportDestinationDir,
SBOMDestinationDir: opts.SBOMDestinationDir,
CreationTime: opts.CreationTime,
Layout: opts.Layout(),
Keychain: c.keychain,
}

switch {
Expand Down Expand Up @@ -740,6 +742,10 @@ func supportsCreator(lifecycleVersion *builder.Version) bool {
return !lifecycleVersion.LessThan(semver.MustParse(minLifecycleVersionSupportingCreator))
}

func supportsCreatorWithExtensions(lifecycleVersion *builder.Version) bool {
return !lifecycleVersion.LessThan(semver.MustParse(minLifecycleVersionSupportingCreatorWithExtensions))
}

func supportsLifecycleImage(lifecycleVersion *builder.Version) bool {
return lifecycleVersion.Equal(builder.VersionMustParse(prevLifecycleVersionSupportingImage)) ||
!lifecycleVersion.LessThan(semver.MustParse(minLifecycleVersionSupportingImage))
Expand Down
34 changes: 34 additions & 0 deletions pkg/client/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2611,6 +2611,40 @@ api = "0.2"
})
})
})

when("use creator with extensions", func() {
when("lifecycle is old", func() {
it("false", func() {
oldLifecycleBuilder := newFakeBuilderImage(t, tmpDir, "example.com/old-lifecycle-builder:tag", defaultBuilderStackID, defaultRunImageName, "0.18.0", newLinuxImage)
defer oldLifecycleBuilder.Cleanup()
fakeImageFetcher.LocalImages[oldLifecycleBuilder.Name()] = oldLifecycleBuilder

h.AssertNil(t, subject.Build(context.TODO(), BuildOptions{
Image: "some/app",
Builder: oldLifecycleBuilder.Name(),
TrustBuilder: func(string) bool { return true },
}))

h.AssertEq(t, fakeLifecycle.Opts.UseCreatorWithExtensions, false)
})
})

when("lifecycle is new", func() {
it("true", func() {
newLifecycleBuilder := newFakeBuilderImage(t, tmpDir, "example.com/new-lifecycle-builder:tag", defaultBuilderStackID, defaultRunImageName, "0.19.0", newLinuxImage)
defer newLifecycleBuilder.Cleanup()
fakeImageFetcher.LocalImages[newLifecycleBuilder.Name()] = newLifecycleBuilder

h.AssertNil(t, subject.Build(context.TODO(), BuildOptions{
Image: "some/app",
Builder: newLifecycleBuilder.Name(),
TrustBuilder: func(string) bool { return true },
}))

h.AssertEq(t, fakeLifecycle.Opts.UseCreatorWithExtensions, true)
})
})
})
})

when("validating mixins", func() {
Expand Down

0 comments on commit c08b289

Please sign in to comment.