github.com/buildpacks/pack@v0.33.3-0.20240516162812-884dd1837311/internal/commands/buildpack_new.go (about) 1 package commands 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "path/filepath" 8 "runtime" 9 "strings" 10 11 "github.com/spf13/cobra" 12 13 "github.com/buildpacks/pack/internal/style" 14 "github.com/buildpacks/pack/internal/target" 15 "github.com/buildpacks/pack/pkg/client" 16 "github.com/buildpacks/pack/pkg/dist" 17 "github.com/buildpacks/pack/pkg/logging" 18 ) 19 20 // BuildpackNewFlags define flags provided to the BuildpackNew command 21 type BuildpackNewFlags struct { 22 API string 23 Path string 24 // Deprecated: Stacks are deprecated 25 Stacks []string 26 Targets []string 27 Version string 28 } 29 30 // BuildpackCreator creates buildpacks 31 type BuildpackCreator interface { 32 NewBuildpack(ctx context.Context, options client.NewBuildpackOptions) error 33 } 34 35 // BuildpackNew generates the scaffolding of a buildpack 36 func BuildpackNew(logger logging.Logger, creator BuildpackCreator) *cobra.Command { 37 var flags BuildpackNewFlags 38 cmd := &cobra.Command{ 39 Use: "new <id>", 40 Short: "Creates basic scaffolding of a buildpack.", 41 Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), 42 Example: "pack buildpack new sample/my-buildpack", 43 Long: "buildpack new generates the basic scaffolding of a buildpack repository. It creates a new directory `name` in the current directory (or at `path`, if passed as a flag), and initializes a buildpack.toml, and two executable bash scripts, `bin/detect` and `bin/build`. ", 44 RunE: logError(logger, func(cmd *cobra.Command, args []string) error { 45 id := args[0] 46 idParts := strings.Split(id, "/") 47 dirName := idParts[len(idParts)-1] 48 49 var path string 50 if len(flags.Path) == 0 { 51 cwd, err := os.Getwd() 52 if err != nil { 53 return err 54 } 55 path = filepath.Join(cwd, dirName) 56 } else { 57 path = flags.Path 58 } 59 60 _, err := os.Stat(path) 61 if !os.IsNotExist(err) { 62 return fmt.Errorf("directory %s exists", style.Symbol(path)) 63 } 64 65 var stacks []dist.Stack 66 for _, s := range flags.Stacks { 67 stacks = append(stacks, dist.Stack{ 68 ID: s, 69 Mixins: []string{}, 70 }) 71 } 72 73 var targets []dist.Target 74 if len(flags.Targets) == 0 && len(flags.Stacks) == 0 { 75 targets = []dist.Target{{ 76 OS: runtime.GOOS, 77 Arch: runtime.GOARCH, 78 }} 79 } else { 80 if targets, err = target.ParseTargets(flags.Targets, logger); err != nil { 81 return err 82 } 83 } 84 85 if err := creator.NewBuildpack(cmd.Context(), client.NewBuildpackOptions{ 86 API: flags.API, 87 ID: id, 88 Path: path, 89 Stacks: stacks, 90 Targets: targets, 91 Version: flags.Version, 92 }); err != nil { 93 return err 94 } 95 96 logger.Infof("Successfully created %s", style.Symbol(id)) 97 return nil 98 }), 99 } 100 101 cmd.Flags().StringVarP(&flags.API, "api", "a", "0.8", "Buildpack API compatibility of the generated buildpack") 102 cmd.Flags().StringVarP(&flags.Path, "path", "p", "", "Path to generate the buildpack") 103 cmd.Flags().StringVarP(&flags.Version, "version", "V", "1.0.0", "Version of the generated buildpack") 104 cmd.Flags().StringSliceVarP(&flags.Stacks, "stacks", "s", nil, "Stack(s) this buildpack will be compatible with"+stringSliceHelp("stack")) 105 cmd.Flags().MarkDeprecated("stacks", "prefer `--targets` instead: https://github.com/buildpacks/rfcs/blob/main/text/0096-remove-stacks-mixins.md") 106 cmd.Flags().StringSliceVarP(&flags.Targets, "targets", "t", nil, 107 `Targets are the list platforms that one targeting, these are generated as part of scaffolding inside buildpack.toml file. one can provide target platforms in format [os][/arch][/variant]:[distroname@osversion@anotherversion];[distroname@osversion] 108 - Base case for two different architectures : '--targets "linux/amd64" --targets "linux/arm64"' 109 - case for distribution version: '--targets "windows/amd64:windows-nano@10.0.19041.1415"' 110 - case for different architecture with distributed versions : '--targets "linux/arm/v6:ubuntu@14.04" --targets "linux/arm/v6:ubuntu@16.04"' 111 `) 112 113 AddHelpFlag(cmd, "new") 114 return cmd 115 }