Documentation
¶
Overview ¶
Package github is a minimal GitHub REST client: in-app authentication (OAuth device flow, PAT validation) and typed search/notification calls.
Nothing in this repository imports it — it exists for the hive-desktop app (hay-kot/hive-desktop), which vendors hive's internal packages at a pinned commit. Keep it building and tested here; removing it would break the desktop's vendor sync.
Index ¶
- Constants
- Variables
- type Client
- func (c *Client) GetIssue(ctx context.Context, owner, repo string, number int) (Issue, error)
- func (c *Client) GetPullRequest(ctx context.Context, owner, repo string, number int) (Issue, error)
- func (c *Client) Notifications(ctx context.Context, limit int, ifModifiedSince string) (NotificationsResult, error)
- func (c *Client) PollDeviceFlow(ctx context.Context, clientID string, auth DeviceAuth) (string, error)
- func (c *Client) SearchIssuesBatch(ctx context.Context, reqs []SearchRequest) ([][]SearchItem, error)
- func (c *Client) StartDeviceFlow(ctx context.Context, clientID string, scopes []string) (DeviceAuth, error)
- func (c *Client) User(ctx context.Context) (User, error)
- func (c *Client) WithTokenCopy(token string) *Client
- type DeviceAuth
- type Issue
- type KeychainStore
- type Label
- type MemoryTokenStore
- type Notification
- type NotificationSubject
- type NotificationsResult
- type Option
- type RateLimitError
- type Repository
- type SearchItem
- type SearchRequest
- type TokenStore
- type User
Constants ¶
const EnvToken = "HIVE_GITHUB_TOKEN"
EnvToken is the environment override for the GitHub token. It takes precedence over the keychain so headless environments (CI, server builds) never need keychain access.
Variables ¶
var ( ErrRateLimited = errors.New("github: rate limited") ErrUnreachable = errors.New("github: unreachable") )
Sentinel errors form the taxonomy the UI maps onto design states (unauthorized -> re-auth, rate limited / unreachable -> "GitHub unreachable").
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a GitHub REST v3 client. The zero value is not usable; construct with NewClient.
func (*Client) GetPullRequest ¶ added in v0.58.0
GetPullRequest fetches and normalizes one GitHub pull request.
func (*Client) Notifications ¶
func (c *Client) Notifications(ctx context.Context, limit int, ifModifiedSince string) (NotificationsResult, error)
Notifications lists the user's notification inbox, including read threads, so the app can mirror the full inbox and keep triage state locally. A non-empty ifModifiedSince makes the request conditional: authenticated 304 responses are free of rate-limit cost, so polling an unchanged inbox costs nothing.
func (*Client) PollDeviceFlow ¶
func (c *Client) PollDeviceFlow(ctx context.Context, clientID string, auth DeviceAuth) (string, error)
PollDeviceFlow polls the token endpoint until the user authorizes the device, the code expires, or ctx is canceled. It blocks; run it in a goroutine and honor ctx for cancellation.
func (*Client) SearchIssuesBatch ¶ added in v0.58.0
func (c *Client) SearchIssuesBatch(ctx context.Context, reqs []SearchRequest) ([][]SearchItem, error)
SearchIssuesBatch runs every request as an aliased search field of a single GraphQL query, newest-updated first. Results map back to requests by index: out[i] answers reqs[i]. Query text is passed via GraphQL variables ($q0, $q1, ...), never interpolated.
func (*Client) StartDeviceFlow ¶
func (c *Client) StartDeviceFlow(ctx context.Context, clientID string, scopes []string) (DeviceAuth, error)
StartDeviceFlow requests a device + user code pair for the OAuth device flow. clientID is the public OAuth app client ID.
func (*Client) User ¶
User returns the authenticated user. It doubles as token validation: ErrUnauthorized means the token is missing, revoked, or expired.
func (*Client) WithTokenCopy ¶
WithTokenCopy returns a copy of the client using the given token.
type DeviceAuth ¶
type DeviceAuth struct {
DeviceCode string `json:"device_code"`
UserCode string `json:"user_code"`
VerificationURI string `json:"verification_uri"`
ExpiresIn int `json:"expires_in"`
Interval int `json:"interval"`
}
DeviceAuth is the pending device authorization the UI presents: the user opens VerificationURI and enters UserCode.
type Issue ¶ added in v0.58.0
Issue is a hydrated single issue or pull request. State is normalized to open/closed; Merged is meaningful only for pull requests.
type KeychainStore ¶
type KeychainStore struct{}
KeychainStore stores the token in the OS keychain, with the EnvToken environment variable as a read-only override.
func NewKeychainStore ¶
func NewKeychainStore() *KeychainStore
func (*KeychainStore) DeleteToken ¶
func (s *KeychainStore) DeleteToken() error
func (*KeychainStore) SetToken ¶
func (s *KeychainStore) SetToken(token string) error
func (*KeychainStore) Token ¶
func (s *KeychainStore) Token() (string, error)
type MemoryTokenStore ¶
type MemoryTokenStore struct {
// contains filtered or unexported fields
}
MemoryTokenStore is an in-memory TokenStore for tests and mock mode.
func NewMemoryTokenStore ¶
func NewMemoryTokenStore(token string) *MemoryTokenStore
func (*MemoryTokenStore) DeleteToken ¶
func (s *MemoryTokenStore) DeleteToken() error
func (*MemoryTokenStore) SetToken ¶
func (s *MemoryTokenStore) SetToken(token string) error
func (*MemoryTokenStore) Token ¶
func (s *MemoryTokenStore) Token() (string, error)
type Notification ¶
type Notification struct {
ID string `json:"id"`
Unread bool `json:"unread"`
Reason string `json:"reason"`
UpdatedAt time.Time `json:"updated_at"`
Subject NotificationSubject `json:"subject"`
Repository Repository `json:"repository"`
}
Notification is one thread from the notifications inbox.
type NotificationSubject ¶
type NotificationSubject struct {
Title string `json:"title"`
URL string `json:"url"`
Type string `json:"type"` // "Issue" | "PullRequest" | "Release" | ...
}
NotificationSubject describes what a notification thread is about.
func (NotificationSubject) Number ¶
func (s NotificationSubject) Number() int
Number parses the issue/PR number from the subject API URL. Returns 0 for subjects without one (releases, discussions).
type NotificationsResult ¶
type NotificationsResult struct {
Items []Notification
NotModified bool
LastModified string
PollInterval int
}
NotificationsResult is one notifications poll. When NotModified is true the inbox has not changed since the ifModifiedSince timestamp and Items is nil — the caller keeps its cached copy. LastModified echoes the response's Last-Modified header for the next conditional request, and PollInterval is the server-mandated minimum seconds between polls (X-Poll-Interval, 0 when the header is absent).
type Option ¶
type Option func(*Client)
func WithAPIBase ¶
WithAPIBase overrides the REST API base URL (tests).
func WithAuthBase ¶
WithAuthBase overrides the OAuth base URL used by the device flow (tests).
func WithHTTPClient ¶
WithHTTPClient overrides the underlying HTTP client.
type RateLimitError ¶ added in v0.58.0
type RateLimitError struct {
// ResetAt is when the limit resets. It is zero when the server supplied
// neither Retry-After nor X-RateLimit-Reset.
ResetAt time.Time
}
RateLimitError is a rate-limit response carrying the server-provided retry time. It unwraps to ErrRateLimited so errors.Is-based handling keeps working; callers that can honor the wait can inspect ResetAt with errors.As.
func (*RateLimitError) Error ¶ added in v0.58.0
func (e *RateLimitError) Error() string
func (*RateLimitError) Unwrap ¶ added in v0.58.0
func (e *RateLimitError) Unwrap() error
type Repository ¶
type Repository struct {
FullName string `json:"full_name"`
}
Repository identifies the repository a notification belongs to.
type SearchItem ¶
type SearchItem struct {
Number int
Title string
Body string
State string
URL string // html URL
Repo string // "owner/name" (repository.nameWithOwner)
Author string // author.login; "" for deleted (ghost) users
Labels []Label
IsPullRequest bool // __typename == "PullRequest"
Draft bool // isDraft; always false for issues
CreatedAt time.Time
UpdatedAt time.Time
}
SearchItem is one issue or pull request from the batched GraphQL search.
type SearchRequest ¶ added in v0.58.0
type SearchRequest struct {
Query string // GitHub search syntax; "sort:updated-desc" is appended by the client
Limit int // max items for this search (GraphQL `first`)
}
SearchRequest is one search in a batched GraphQL issue/PR search.