diff --git a/Makefile b/Makefile index 7722439d9f..558d08605e 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ tidy: mod-tidy mod-vendor format build: out @echo "> Building..." - $(GOCMD) build -ldflags "-s -w -X 'github.com/buildpacks/pack/cmd.Version=${PACK_VERSION}' -extldflags ${LDFLAGS}" -trimpath -o ./out/$(PACK_BIN) -a ./cmd/pack + $(GOCMD) build -ldflags "-s -w -X 'github.com/buildpacks/pack.Version=${PACK_VERSION}' -extldflags ${LDFLAGS}" -trimpath -o ./out/$(PACK_BIN) -a ./cmd/pack package: out tar czf ./out/$(ARCHIVE_NAME).tgz -C out/ pack diff --git a/build.go b/build.go index e80eb51659..75211538b3 100644 --- a/build.go +++ b/build.go @@ -19,7 +19,6 @@ import ( "github.com/google/go-containerregistry/pkg/name" "github.com/pkg/errors" - "github.com/buildpacks/pack/cmd" "github.com/buildpacks/pack/internal/api" "github.com/buildpacks/pack/internal/archive" "github.com/buildpacks/pack/internal/build" @@ -133,7 +132,7 @@ func (c *Client) Build(ctx context.Context, opts BuildOptions) error { } } if !supportsPlatform { - c.logger.Debugf("pack %s supports Platform API version(s): %s", cmd.Version, strings.Join(build.SupportedPlatformAPIVersions, ", ")) + c.logger.Debugf("pack %s supports Platform API version(s): %s", Version, strings.Join(build.SupportedPlatformAPIVersions, ", ")) c.logger.Debugf("Builder %s has Platform API version: %s", style.Symbol(opts.Builder), lcPlatformAPIVersion) return errors.Errorf("Builder %s is incompatible with this version of pack", style.Symbol(opts.Builder)) } @@ -602,7 +601,7 @@ func (c *Client) createEphemeralBuilder(rawBuilderImage imgutil.Image, env map[s bldr.SetOrder(order) } - if err := bldr.Save(c.logger); err != nil { + if err := bldr.Save(c.logger, Version); err != nil { return nil, err } return bldr, nil diff --git a/cli/pack_command.go b/cli/pack_command.go deleted file mode 100644 index fe47e47d60..0000000000 --- a/cli/pack_command.go +++ /dev/null @@ -1,104 +0,0 @@ -package cli - -import ( - "github.com/heroku/color" - "github.com/pkg/errors" - "github.com/spf13/cobra" - - "github.com/buildpacks/pack" - "github.com/buildpacks/pack/buildpackage" - "github.com/buildpacks/pack/cmd" - "github.com/buildpacks/pack/internal/commands" - "github.com/buildpacks/pack/internal/config" - clilogger "github.com/buildpacks/pack/internal/logging" - "github.com/buildpacks/pack/logging" -) - -// NewPackCommand generates a Pack command -func NewPackCommand(logger *clilogger.LogWithWriters) (*cobra.Command, error) { - cobra.EnableCommandSorting = false - cfg, err := initConfig() - if err != nil { - return nil, err - } - - packClient, err := initClient(logger, cfg) - if err != nil { - return nil, err - } - - rootCmd := &cobra.Command{ - Use: "pack", - PersistentPreRun: func(cmd *cobra.Command, args []string) { - if fs := cmd.Flags(); fs != nil { - if flag, err := fs.GetBool("no-color"); err == nil { - color.Disable(flag) - } - if flag, err := fs.GetBool("quiet"); err == nil { - logger.WantQuiet(flag) - } - if flag, err := fs.GetBool("verbose"); err == nil { - logger.WantVerbose(flag) - } - if flag, err := fs.GetBool("timestamps"); err == nil { - logger.WantTime(flag) - } - } - }, - } - - rootCmd.PersistentFlags().Bool("no-color", false, "Disable color output") - rootCmd.PersistentFlags().Bool("timestamps", false, "Enable timestamps in output") - rootCmd.PersistentFlags().BoolP("quiet", "q", false, "Show less output") - rootCmd.PersistentFlags().BoolP("verbose", "v", false, "Show more output") - rootCmd.Flags().Bool("version", false, "Show current 'pack' version") - - commands.AddHelpFlag(rootCmd, "pack") - - rootCmd.AddCommand(commands.Build(logger, cfg, &packClient)) - rootCmd.AddCommand(commands.Rebase(logger, cfg, &packClient)) - rootCmd.AddCommand(commands.InspectImage(logger, &cfg, &packClient)) - rootCmd.AddCommand(commands.SetRunImagesMirrors(logger, cfg)) - - rootCmd.AddCommand(commands.SetDefaultBuilder(logger, cfg, &packClient)) - rootCmd.AddCommand(commands.InspectBuilder(logger, cfg, &packClient)) - rootCmd.AddCommand(commands.SuggestBuilders(logger, &packClient)) - rootCmd.AddCommand(commands.TrustBuilder(logger, cfg)) - rootCmd.AddCommand(commands.CreateBuilder(logger, cfg, &packClient)) - - rootCmd.AddCommand(commands.PackageBuildpack(logger, &packClient, buildpackage.NewConfigReader())) - - rootCmd.AddCommand(commands.SuggestStacks(logger)) - - rootCmd.AddCommand(commands.Version(logger, cmd.Version)) - rootCmd.AddCommand(commands.Report(logger, cmd.Version)) - - rootCmd.AddCommand(commands.CompletionCommand(logger)) - - rootCmd.Version = cmd.Version - rootCmd.SetVersionTemplate(`{{.Version}}{{"\n"}}`) - - return rootCmd, nil -} - -func initConfig() (config.Config, error) { - path, err := config.DefaultConfigPath() - if err != nil { - return config.Config{}, errors.Wrap(err, "getting config path") - } - - cfg, err := config.Read(path) - if err != nil { - return config.Config{}, errors.Wrap(err, "reading pack config") - } - return cfg, nil -} - -func initClient(logger logging.Logger, cfg config.Config) (pack.Client, error) { - client, err := pack.NewClient(pack.WithLogger(logger), pack.WithExperimental(cfg.Experimental)) - if err != nil { - return *client, err - } - - return *client, nil -} diff --git a/cmd/cmd.go b/cmd/cmd.go index 3a347a3cf9..5b0a2c6c53 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -1,6 +1,103 @@ package cmd -var ( - // Version is the version of `pack`. It is injected at compile time. - Version = "0.0.0" +import ( + "github.com/heroku/color" + "github.com/pkg/errors" + "github.com/spf13/cobra" + + "github.com/buildpacks/pack" + "github.com/buildpacks/pack/buildpackage" + "github.com/buildpacks/pack/internal/commands" + "github.com/buildpacks/pack/internal/config" + clilogger "github.com/buildpacks/pack/internal/logging" + "github.com/buildpacks/pack/logging" ) + +// NewPackCommand generates a Pack command +func NewPackCommand(logger *clilogger.LogWithWriters) (*cobra.Command, error) { + cobra.EnableCommandSorting = false + cfg, err := initConfig() + if err != nil { + return nil, err + } + + packClient, err := initClient(logger, cfg) + if err != nil { + return nil, err + } + + rootCmd := &cobra.Command{ + Use: "pack", + PersistentPreRun: func(cmd *cobra.Command, args []string) { + if fs := cmd.Flags(); fs != nil { + if flag, err := fs.GetBool("no-color"); err == nil { + color.Disable(flag) + } + if flag, err := fs.GetBool("quiet"); err == nil { + logger.WantQuiet(flag) + } + if flag, err := fs.GetBool("verbose"); err == nil { + logger.WantVerbose(flag) + } + if flag, err := fs.GetBool("timestamps"); err == nil { + logger.WantTime(flag) + } + } + }, + } + + rootCmd.PersistentFlags().Bool("no-color", false, "Disable color output") + rootCmd.PersistentFlags().Bool("timestamps", false, "Enable timestamps in output") + rootCmd.PersistentFlags().BoolP("quiet", "q", false, "Show less output") + rootCmd.PersistentFlags().BoolP("verbose", "v", false, "Show more output") + rootCmd.Flags().Bool("version", false, "Show current 'pack' version") + + commands.AddHelpFlag(rootCmd, "pack") + + rootCmd.AddCommand(commands.Build(logger, cfg, &packClient)) + rootCmd.AddCommand(commands.Rebase(logger, cfg, &packClient)) + rootCmd.AddCommand(commands.InspectImage(logger, &cfg, &packClient)) + rootCmd.AddCommand(commands.SetRunImagesMirrors(logger, cfg)) + + rootCmd.AddCommand(commands.SetDefaultBuilder(logger, cfg, &packClient)) + rootCmd.AddCommand(commands.InspectBuilder(logger, cfg, &packClient)) + rootCmd.AddCommand(commands.SuggestBuilders(logger, &packClient)) + rootCmd.AddCommand(commands.TrustBuilder(logger, cfg)) + rootCmd.AddCommand(commands.CreateBuilder(logger, cfg, &packClient)) + + rootCmd.AddCommand(commands.PackageBuildpack(logger, &packClient, buildpackage.NewConfigReader())) + + rootCmd.AddCommand(commands.SuggestStacks(logger)) + + rootCmd.AddCommand(commands.Version(logger, pack.Version)) + rootCmd.AddCommand(commands.Report(logger, pack.Version)) + + rootCmd.AddCommand(commands.CompletionCommand(logger)) + + rootCmd.Version = pack.Version + rootCmd.SetVersionTemplate(`{{.Version}}{{"\n"}}`) + + return rootCmd, nil +} + +func initConfig() (config.Config, error) { + path, err := config.DefaultConfigPath() + if err != nil { + return config.Config{}, errors.Wrap(err, "getting config path") + } + + cfg, err := config.Read(path) + if err != nil { + return config.Config{}, errors.Wrap(err, "reading pack config") + } + return cfg, nil +} + +func initClient(logger logging.Logger, cfg config.Config) (pack.Client, error) { + client, err := pack.NewClient(pack.WithLogger(logger), pack.WithExperimental(cfg.Experimental)) + if err != nil { + return *client, err + } + + return *client, nil +} diff --git a/cmd/pack/main.go b/cmd/pack/main.go index 168ba75d09..0e8ed8d561 100644 --- a/cmd/pack/main.go +++ b/cmd/pack/main.go @@ -3,10 +3,11 @@ package main import ( "os" + "github.com/buildpacks/pack/cmd" + "github.com/heroku/color" "github.com/buildpacks/pack" - "github.com/buildpacks/pack/cli" "github.com/buildpacks/pack/internal/commands" clilogger "github.com/buildpacks/pack/internal/logging" ) @@ -15,7 +16,7 @@ func main() { // create logger with defaults logger := clilogger.NewLogWithWriters(color.Stdout(), color.Stderr()) - rootCmd, err := cli.NewPackCommand(logger) + rootCmd, err := cmd.NewPackCommand(logger) if err != nil { logger.Error(err.Error()) os.Exit(1) diff --git a/create_builder.go b/create_builder.go index 9f578d46b2..125c994fb2 100644 --- a/create_builder.go +++ b/create_builder.go @@ -45,7 +45,7 @@ func (c *Client) CreateBuilder(ctx context.Context, opts CreateBuilderOptions) e bldr.SetOrder(opts.Config.Order) bldr.SetStack(opts.Config.Stack) - return bldr.Save(c.logger) + return bldr.Save(c.logger, Version) } func (c *Client) validateConfig(ctx context.Context, opts CreateBuilderOptions) error { diff --git a/internal/builder/builder.go b/internal/builder/builder.go index 4458bf5cbe..de19a517b0 100644 --- a/internal/builder/builder.go +++ b/internal/builder/builder.go @@ -18,7 +18,6 @@ import ( "github.com/pkg/errors" "github.com/buildpacks/pack/builder" - "github.com/buildpacks/pack/cmd" "github.com/buildpacks/pack/internal/api" "github.com/buildpacks/pack/internal/archive" "github.com/buildpacks/pack/internal/dist" @@ -259,7 +258,7 @@ func (b *Builder) SetStack(stackConfig builder.StackConfig) { } // Save saves the builder -func (b *Builder) Save(logger logging.Logger) error { +func (b *Builder) Save(logger logging.Logger, version string) error { logger.Debugf("Creating builder with the following buildpacks:") for _, bpInfo := range b.metadata.Buildpacks { logger.Debugf("-> %s", style.Symbol(bpInfo.FullName())) @@ -373,7 +372,7 @@ func (b *Builder) Save(logger logging.Logger) error { b.metadata.CreatedBy = CreatorMetadata{ Name: packName, - Version: cmd.Version, + Version: version, } if err := dist.SetLabel(b.image, metadataLabel, b.metadata); err != nil { diff --git a/internal/builder/builder_test.go b/internal/builder/builder_test.go index 4ccc04bbe6..57cf06bd4a 100644 --- a/internal/builder/builder_test.go +++ b/internal/builder/builder_test.go @@ -210,13 +210,14 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { when("#Save", func() { it("creates a builder from the image and renames it", func() { - h.AssertNil(t, subject.Save(logger)) + h.AssertNil(t, subject.Save(logger, "")) h.AssertEq(t, baseImage.IsSaved(), true) h.AssertEq(t, baseImage.Name(), "some/builder") }) it("adds creator metadata", func() { - h.AssertNil(t, subject.Save(logger)) + testVersion := "1.2.5" + h.AssertNil(t, subject.Save(logger, testVersion)) h.AssertEq(t, baseImage.IsSaved(), true) label, err := baseImage.Label("io.buildpacks.builder.metadata") @@ -226,11 +227,11 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { h.AssertNil(t, json.Unmarshal([]byte(label), &metadata)) h.AssertEq(t, metadata.CreatedBy.Name, "Pack CLI") - h.AssertEq(t, metadata.CreatedBy.Version, "0.0.0") + h.AssertEq(t, metadata.CreatedBy.Version, testVersion) }) it("creates the workspace dir with CNB user and group", func() { - h.AssertNil(t, subject.Save(logger)) + h.AssertNil(t, subject.Save(logger, "")) h.AssertEq(t, baseImage.IsSaved(), true) layerTar, err := baseImage.FindLayerWithPath("/workspace") @@ -244,7 +245,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { }) it("creates the layers dir with CNB user and group", func() { - h.AssertNil(t, subject.Save(logger)) + h.AssertNil(t, subject.Save(logger, "")) h.AssertEq(t, baseImage.IsSaved(), true) layerTar, err := baseImage.FindLayerWithPath("/layers") @@ -258,7 +259,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { }) it("creates the cnb dir", func() { - h.AssertNil(t, subject.Save(logger)) + h.AssertNil(t, subject.Save(logger, "")) h.AssertEq(t, baseImage.IsSaved(), true) layerTar, err := baseImage.FindLayerWithPath("/cnb") @@ -272,7 +273,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { }) it("creates the buildpacks dir", func() { - h.AssertNil(t, subject.Save(logger)) + h.AssertNil(t, subject.Save(logger, "")) h.AssertEq(t, baseImage.IsSaved(), true) layerTar, err := baseImage.FindLayerWithPath("/cnb/buildpacks") @@ -286,7 +287,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { }) it("creates the platform dir", func() { - h.AssertNil(t, subject.Save(logger)) + h.AssertNil(t, subject.Save(logger, "")) h.AssertEq(t, baseImage.IsSaved(), true) layerTar, err := baseImage.FindLayerWithPath("/platform") @@ -306,7 +307,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { }) it("sets the working dir to the layers dir", func() { - h.AssertNil(t, subject.Save(logger)) + h.AssertNil(t, subject.Save(logger, "")) h.AssertEq(t, baseImage.IsSaved(), true) h.AssertEq(t, baseImage.WorkingDir(), "/layers") @@ -324,7 +325,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { h.AssertNil(t, baseImage.AddLayer(layerFile)) baseImage.Save() - h.AssertNil(t, subject.Save(logger)) + h.AssertNil(t, subject.Save(logger, "")) h.AssertEq(t, baseImage.IsSaved(), true) layerTar, err := baseImage.FindLayerWithPath("/cnb/order.toml") @@ -348,7 +349,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { {BuildpackInfo: dist.BuildpackInfo{ID: bp1v1.Descriptor().Info.ID}}}, }}) - err := subject.Save(logger) + err := subject.Save(logger, "") h.AssertNil(t, err) layerTar, err := baseImage.FindLayerWithPath("/cnb/order.toml") @@ -368,7 +369,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { {BuildpackInfo: dist.BuildpackInfo{ID: "missing-buildpack-id"}}}, }}) - err := subject.Save(logger) + err := subject.Save(logger, "") h.AssertError(t, err, "no versions of buildpack 'missing-buildpack-id' were found on the builder") }) @@ -381,7 +382,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { {BuildpackInfo: dist.BuildpackInfo{ID: "buildpack-1-id", Version: "missing-buildpack-version"}}}, }}) - err := subject.Save(logger) + err := subject.Save(logger, "") h.AssertError(t, err, "buildpack 'buildpack-1-id' with version 'missing-buildpack-version' was not found on the builder") }) @@ -401,7 +402,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { {BuildpackInfo: bp1v1.Descriptor().Info}}, }}) - err := subject.Save(logger) + err := subject.Save(logger, "") h.AssertNil(t, err) layerTar, err := baseImage.FindLayerWithPath("/cnb/order.toml") @@ -422,7 +423,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { {BuildpackInfo: dist.BuildpackInfo{ID: "buildpack-1-id"}}}, }}) - err := subject.Save(logger) + err := subject.Save(logger, "") h.AssertError(t, err, "multiple versions of 'buildpack-1-id' - must specify an explicit version") }) }) @@ -437,7 +438,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { subject.AddBuildpack(bpOrder) // order buildpack requires bp2v1 - err := subject.Save(logger) + err := subject.Save(logger, "") h.AssertError(t, err, "buildpack 'buildpack-2-id@buildpack-2-version-1' not found on the builder") }) @@ -451,7 +452,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { // order buildpack requires bp1v1 rather than bp1v2 subject.AddBuildpack(bpOrder) - err := subject.Save(logger) + err := subject.Save(logger, "") h.AssertError(t, err, "buildpack 'buildpack-1-id@buildpack-1-version-1' not found on the builder") }) @@ -468,7 +469,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { h.AssertNil(t, err) subject.AddBuildpack(bp) - err = subject.Save(logger) + err = subject.Save(logger, "") h.AssertError(t, err, "buildpack 'buildpack-1-id@buildpack-1-version-1' does not support stack 'some.stack.id'") }) @@ -484,7 +485,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { h.AssertNil(t, err) subject.AddBuildpack(bp) - err = subject.Save(logger) + err = subject.Save(logger, "") h.AssertError(t, err, "buildpack 'buildpack-1-id@buildpack-1-version-1' (Buildpack API version 0.1) is incompatible with lifecycle '1.2.3' (Buildpack API version 0.2)") }) @@ -503,7 +504,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { h.AssertNil(t, err) subject.AddBuildpack(bp) - err = subject.Save(logger) + err = subject.Save(logger, "") h.AssertError(t, err, "buildpack 'buildpack-1-id@buildpack-1-version-1' requires missing mixin(s): missing") }) @@ -515,7 +516,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { it.Before(func() { subject.SetLifecycle(mockLifecycle) - h.AssertNil(t, subject.Save(logger)) + h.AssertNil(t, subject.Save(logger, "")) h.AssertEq(t, baseImage.IsSaved(), true) }) @@ -598,7 +599,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { }) it("adds the buildpack as an image layer", func() { - h.AssertNil(t, subject.Save(logger)) + h.AssertNil(t, subject.Save(logger, "")) h.AssertEq(t, baseImage.IsSaved(), true) assertImageHasBPLayer(t, baseImage, bp1v1) assertImageHasBPLayer(t, baseImage, bp1v2) @@ -607,7 +608,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { }) it("adds the buildpack metadata", func() { - h.AssertNil(t, subject.Save(logger)) + h.AssertNil(t, subject.Save(logger, "")) h.AssertEq(t, baseImage.IsSaved(), true) label, err := baseImage.Label("io.buildpacks.builder.metadata") @@ -631,7 +632,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { }) it("adds the buildpack layers label", func() { - h.AssertNil(t, subject.Save(logger)) + h.AssertNil(t, subject.Save(logger, "")) h.AssertEq(t, baseImage.IsSaved(), true) label, err := baseImage.Label("io.buildpacks.buildpack.layers") @@ -699,7 +700,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { subject.SetLifecycle(mockLifecycle) - h.AssertNil(t, subject.Save(logger)) + h.AssertNil(t, subject.Save(logger, "")) h.AssertEq(t, baseImage.IsSaved(), true) }) @@ -750,7 +751,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { h.AssertNil(t, err) subject.AddBuildpack(bp1v1) - h.AssertNil(t, subject.Save(logger)) + h.AssertNil(t, subject.Save(logger, "")) h.AssertEq(t, baseImage.IsSaved(), true) }) @@ -795,7 +796,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { }}, }) - h.AssertNil(t, subject.Save(logger)) + h.AssertNil(t, subject.Save(logger, "")) h.AssertEq(t, baseImage.IsSaved(), true) }) @@ -839,7 +840,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { when("#SetDescription", func() { it.Before(func() { subject.SetDescription("Some description") - h.AssertNil(t, subject.Save(logger)) + h.AssertNil(t, subject.Save(logger, "")) h.AssertEq(t, baseImage.IsSaved(), true) }) @@ -859,7 +860,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { RunImage: "some/run", RunImageMirrors: []string{"some/mirror", "other/mirror"}, }) - h.AssertNil(t, subject.Save(logger)) + h.AssertNil(t, subject.Save(logger, "")) h.AssertEq(t, baseImage.IsSaved(), true) }) @@ -893,7 +894,7 @@ func testBuilder(t *testing.T, when spec.G, it spec.S) { "SOME_KEY": "some-val", "OTHER_KEY": "other-val", }) - h.AssertNil(t, subject.Save(logger)) + h.AssertNil(t, subject.Save(logger, "")) h.AssertEq(t, baseImage.IsSaved(), true) }) diff --git a/pack.go b/pack.go index 29f6e26905..98b59ee254 100644 --- a/pack.go +++ b/pack.go @@ -10,6 +10,11 @@ import ( "github.com/buildpacks/pack/internal/style" ) +var ( + // Version is the version of `pack`. It is injected at compile time. + Version = "0.0.0" +) + func extractPackagedBuildpacks(ctx context.Context, pkgImageRef string, fetcher ImageFetcher, publish, noPull bool) (mainBP dist.Buildpack, depBPs []dist.Buildpack, err error) { pkgImage, err := fetcher.Fetch(ctx, pkgImageRef, !publish, !noPull) if err != nil {