package github import ( "context" "encoding/json" "errors" "fmt" "io" "net/http" "strings" "github.com/databricks/cli/libs/log" ) const gitHubAPI = "https://api.github.com" const gitHubUserContent = "https://raw.githubusercontent.com" // Placeholders to use as unique keys in context.Context. var apiOverride int var userContentOverride int func WithApiOverride(ctx context.Context, override string) context.Context { return context.WithValue(ctx, &apiOverride, override) } func WithUserContentOverride(ctx context.Context, override string) context.Context { return context.WithValue(ctx, &userContentOverride, override) } var ErrNotFound = errors.New("not found") func getBytes(ctx context.Context, method, url string, body io.Reader) ([]byte, error) { ao, ok := ctx.Value(&apiOverride).(string) if ok { url = strings.Replace(url, gitHubAPI, ao, 1) } uco, ok := ctx.Value(&userContentOverride).(string) if ok { url = strings.Replace(url, gitHubUserContent, uco, 1) } log.Tracef(ctx, "%s %s", method, url) req, err := http.NewRequestWithContext(ctx, "GET", url, body) if err != nil { return nil, err } res, err := http.DefaultClient.Do(req) if err != nil { return nil, err } if res.StatusCode == 404 { return nil, ErrNotFound } if res.StatusCode >= 400 { return nil, fmt.Errorf("github request failed: %s", res.Status) } defer res.Body.Close() return io.ReadAll(res.Body) } func httpGetAndUnmarshal(ctx context.Context, url string, response any) error { raw, err := getBytes(ctx, "GET", url, nil) if err != nil { return err } return json.Unmarshal(raw, response) }