Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add builder to project descriptor #1116

Merged
merged 2 commits into from
Apr 6, 2021
Merged

Conversation

sambhav
Copy link
Member

@sambhav sambhav commented Mar 22, 2021

Signed-off-by: Sambhav Kothari skothari44@bloomberg.net

Summary

Adds support for the builder key in project descriptor

Output

Before

After

Documentation

  • Should this change be documented?
    • Yes, see #___
    • No

Related

Resolves #1114
Implements buildpacks/rfcs#138 (We should wait for that to be merged before merging this I guess?)

Signed-off-by: Sambhav Kothari <skothari44@bloomberg.net>
@sambhav sambhav requested a review from a team as a code owner March 22, 2021 23:19
@github-actions github-actions bot added this to the 0.18.0 milestone Mar 22, 2021
@github-actions github-actions bot added the type/enhancement Issue that requests a new feature or improvement. label Mar 22, 2021
@@ -72,18 +72,30 @@ func Build(logger logging.Logger, cfg config.Config, packClient PackClient) *cob
logger.Debugf("Using project descriptor located at %s", style.Symbol(actualDescriptorPath))
}

builder := flags.Builder
Copy link
Member Author

Choose a reason for hiding this comment

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

This ended up being a bit weird to implement than I imagined.

We needed to do 2 things -

  1. Figure out if the user explicitly passed a flag or the default one was used.
  2. Parse the project descriptor and check if builder existed before before we could validate the bulder flag. In order to do so, I moved the builder validation out of validate flags as it was sort of a chicken egg problem where I had to use the project descriptor from the flags and parse it before I could validate the actual flags and that seemed to break the whole contract of validating the flags before using them. So for now I extracted this part out of validate flags and I explicitly check and throw an error if builder is null.

Copy link
Member Author

Choose a reason for hiding this comment

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

I also had to parse the builder and decide which one to use in the command instead of the client.Build as at that point it was too late to distinguish which flag was passed and the order of preference.

@codecov
Copy link

codecov bot commented Mar 22, 2021

Codecov Report

Merging #1116 (dc94db0) into main (e00ee4a) will decrease coverage by 0.52%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1116      +/-   ##
==========================================
- Coverage   80.52%   80.00%   -0.51%     
==========================================
  Files         136      136              
  Lines        8243     6005    -2238     
==========================================
- Hits         6637     4804    -1833     
+ Misses       1176      767     -409     
- Partials      430      434       +4     
Flag Coverage Δ
os_linux 79.97% <100.00%> (-0.02%) ⬇️
os_macos 77.49% <100.00%> (-0.02%) ⬇️
os_windows 100.00% <ø> (+19.57%) ⬆️
unit 80.00% <100.00%> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Copy link
Member

@dfreilich dfreilich left a comment

Choose a reason for hiding this comment

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

This is great! One small concern is that we don't have a unit test for the case where a default builder was previously set in the config, but we test it in our acceptance tests here (

