Skip to content

Commit

Permalink
Add pre and post buildpacks
Browse files Browse the repository at this point in the history
Co-authored-by: Johannes Dillmann <[email protected]>
Co-authored-by: Ralf Pannemans <[email protected]>
Co-authored-by: Pavel Busko <[email protected]>
  • Loading branch information
3 people committed Jul 5, 2023
1 parent b9bb526 commit 6e54c6a
Show file tree
Hide file tree
Showing 18 changed files with 901 additions and 98 deletions.
41 changes: 35 additions & 6 deletions cmd/cnbBuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,29 @@ func processConfigs(main cnbBuildOptions, multipleImages []map[string]interface{
return result, nil
}

func setCustomBuildpacks(bpacks []string, dockerCreds string, utils cnbutils.BuildUtils) (string, string, error) {
func setCustomBuildpacks(bpacks, preBuildpacks, postBuildpacks []string, dockerCreds string, utils cnbutils.BuildUtils) (string, string, error) {
buildpacksPath := "/tmp/buildpacks"
orderPath := "/tmp/buildpacks/order.toml"
newOrder, err := cnbutils.DownloadBuildpacks(buildpacksPath, bpacks, dockerCreds, utils)
err := cnbutils.DownloadBuildpacks(buildpacksPath, append(bpacks, append(preBuildpacks, postBuildpacks...)...), dockerCreds, utils)
if err != nil {
return "", "", err
}

if len(bpacks) == 0 && (len(postBuildpacks) > 0 || len(preBuildpacks) > 0) {
matches, err := utils.Glob("/cnb/buildpacks/*")
if err != nil {
return "", "", err
}

for _, match := range matches {
err = cnbutils.CreateVersionSymlinks(buildpacksPath, match, utils)
if err != nil {
return "", "", err
}
}
}

newOrder, err := cnbutils.CreateOrder(bpacks, preBuildpacks, postBuildpacks, dockerCreds, utils)
if err != nil {
return "", "", err
}
Expand Down Expand Up @@ -475,10 +494,18 @@ func runCnbBuild(config *cnbBuildOptions, cnbTelemetry *cnbBuildTelemetry, utils

config.mergeEnvVars(descriptor.EnvVars)

if (config.Buildpacks == nil || len(config.Buildpacks) == 0) && len(descriptor.Buildpacks) > 0 {
if len(config.Buildpacks) == 0 && len(descriptor.Buildpacks) > 0 {
config.Buildpacks = descriptor.Buildpacks
}

if len(config.PreBuildpacks) == 0 && len(descriptor.PreBuildpacks) > 0 {
config.PreBuildpacks = descriptor.PreBuildpacks
}

if len(config.PostBuildpacks) == 0 && len(descriptor.PostBuildpacks) > 0 {
config.PostBuildpacks = descriptor.PostBuildpacks
}

if descriptor.Exclude != nil {
exclude = descriptor.Exclude
}
Expand Down Expand Up @@ -563,11 +590,13 @@ func runCnbBuild(config *cnbBuildOptions, cnbTelemetry *cnbBuildTelemetry, utils
metadata.WriteProjectMetadata(GeneralConfig.EnvRootPath, utils)

var buildpacksPath = "/cnb/buildpacks"
var orderPath = "/cnb/order.toml"
var orderPath = cnbutils.DefaultOrderPath

if config.Buildpacks != nil && len(config.Buildpacks) > 0 {
if len(config.Buildpacks) > 0 || len(config.PreBuildpacks) > 0 || len(config.PostBuildpacks) > 0 {
log.Entry().Infof("Setting custom buildpacks: '%v'", config.Buildpacks)
buildpacksPath, orderPath, err = setCustomBuildpacks(config.Buildpacks, config.DockerConfigJSON, utils)
log.Entry().Infof("Pre-buildpacks: '%v'", config.PreBuildpacks)
log.Entry().Infof("Post-buildpacks: '%v'", config.PostBuildpacks)
buildpacksPath, orderPath, err = setCustomBuildpacks(config.Buildpacks, config.PreBuildpacks, config.PostBuildpacks, config.DockerConfigJSON, utils)
defer func() { _ = utils.RemoveAll(buildpacksPath) }()
defer func() { _ = utils.RemoveAll(orderPath) }()
if err != nil {
Expand Down
34 changes: 33 additions & 1 deletion cmd/cnbBuild_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

124 changes: 113 additions & 11 deletions cmd/cnbBuild_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,23 +25,56 @@ import (
const imageRegistry = "some-registry"

func newCnbBuildTestsUtils() cnbutils.MockUtils {
imageStub := func(imageRef, target string) (v1.Image, error) {
fakeImage := &fake.FakeImage{}
var imageConfig v1.Config
switch imageRef {
case "pre-test":
imageConfig = v1.Config{
Labels: map[string]string{
"io.buildpacks.buildpackage.metadata": "{\"id\": \"pre-testbuildpack\", \"version\": \"0.0.1\"}",
},
}
case "post-test":
imageConfig = v1.Config{
Labels: map[string]string{
"io.buildpacks.buildpackage.metadata": "{\"id\": \"post-testbuildpack\", \"version\": \"0.0.1\"}",
},
}
default:
imageConfig = v1.Config{
Labels: map[string]string{
"io.buildpacks.buildpackage.metadata": "{\"id\": \"testbuildpack\", \"version\": \"0.0.1\"}",
},
}
}

fakeImage.ConfigFileReturns(&v1.ConfigFile{
Config: imageConfig,
}, nil)

return fakeImage, nil
}

utils := cnbutils.MockUtils{
ExecMockRunner: &mock.ExecMockRunner{},
FilesMock: &mock.FilesMock{},
DownloadMock: &mock.DownloadMock{},
}

fakeImage := &fake.FakeImage{}
fakeImage.ConfigFileReturns(&v1.ConfigFile{
Config: v1.Config{
Labels: map[string]string{
"io.buildpacks.buildpackage.metadata": "{\"id\": \"testbuildpack\", \"version\": \"0.0.1\"}",
DownloadMock: &mock.DownloadMock{
ImageContentStub: imageStub,
ImageInfoStub: func(imageRef string) (v1.Image, error) {
return imageStub(imageRef, "")
},
},
}, nil)
}

utils.RemoteImageInfo = fakeImage
utils.ReturnImage = fakeImage
utils.AddFile("/cnb/order.toml", []byte(`[[order]]
[[order.group]]
id = "buildpacks/java"
version = "1.8.0"
[[order]]
[[order.group]]
id = "buildpacks/nodejs"
version = "1.6.0"`))
utils.AddFile("/layers/report.toml", []byte(`[build]
[image]
tags = ["localhost:5000/not-found:0.0.1"]
Expand Down Expand Up @@ -234,6 +267,75 @@ func TestRunCnbBuild(t *testing.T) {
assert.True(t, copiedFileExists)
})

t.Run("success case (custom buildpacks, pre and post buildpacks and custom env variables, renaming docker conf file, additional tag)", func(t *testing.T) {
t.Parallel()
config := cnbBuildOptions{
ContainerImageName: "my-image",
ContainerImageTag: "0.0.1",
ContainerRegistryURL: imageRegistry,
DockerConfigJSON: "/path/to/test.json",
PreBuildpacks: []string{"pre-test"},
PostBuildpacks: []string{"post-test"},
Buildpacks: []string{"test"},
BuildEnvVars: map[string]interface{}{
"FOO": "BAR",
},
AdditionalTags: []string{"latest"},
}

utils := newCnbBuildTestsUtils()
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
addBuilderFiles(&utils)

err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{})

require.NoError(t, err)
runner := utils.ExecMockRunner
assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}")
assert.Equal(t, creatorPath, runner.Calls[0].Exec)
assert.Contains(t, runner.Calls[0].Params, "/tmp/buildpacks")
assert.Contains(t, runner.Calls[0].Params, "/tmp/buildpacks/order.toml")
assert.Contains(t, runner.Calls[0].Params, fmt.Sprintf("%s/%s:%s", config.ContainerRegistryURL, config.ContainerImageName, config.ContainerImageTag))
assert.Contains(t, runner.Calls[0].Params, fmt.Sprintf("%s/%s:latest", config.ContainerRegistryURL, config.ContainerImageName))

copiedFileExists, _ := utils.FileExists("/tmp/config.json")
assert.True(t, copiedFileExists)
})

t.Run("success case (custom pre and post buildpacks and custom env variables, renaming docker conf file, additional tag)", func(t *testing.T) {
t.Parallel()
config := cnbBuildOptions{
ContainerImageName: "my-image",
ContainerImageTag: "0.0.1",
ContainerRegistryURL: imageRegistry,
DockerConfigJSON: "/path/to/test.json",
PostBuildpacks: []string{"post-test"},
PreBuildpacks: []string{"pre-test"},
BuildEnvVars: map[string]interface{}{
"FOO": "BAR",
},
AdditionalTags: []string{"latest"},
}

utils := newCnbBuildTestsUtils()
utils.FilesMock.AddFile(config.DockerConfigJSON, []byte(`{"auths":{"my-registry":{"auth":"dXNlcjpwYXNz"}}}`))
addBuilderFiles(&utils)

err := callCnbBuild(&config, &telemetry.CustomData{}, &utils, &cnbBuildCommonPipelineEnvironment{}, &piperhttp.Client{})

require.NoError(t, err)
runner := utils.ExecMockRunner
assert.Contains(t, runner.Env, "CNB_REGISTRY_AUTH={\"my-registry\":\"Basic dXNlcjpwYXNz\"}")
assert.Equal(t, creatorPath, runner.Calls[0].Exec)
assert.Contains(t, runner.Calls[0].Params, "/tmp/buildpacks")
assert.Contains(t, runner.Calls[0].Params, "/tmp/buildpacks/order.toml")
assert.Contains(t, runner.Calls[0].Params, fmt.Sprintf("%s/%s:%s", config.ContainerRegistryURL, config.ContainerImageName, config.ContainerImageTag))
assert.Contains(t, runner.Calls[0].Params, fmt.Sprintf("%s/%s:latest", config.ContainerRegistryURL, config.ContainerImageName))

copiedFileExists, _ := utils.FileExists("/tmp/config.json")
assert.True(t, copiedFileExists)
})

t.Run("success case (customTlsCertificates)", func(t *testing.T) {
t.Parallel()
httpmock.Activate()
Expand Down
1 change: 1 addition & 0 deletions integration/github_actions_integration_test_list.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ run:
- '"TestCNBIntegrationNPMCustomBuildpacksBuildpacklessProject"'
- '"TestCNBIntegrationNPMCustomBuildpacksFullProject"'
- '"TestCNBIntegrationProjectDescriptor"'
- '"TestCNBIntegrationPrePostBuildpacks"'

- '"TestGolangIntegration"'
- '"TestGradleIntegration"'
Expand Down
26 changes: 25 additions & 1 deletion integration/integration_cnb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (

const (
registryURL = "localhost:5000"
baseBuilder = "paketobuildpacks/builder:0.3.26-base"
baseBuilder = "paketobuildpacks/builder:0.3.280-base"
)

func setupDockerRegistry(t *testing.T, ctx context.Context) testcontainers.Container {
Expand Down Expand Up @@ -334,3 +334,27 @@ func TestCNBIntegrationPreserveFilesIgnored(t *testing.T) {
container.assertHasOutput(t, "skipping preserving files because the source")
container.terminate(t)
}

func TestCNBIntegrationPrePostBuildpacks(t *testing.T) {
t.Parallel()
ctx := context.Background()
registryContainer := setupDockerRegistry(t, ctx)
defer registryContainer.Terminate(ctx)

container := givenThisContainer(t, IntegrationTestDockerExecRunnerBundle{
Image: baseBuilder,
User: "cnb",
TestDir: []string{"testdata", "TestCnbIntegration"},
Network: fmt.Sprintf("container:%s", registryContainer.GetContainerID()),
Environment: map[string]string{
"PIPER_VAULTCREDENTIAL_DYNATRACE_API_KEY": "api-key-content",
},
})

err := container.whenRunningPiperCommand("cnbBuild", "--noTelemetry", "--verbose", "--projectDescriptor", "", "--path", "project", "--customConfig", "config.yml", "--containerImageTag", "0.0.1", "--containerImageName", "not-found", "--containerRegistryUrl", registryURL, "--postBuildpacks", "paketobuildpacks/datadog")
assert.NoError(t, err)
container.assertHasOutput(t, "Setting custom buildpacks: '[]'")
container.assertHasOutput(t, "Pre-buildpacks: '[]'")
container.assertHasOutput(t, "Post-buildpacks: '[paketobuildpacks/datadog]'")
container.terminate(t)
}
3 changes: 3 additions & 0 deletions integration/testdata/TestCnbIntegration/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ general:
collectTelemetryData: false
steps:
cnbBuild:
buildEnvVars:
BP_DATADOG_ENABLED: true
BP_EAR_KEY: 74657374
bindings:
maven-settings:
type: maven
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "test-mta-js",
"version": "1.0.0",
"main": "srv/hello.js",
"dependencies": {
"jest": "^26.0.1",
"jest-jenkins-reporter": "^1.0.2"
Expand Down
Loading

0 comments on commit 6e54c6a

Please sign in to comment.