github.com/buildpacks/pack@v0.33.3-0.20240516162812-884dd1837311/pkg/client/register_buildpack.go (about) 1 package client 2 3 import ( 4 "context" 5 "errors" 6 "net/url" 7 "runtime" 8 "strings" 9 10 "github.com/buildpacks/pack/internal/registry" 11 "github.com/buildpacks/pack/pkg/buildpack" 12 "github.com/buildpacks/pack/pkg/dist" 13 "github.com/buildpacks/pack/pkg/image" 14 ) 15 16 // RegisterBuildpackOptions is a configuration struct that controls the 17 // behavior of the RegisterBuildpack function. 18 type RegisterBuildpackOptions struct { 19 ImageName string 20 Type string 21 URL string 22 Name string 23 } 24 25 // RegisterBuildpack updates the Buildpack Registry with to include a new buildpack specified in 26 // the opts argument 27 func (c *Client) RegisterBuildpack(ctx context.Context, opts RegisterBuildpackOptions) error { 28 appImage, err := c.imageFetcher.Fetch(ctx, opts.ImageName, image.FetchOptions{Daemon: false, PullPolicy: image.PullAlways}) 29 if err != nil { 30 return err 31 } 32 33 var buildpackInfo dist.ModuleInfo 34 if _, err := dist.GetLabel(appImage, buildpack.MetadataLabel, &buildpackInfo); err != nil { 35 return err 36 } 37 38 namespace, name, err := parseID(buildpackInfo.ID) 39 if err != nil { 40 return err 41 } 42 43 id, err := appImage.Identifier() 44 if err != nil { 45 return err 46 } 47 48 buildpack := registry.Buildpack{ 49 Namespace: namespace, 50 Name: name, 51 Version: buildpackInfo.Version, 52 Address: id.String(), 53 Yanked: false, 54 } 55 56 if opts.Type == "github" { 57 issueURL, err := registry.GetIssueURL(opts.URL) 58 if err != nil { 59 return err 60 } 61 62 issue, err := registry.CreateGithubIssue(buildpack) 63 if err != nil { 64 return err 65 } 66 67 params := url.Values{} 68 params.Add("title", issue.Title) 69 params.Add("body", issue.Body) 70 issueURL.RawQuery = params.Encode() 71 72 c.logger.Debugf("Open URL in browser: %s", issueURL) 73 cmd, err := registry.CreateBrowserCmd(issueURL.String(), runtime.GOOS) 74 if err != nil { 75 return err 76 } 77 78 return cmd.Start() 79 } else if opts.Type == "git" { 80 registryCache, err := getRegistry(c.logger, opts.Name) 81 if err != nil { 82 return err 83 } 84 85 username, err := parseUsernameFromURL(opts.URL) 86 if err != nil { 87 return err 88 } 89 90 if err := registry.GitCommit(buildpack, username, registryCache); err != nil { 91 return err 92 } 93 } 94 95 return nil 96 } 97 98 func parseUsernameFromURL(url string) (string, error) { 99 parts := strings.Split(url, "/") 100 if len(parts) < 3 { 101 return "", errors.New("invalid url: cannot parse username from url") 102 } 103 if parts[3] == "" { 104 return "", errors.New("invalid url: username is empty") 105 } 106 107 return parts[3], nil 108 } 109 110 func parseID(id string) (string, string, error) { 111 parts := strings.Split(id, "/") 112 if len(parts) < 2 { 113 return "", "", errors.New("invalid id: does not contain a namespace") 114 } else if len(parts) > 2 { 115 return "", "", errors.New("invalid id: contains unexpected characters") 116 } 117 118 return parts[0], parts[1], nil 119 }