tests/thirdparty: package metadata (#223)
Fetches third-party package metadata from Github.
This commit is contained in:
committed by
GitHub
parent
afe2d539b8
commit
f355d27b13
107
internal/github/client.go
Normal file
107
internal/github/client.go
Normal file
@@ -0,0 +1,107 @@
|
||||
// Package github provides a client for the Github REST API.
|
||||
package github
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Client for the Github REST API.
|
||||
type Client struct {
|
||||
client *http.Client
|
||||
base string
|
||||
token string
|
||||
}
|
||||
|
||||
// Option configures a Github client.
|
||||
type Option func(*Client)
|
||||
|
||||
// WithHTTPClient configures the HTTP client that should be used for Github API
|
||||
// requests.
|
||||
func WithHTTPClient(h *http.Client) Option {
|
||||
return func(c *Client) { c.client = h }
|
||||
}
|
||||
|
||||
// WithToken configures a Client with an authentication token for Github API
|
||||
// requests.
|
||||
func WithToken(token string) Option {
|
||||
return func(c *Client) { c.token = token }
|
||||
}
|
||||
|
||||
// WithTokenFromEnvironment configures a Client using the GITHUB_TOKEN
|
||||
// environment variable.
|
||||
func WithTokenFromEnvironment() Option {
|
||||
return WithToken(os.Getenv("GITHUB_TOKEN"))
|
||||
}
|
||||
|
||||
// NewClient initializes a client using the given HTTP client.
|
||||
func NewClient(opts ...Option) *Client {
|
||||
c := &Client{
|
||||
client: http.DefaultClient,
|
||||
base: "https://api.github.com",
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(c)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// Repository gets information about the given Github repository.
|
||||
func (c *Client) Repository(ctx context.Context, owner, name string) (*Repository, error) {
|
||||
// Build request.
|
||||
u := c.base + "/repos/" + owner + "/" + name
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Execute.
|
||||
repo := &Repository{}
|
||||
if err := c.request(req, repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
func (c *Client) request(req *http.Request, payload interface{}) (err error) {
|
||||
// Add common headers.
|
||||
if c.token != "" {
|
||||
req.Header.Set("Authorization", "Bearer "+c.token)
|
||||
}
|
||||
req.Header.Set("Accept", "application/vnd.github.v3+json")
|
||||
|
||||
// Execute the request.
|
||||
res, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if errc := res.Body.Close(); errc != nil && err == nil {
|
||||
err = errc
|
||||
}
|
||||
}()
|
||||
|
||||
// Check status.
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("http status %d: %s", res.StatusCode, http.StatusText(res.StatusCode))
|
||||
}
|
||||
|
||||
// Parse response body.
|
||||
d := json.NewDecoder(res.Body)
|
||||
|
||||
if err := d.Decode(payload); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Should not have trailing data.
|
||||
if d.More() {
|
||||
return errors.New("unexpected extra data after JSON")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user