github.com/buildpacks/pack@v0.33.3-0.20240516162812-884dd1837311/pkg/client/new_buildpack.go (about) 1 package client 2 3 import ( 4 "context" 5 "os" 6 "path/filepath" 7 8 "github.com/BurntSushi/toml" 9 10 "github.com/buildpacks/lifecycle/api" 11 12 "github.com/buildpacks/pack/internal/style" 13 "github.com/buildpacks/pack/pkg/dist" 14 ) 15 16 var ( 17 bashBinBuild = `#!/usr/bin/env bash 18 19 set -euo pipefail 20 21 layers_dir="$1" 22 env_dir="$2/env" 23 plan_path="$3" 24 25 exit 0 26 ` 27 bashBinDetect = `#!/usr/bin/env bash 28 29 exit 0 30 ` 31 ) 32 33 type NewBuildpackOptions struct { 34 // api compat version of the output buildpack artifact. 35 API string 36 37 // The base directory to generate assets 38 Path string 39 40 // The ID of the output buildpack artifact. 41 ID string 42 43 // version of the output buildpack artifact. 44 Version string 45 46 // Deprecated: The stacks this buildpack will work with 47 Stacks []dist.Stack 48 49 // the targets this buildpack will work with 50 Targets []dist.Target 51 } 52 53 func (c *Client) NewBuildpack(ctx context.Context, opts NewBuildpackOptions) error { 54 err := createBuildpackTOML(opts.Path, opts.ID, opts.Version, opts.API, opts.Stacks, opts.Targets, c) 55 if err != nil { 56 return err 57 } 58 return createBashBuildpack(opts.Path, c) 59 } 60 61 func createBashBuildpack(path string, c *Client) error { 62 if err := createBinScript(path, "build", bashBinBuild, c); err != nil { 63 return err 64 } 65 66 if err := createBinScript(path, "detect", bashBinDetect, c); err != nil { 67 return err 68 } 69 70 return nil 71 } 72 73 func createBinScript(path, name, contents string, c *Client) error { 74 binDir := filepath.Join(path, "bin") 75 binFile := filepath.Join(binDir, name) 76 77 _, err := os.Stat(binFile) 78 if os.IsNotExist(err) { 79 // The following line's comment is for gosec, it will ignore rule 301 in this case 80 // G301: Expect directory permissions to be 0750 or less 81 /* #nosec G301 */ 82 if err := os.MkdirAll(binDir, 0755); err != nil { 83 return err 84 } 85 // The following line's comment is for gosec, it will ignore rule 306 in this case 86 // G306: Expect WriteFile permissions to be 0600 or less 87 /* #nosec G306 */ 88 err = os.WriteFile(binFile, []byte(contents), 0755) 89 if err != nil { 90 return err 91 } 92 93 if c != nil { 94 c.logger.Infof(" %s bin/%s", style.Symbol("create"), name) 95 } 96 } 97 return nil 98 } 99 100 func createBuildpackTOML(path, id, version, apiStr string, stacks []dist.Stack, targets []dist.Target, c *Client) error { 101 api, err := api.NewVersion(apiStr) 102 if err != nil { 103 return err 104 } 105 106 buildpackTOML := dist.BuildpackDescriptor{ 107 WithAPI: api, 108 WithStacks: stacks, 109 WithTargets: targets, 110 WithInfo: dist.ModuleInfo{ 111 ID: id, 112 Version: version, 113 }, 114 } 115 116 // The following line's comment is for gosec, it will ignore rule 301 in this case 117 // G301: Expect directory permissions to be 0750 or less 118 /* #nosec G301 */ 119 if err := os.MkdirAll(path, 0755); err != nil { 120 return err 121 } 122 123 buildpackTOMLPath := filepath.Join(path, "buildpack.toml") 124 _, err = os.Stat(buildpackTOMLPath) 125 if os.IsNotExist(err) { 126 f, err := os.Create(buildpackTOMLPath) 127 if err != nil { 128 return err 129 } 130 if err := toml.NewEncoder(f).Encode(buildpackTOML); err != nil { 131 return err 132 } 133 defer f.Close() 134 if c != nil { 135 c.logger.Infof(" %s buildpack.toml", style.Symbol("create")) 136 } 137 } 138 139 return nil 140 }