diff --git a/internal/commands/buildpack_package.go b/internal/commands/buildpack_package.go index 15489e8cd8..2a1d52120a 100644 --- a/internal/commands/buildpack_package.go +++ b/internal/commands/buildpack_package.go @@ -22,6 +22,7 @@ type BuildpackPackageFlags struct { Publish bool Policy string BuildpackRegistry string + Buildpack string } // BuildpackPackager packages buildpacks @@ -60,7 +61,12 @@ func BuildpackPackage(logger logging.Logger, cfg config.Config, client Buildpack if err != nil { return errors.Wrap(err, "parsing pull policy") } - + var bpPath string + if flags.Buildpack != "" { + if bpPath, err = filepath.Abs(flags.Buildpack); err != nil { + return errors.Wrap(err, "resolving buildpack path") + } + } bpPackageCfg := pubbldpkg.DefaultConfig() relativeBaseDir := "" if flags.PackageTomlPath != "" { @@ -74,7 +80,9 @@ func BuildpackPackage(logger logging.Logger, cfg config.Config, client Buildpack return errors.Wrap(err, "getting absolute path for config") } } - + if bpPath != "" { + bpPackageCfg.Buildpack.URI = bpPath + } name := args[0] if err := client.PackageBuildpack(cmd.Context(), pack.PackageBuildpackOptions{ RelativeBaseDir: relativeBaseDir, @@ -98,10 +106,11 @@ func BuildpackPackage(logger logging.Logger, cfg config.Config, client Buildpack }), } - cmd.Flags().StringVarP(&flags.PackageTomlPath, "config", "c", "", "Path to package TOML config (required)") + cmd.Flags().StringVarP(&flags.PackageTomlPath, "config", "c", "", "Path to package TOML config") cmd.Flags().StringVarP(&flags.Format, "format", "f", "", `Format to save package as ("image" or "file")`) cmd.Flags().BoolVar(&flags.Publish, "publish", false, `Publish to registry (applies to "--format=image" only)`) cmd.Flags().StringVar(&flags.Policy, "pull-policy", "", "Pull policy to use. Accepted values are always, never, and if-not-present. The default is always") + cmd.Flags().StringVarP(&flags.Buildpack, "buildpack", "b", "", "Path to the Buildpack that needs to be packaged. If config is specified, the Buildpack URI is overridden to this value.") cmd.Flags().StringVarP(&flags.BuildpackRegistry, "buildpack-registry", "r", "", "Buildpack Registry name") AddHelpFlag(cmd, "package") diff --git a/internal/commands/buildpack_package_test.go b/internal/commands/buildpack_package_test.go index df3aeade1a..8e424ab976 100644 --- a/internal/commands/buildpack_package_test.go +++ b/internal/commands/buildpack_package_test.go @@ -3,6 +3,7 @@ package commands_test import ( "bytes" "fmt" + "path/filepath" "testing" "github.com/heroku/color" @@ -87,6 +88,29 @@ func testPackageCommand(t *testing.T, when spec.G, it spec.S) { h.AssertEq(t, receivedOptions.Config, myConfig) }) + when("there is a buildpack flag", func() { + it("overrides with config returned by the reader with the buildpack uri with the passed flag", func() { + myConfig := pubbldpkg.Config{ + Buildpack: dist.BuildpackURI{URI: "test"}, + } + + cmd := packageCommand( + withBuildpackPackager(fakeBuildpackPackager), + withPackageConfigReader(fakes.NewFakePackageConfigReader(whereReadReturns(myConfig, nil))), + withBuildpack(".."), + ) + err := cmd.Execute() + h.AssertNil(t, err) + bpPath, _ := filepath.Abs("..") + expectedConfig := pubbldpkg.Config{ + Buildpack: dist.BuildpackURI{URI: bpPath}, + } + + receivedOptions := fakeBuildpackPackager.CreateCalledWithOptions + h.AssertEq(t, receivedOptions.Config, expectedConfig) + }) + }) + when("pull-policy", func() { var pullPolicyArgs = []string{ "some-image-name", @@ -147,13 +171,25 @@ func testPackageCommand(t *testing.T, when spec.G, it spec.S) { }) when("no config path is specified", func() { - it("creates a default config", func() { - cmd := packageCommand(withBuildpackPackager(fakeBuildpackPackager)) - cmd.SetArgs([]string{"some-name"}) - h.AssertNil(t, cmd.Execute()) + when("no buildpack is specified", func() { + it("creates a default config", func() { + cmd := packageCommand(withBuildpackPackager(fakeBuildpackPackager)) + cmd.SetArgs([]string{"some-name"}) + h.AssertNil(t, cmd.Execute()) - receivedOptions := fakeBuildpackPackager.CreateCalledWithOptions - h.AssertEq(t, receivedOptions.Config.Buildpack.URI, ".") + receivedOptions := fakeBuildpackPackager.CreateCalledWithOptions + h.AssertEq(t, receivedOptions.Config.Buildpack.URI, ".") + }) + }) + when("a buildpack is specified", func() { + it("creates a default config with the appropriate buildpack", func() { + cmd := packageCommand(withBuildpackPackager(fakeBuildpackPackager)) + cmd.SetArgs([]string{"some-name", "-b", ".."}) + h.AssertNil(t, cmd.Execute()) + bpPath, _ := filepath.Abs("..") + receivedOptions := fakeBuildpackPackager.CreateCalledWithOptions + h.AssertEq(t, receivedOptions.Config.Buildpack.URI, bpPath) + }) }) }) }) @@ -223,6 +259,7 @@ type packageCommandConfig struct { clientConfig config.Config imageName string configPath string + buildpack string } type packageCommandOption func(config *packageCommandConfig) @@ -242,7 +279,7 @@ func packageCommand(ops ...packageCommandOption) *cobra.Command { } cmd := commands.BuildpackPackage(config.logger, config.clientConfig, config.buildpackPackager, config.packageConfigReader) - cmd.SetArgs([]string{config.imageName, "--config", config.configPath}) + cmd.SetArgs([]string{config.imageName, "--config", config.configPath, "-b", config.buildpack}) return cmd } @@ -271,6 +308,12 @@ func withImageName(name string) packageCommandOption { } } +func withBuildpack(name string) packageCommandOption { + return func(config *packageCommandConfig) { + config.buildpack = name + } +} + func withPackageConfigPath(path string) packageCommandOption { return func(config *packageCommandConfig) { config.configPath = path