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  }