when("default builder is set", func() {
it.Before(func() {
pack.RunSuccessfully("config", "default-builder", builderName)
pack.JustRunSuccessfully("config", "trusted-builders", "add", builderName)
})
it("creates a runnable, rebuildable image on daemon from app dir", func() {
appPath := filepath.Join("testdata", "mock_app")
output := pack.RunSuccessfully(
"build", repoName,
"-p", appPath,
)
assertOutput := assertions.NewOutputAssertionManager(t, output)
assertOutput.ReportsSuccessfulImageBuild(repoName)
assertOutput.ReportsUsingBuildCacheVolume()
assertOutput.ReportsSelectingRunImageMirror(runImageMirror)
t.Log("app is runnable")
assertImage.RunsWithOutput(repoName, "Launch Dep Contents", "Cached Dep Contents")
t.Log("it uses the run image as a base image")
assertImage.HasBaseImage(repoName, runImage)
t.Log("sets the run image metadata")
assertImage.HasLabelWithData(repoName, "io.buildpacks.lifecycle.metadata", fmt.Sprintf(`"stack":{"runImage":{"image":"%s","mirrors":["%s"]}}}`, runImage, runImageMirror))
t.Log("registry is empty")
assertImage.NotExistsInRegistry(repo)
t.Log("add a local mirror")
localRunImageMirror := registryConfig.RepoName("pack-test/run-mirror")
imageManager.TagImage(runImage, localRunImageMirror)
defer imageManager.CleanupImages(localRunImageMirror)
pack.JustRunSuccessfully("config", "run-image-mirrors", "add", runImage, "-m", localRunImageMirror)
t.Log("rebuild")
output = pack.RunSuccessfully(
"build", repoName,
"-p", appPath,
)
assertOutput = assertions.NewOutputAssertionManager(t, output)
assertOutput.ReportsSuccessfulImageBuild(repoName)
assertOutput.ReportsSelectingRunImageMirrorFromLocalConfig(localRunImageMirror)
cachedLaunchLayer := "simple/layers:cached-launch-layer"
assertLifecycleOutput := assertions.NewLifecycleOutputAssertionManager(t, output)
assertLifecycleOutput.ReportsRestoresCachedLayer(cachedLaunchLayer)
assertLifecycleOutput.ReportsExporterReusingUnchangedLayer(cachedLaunchLayer)
assertLifecycleOutput.ReportsCacheReuse(cachedLaunchLayer)
t.Log("app is runnable")
assertImage.RunsWithOutput(repoName, "Launch Dep Contents", "Cached Dep Contents")
t.Log("rebuild with --clear-cache")
output = pack.RunSuccessfully("build", repoName, "-p", appPath, "--clear-cache")
assertOutput = assertions.NewOutputAssertionManager(t, output)
assertOutput.ReportsSuccessfulImageBuild(repoName)
assertLifecycleOutput = assertions.NewLifecycleOutputAssertionManager(t, output)
assertLifecycleOutput.ReportsSkippingBuildpackLayerAnalysis()
assertLifecycleOutput.ReportsExporterReusingUnchangedLayer(cachedLaunchLayer)
assertLifecycleOutput.ReportsCacheCreation(cachedLaunchLayer)
t.Log("cacher adds layers")
assert.Matches(output, regexp.MustCompile(`(?i)Adding cache layer 'simple/layers:cached-launch-layer'`))
t.Log("inspecting image")
inspectCmd := "inspect"
if !pack.Supports("inspect") {
inspectCmd = "inspect-image"
}
var (
webCommand string
helloCommand string
helloArgs []string
helloArgsPrefix string
)
if imageManager.HostOS() == "windows" {
webCommand = ".\\run"
helloCommand = "cmd"
helloArgs = []string{"/c", "echo hello world"}
helloArgsPrefix = " "
} else {
webCommand = "./run"
helloCommand = "echo"
helloArgs = []string{"hello", "world"}
helloArgsPrefix = ""
}
formats := []compareFormat{
{
extension: "txt",
compareFunc: assert.TrimmedEq,
outputArg: "human-readable",
},
{
extension: "json",
compareFunc: assert.EqualJSON,
outputArg: "json",
},
{
extension: "yaml",
compareFunc: assert.EqualYAML,
outputArg: "yaml",
},
{
extension: "toml",
compareFunc: assert.EqualTOML,
outputArg: "toml",
},
}
for _, format := range formats {
t.Logf("inspecting image %s format", format.outputArg)
output = pack.RunSuccessfully(inspectCmd, repoName, "--output", format.outputArg)
expectedOutput := pack.FixtureManager().TemplateFixture(
fmt.Sprintf("inspect_image_local_output.%s", format.extension),
map[string]interface{}{
"image_name": repoName,
"base_image_id": h.ImageID(t, runImageMirror),
"base_image_top_layer": h.TopLayerDiffID(t, runImageMirror),
"run_image_local_mirror": localRunImageMirror,
"run_image_mirror": runImageMirror,
"web_command": webCommand,
"hello_command": helloCommand,
"hello_args": helloArgs,
"hello_args_prefix": helloArgsPrefix,
},
)
format.compareFunc(output, expectedOutput)
}
})
) so it's ok.

@dfreilich dfreilich merged commit 236700e into buildpacks:main Apr 6, 2021
@sambhav sambhav deleted the builder branch April 6, 2021 06:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type/enhancement Issue that requests a new feature or improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

RFC 138: Add builder to project descriptor
3 participants