Documentation
¶
Index ¶
- Constants
- Variables
- func CheckGHAuth() error
- func CheckoutBranch(repoPath, branchName string) error
- func CleanupClone(owner, repo string) error
- func CloneRepository(owner, repo, targetPath string) error
- func ClosePR(owner, repo string, prNumber int) error
- func DeleteKeychainToken() error
- func DeleteKeychainTokenForAccount(host, username string) error
- func EnsureCloneDirectory() error
- func FetchBranch(repoPath, branchName string) error
- func FindExistingClone(owner, repo string) (string, bool)
- func GeneratePRPrompt(pr *PRInfo, includeDescription bool) string
- func GetCLIToken(ctx context.Context, host string) (string, error)
- func GetClonePath(owner, repo string) string
- func GetCurrentUserLogin(ctx context.Context) (string, error)
- func GetCurrentUserLoginWithToken(ctx context.Context, host, token string) (string, error)
- func GetKeychainToken() string
- func GetKeychainTokenForAccount(host, username string) string
- func GetKeychainTokenForHost(host string) string
- func GetPRDiff(owner, repo string, prNumber int) (string, error)
- func GetRemoteURL(repoPath string) (string, error)
- func IsForkRepo(ctx context.Context, owner, repo string) (bool, error)
- func IsGitHubCom(host string) bool
- func IsGitHubRef(input string) bool
- func IsGitHubRefWithHosts(input string, enterpriseHosts []string) bool
- func IsTerminal(priority PRPriority) bool
- func ListClonedRepos() ([]string, error)
- func MergePR(owner, repo string, prNumber int, method string) error
- func NormalizeHost(host string) string
- func PollDeviceAuth(ctx context.Context, host, clientIDOverride, deviceCode string) (string, error)
- func PostPRComment(owner, repo string, prNumber int, body string) error
- func RestBaseURLForHost(host string) string
- func SetKeychainToken(token string) error
- func SetKeychainTokenForAccount(host, username, token string) error
- func StoreTokenForDiscoveredUser(ctx context.Context, host, token string) error
- func WaitForDeviceAuth(ctx context.Context, host, clientIDOverride string, da *DeviceAuthStart) (string, error)
- type AccountRef
- type AccountToken
- type CLIHost
- type CachedAccount
- type CloneOptions
- type CloneResult
- type CommitResult
- type DeviceAuthStart
- type ETagCache
- type IssueResult
- type PRAnnotationSession
- type PRAnnotationWorktree
- type PRComment
- type PRInfo
- func GetPRByNumber(ctx context.Context, owner, repo string, prNumber int) (*PRInfo, error)
- func GetPRForBranch(ctx context.Context, owner, repo, branch string) (*PRInfo, error)
- func GetPRForBranchConditional(ctx context.Context, owner, repo, branch, etag string) (info *PRInfo, newEtag string, changed bool, err error)
- func GetPRInfo(owner, repo string, prNumber int) (*PRInfo, error)
- func GetPRInfoConditional(ctx context.Context, owner, repo string, prNumber int, cache *ETagCache) (*PRInfo, bool, error)
- func GetPRInfoCtx(ctx context.Context, owner, repo string, prNumber int) (*PRInfo, error)
- type PRPriority
- type PRResult
- type ParsedGitHubRef
- type RateLimiter
- type RefType
- type RepoRef
- type RepoResult
- type UserPR
- type UserPRCache
- func (c *UserPRCache) Annotate(sessions []PRAnnotationSession, worktrees []PRAnnotationWorktree)
- func (c *UserPRCache) GetAll() []UserPR
- func (c *UserPRCache) GetCachedAccounts() []CachedAccount
- func (c *UserPRCache) GetCachedLogin() string
- func (c *UserPRCache) GetCachedLogins() []string
- func (c *UserPRCache) InvalidateLoginCache()
- func (c *UserPRCache) Refresh(ctx context.Context) error
- func (c *UserPRCache) SetOnUpdated(fn func(prs []UserPR))
- func (c *UserPRCache) Start(ctx context.Context)
- func (c *UserPRCache) Stop()
- func (c *UserPRCache) Subscribe(id string, ch chan []UserPR)
- func (c *UserPRCache) Unsubscribe(id string)
- type UserPRCacheConfig
Constants ¶
const ( PRStateOpen = "open" PRStateClosed = "closed" PRStateMerged = "merged" )
PR state strings. These are the single source of truth for the three PR lifecycle states surfaced by PRInfo.State — GetPRByNumber and any other consumer of PRInfo.State should compare against these constants rather than hardcoding "open"/"closed"/"merged" string literals.
const (
// DefaultCloneBase is the default base directory for cloned repositories
DefaultCloneBase = "~/.stapler-squad/repos"
)
Variables ¶
var DefaultRateLimiter = &RateLimiter{}
DefaultRateLimiter is the shared GitHub API rate limiter used by all native HTTP calls. It is updated automatically by rateLimitTransport on every response; pollers check IsLimited() before dispatching work.
var EnterpriseBaseURLOverride = map[string]string{}
EnterpriseBaseURLOverride lets tests redirect a specific enterprise host's API traffic (both REST and GraphQL) to an httptest.Server, mirroring the GhBaseURL seam for github.com. Keyed by normalized host, value is the server root including a trailing slash; empty/absent falls back to the real GHES API paths. RestBaseURLForHost and graphQLURLForHost must both consult this map — if only one does, tests that set it get a false sense of isolation while the other call type still dials the real host.
var ErrAuthorizationPending = errors.New("authorization_pending")
ErrAuthorizationPending is returned by PollDeviceAuth while waiting for the user to complete the browser authorization step.
var ErrDeviceFlowExpired = errors.New("expired_token")
ErrDeviceFlowExpired is returned when the device code has expired before the user authorized. The caller should restart the flow.
var ErrGitHubAccessDenied = errors.New("github: access denied")
ErrGitHubAccessDenied is 401, or 403 with no rate-limit signal — retrying with the same credentials will not change the outcome.
var ErrGitHubRefNotFound = errors.New("github: reference not found")
ErrGitHubRefNotFound is a definitive 404: the referenced PR/issue/commit doesn't exist, or exists but is invisible to the configured token (GitHub disguises "exists, no access" as "not found" for security).
var ErrNoPR = errors.New("no pull request found for branch")
ErrNoPR is returned by GetPRForBranch when no pull request exists for the branch.
var ErrNotAuthenticated = errors.New("github token not configured")
ErrNotAuthenticated is returned by SearchUserRepos and ListRepoIssues when no GitHub token is configured (GITHUB_TOKEN, GH_TOKEN, or OS keychain).
var GhBaseURL = "https://api.github.com/"
GhBaseURL is the GitHub REST API base URL. Tests override this to point at an httptest.Server so requests never reach the real API.
Functions ¶
func CheckGHAuth ¶
func CheckGHAuth() error
CheckGHAuth verifies GitHub authentication via GET /user using the native HTTP client. No subprocess is invoked — avoids forkExec lock contention. Results are cached for 5 minutes. Concurrent callers share a single inflight call via singleflight.
func CheckoutBranch ¶
CheckoutBranch checks out a branch in an existing repository
func CleanupClone ¶
CleanupClone removes a cloned repository Use with caution - this deletes the entire repository directory
func CloneRepository ¶
CloneRepository clones a GitHub repository
func DeleteKeychainToken ¶ added in v1.35.0
func DeleteKeychainToken() error
DeleteKeychainToken removes the legacy single-account token.
func DeleteKeychainTokenForAccount ¶ added in v1.35.0
DeleteKeychainTokenForAccount removes the token for username on host and removes it from the accounts list.
func EnsureCloneDirectory ¶
func EnsureCloneDirectory() error
EnsureCloneDirectory ensures the base clone directory exists
func FetchBranch ¶
FetchBranch fetches a specific branch in an existing repository
func FindExistingClone ¶
FindExistingClone checks if a repository is already cloned Returns the path and true if found, empty string and false otherwise
func GeneratePRPrompt ¶
GeneratePRPrompt generates a context prompt from PR information This can be used to initialize a Claude Code session with PR context
func GetCLIToken ¶ added in v1.41.0
GetCLIToken shells out to `gh auth token --hostname <host>` to retrieve the token gh has stored (keyring or hosts.yml) for host. Requires the gh CLI to be installed and already authenticated to that host.
func GetClonePath ¶
GetClonePath returns the path where a repository would be cloned Format: ~/.stapler-squad/repos/{owner}/{repo}
func GetCurrentUserLogin ¶ added in v1.35.0
GetCurrentUserLogin returns the GitHub login of the authenticated user via GET /user. Returns an empty string (not an error) when unauthenticated so callers can degrade gracefully.
func GetCurrentUserLoginWithToken ¶ added in v1.35.0
GetCurrentUserLoginWithToken fetches the GitHub login for an explicit token on host ("" means github.com). Returns ("", nil) when the token is invalid or unauthenticated.
func GetKeychainToken ¶ added in v1.35.0
func GetKeychainToken() string
GetKeychainToken returns any stored GitHub token (first account, or the legacy single-account slot). Kept for backward-compatibility with the single-token auth flow.
func GetKeychainTokenForAccount ¶ added in v1.35.0
GetKeychainTokenForAccount returns the stored token for username on host, or "".
func GetKeychainTokenForHost ¶ added in v1.41.0
GetKeychainTokenForHost returns any stored token for host, regardless of which account it belongs to. Backlog sync plugins (session/backlog_plugin_github.go, session/backlog_plugin_github_prs.go) only know a host, not a username, so they can't call GetKeychainTokenForAccount directly. Falls back to the legacy single-account slot for github.com when no named account matches.
func GetRemoteURL ¶
GetRemoteURL returns the remote URL of a repository (used to determine owner/repo)
func IsForkRepo ¶ added in v1.12.0
IsForkRepo reports whether the given repo is a fork of another repository.
func IsGitHubCom ¶ added in v1.41.0
IsGitHubCom reports whether host (after normalization) is github.com.
func IsGitHubRef ¶
IsGitHubRef checks if the input string looks like a GitHub URL or reference This is a quick check that doesn't validate the full format
func IsGitHubRefWithHosts ¶ added in v1.41.0
IsGitHubRefWithHosts is the host-aware variant of IsGitHubRef, additionally recognizing URLs against any of the supplied enterpriseHosts.
func IsTerminal ¶ added in v1.12.0
func IsTerminal(priority PRPriority) bool
IsTerminal returns true if the priority indicates a terminal PR state. Terminal sessions should not be polled at normal frequency.
func ListClonedRepos ¶
ListClonedRepos returns a list of all cloned repositories
func NormalizeHost ¶ added in v1.41.0
NormalizeHost returns the canonical form of a GitHub host: lowercased, no scheme, no trailing slash, and "" mapped to github.com. Hostnames are case-insensitive (DNS), and GHE hosts are free-text admin/user input, so lowercasing here keeps registration and URL-match comparisons consistent regardless of how a host was typed.
func PollDeviceAuth ¶ added in v1.35.0
PollDeviceAuth polls GitHub's token endpoint once.
- Returns (token, nil) on success — the caller should store the token.
- Returns ("", ErrAuthorizationPending) if the user hasn't approved yet.
- Returns ("", ErrDeviceFlowExpired) if the device code has expired.
- Returns ("", err) for any other error.
func PostPRComment ¶
PostPRComment posts a comment on a pull request
func RestBaseURLForHost ¶ added in v1.41.0
RestBaseURLForHost returns the REST API base URL for host, including a trailing slash. For github.com this returns the existing GhBaseURL package var unchanged, preserving the test seam that overrides it directly.
func SetKeychainToken ¶ added in v1.35.0
SetKeychainToken stores a token under the legacy single-account slot. Prefer SetKeychainTokenForAccount when the username is known.
func SetKeychainTokenForAccount ¶ added in v1.35.0
SetKeychainTokenForAccount stores a token under a per-account key and adds the account to the accounts list if not already present.
func StoreTokenForDiscoveredUser ¶ added in v1.35.0
StoreTokenForDiscoveredUser fetches the GitHub login for token on host and stores it under the per-account keychain slot. Falls back to the legacy slot (github.com only) if the login cannot be determined.
func WaitForDeviceAuth ¶ added in v1.35.0
func WaitForDeviceAuth(ctx context.Context, host, clientIDOverride string, da *DeviceAuthStart) (string, error)
WaitForDeviceAuth polls GitHub repeatedly until the user completes authorization, the code expires, or ctx is cancelled. On success it stores the token in the OS keychain and returns it.
Types ¶
type AccountRef ¶ added in v1.41.0
AccountRef identifies one connected GitHub account by username and host.
func ListKeychainAccounts ¶ added in v1.35.0
func ListKeychainAccounts() []AccountRef
ListKeychainAccounts returns the ordered list of connected GitHub accounts. The stored shape is normally []AccountRef; a legacy []string of usernames (from before per-host support) is transparently read as github.com accounts.
type AccountToken ¶ added in v1.35.0
type AccountToken struct {
Username string // empty for the legacy single-account slot
Host string
Token string
}
AccountToken pairs a GitHub username and host with its token.
func GetAllKeychainTokens ¶ added in v1.35.0
func GetAllKeychainTokens() []AccountToken
GetAllKeychainTokens returns all stored tokens across all named accounts plus the legacy single-account slot. Each entry is a (username, host, token) tuple.
type CLIHost ¶ added in v1.41.0
CLIHost describes a GitHub host the `gh` CLI is already authenticated to.
func ListCLIHosts ¶ added in v1.41.0
ListCLIHosts reads gh CLI's hosts.yml to discover which GitHub hosts the user has already run `gh auth login` against. It only reads the host and associated username — safe to display in the UI — never a token: gh 2.x stores tokens in the OS keyring, not in this file, so retrieving the actual token still requires GetCLIToken. Returns an empty slice (not an error) when gh has never been configured on this machine.
type CachedAccount ¶ added in v1.41.0
CachedAccount is a resolved (login, host) pair for the accounts list RPC.
type CloneOptions ¶
type CloneOptions struct {
Host string // GitHub host, e.g. "github.com" or a GHES hostname; "" means github.com
Owner string
Repo string
Branch string // Optional: specific branch to checkout after cloning
Shallow bool // Use shallow clone (--depth=1) for faster cloning
}
CloneOptions specifies options for cloning or accessing a repository
type CloneResult ¶
type CloneResult struct {
Path string // Full path to the repository
WasCloned bool // True if we just cloned it, false if it already existed
Branch string // Current branch name
}
CloneResult contains information about a cloned or existing repository
func GetOrCloneRepository ¶
func GetOrCloneRepository(opts CloneOptions) (*CloneResult, error)
GetOrCloneRepository ensures a repository is available locally It will clone it if not already present, or return the existing clone
type CommitResult ¶ added in v1.41.0
CommitResult is the domain return type for GetCommit.
func GetCommit ¶ added in v1.41.0
func GetCommit(ctx context.Context, owner, repo, sha string) (*CommitResult, error)
GetCommit fetches a single commit by SHA via the GitHub REST API (native net/http, same auth/error-classification mechanism as GetIssue/GetPR). Returns ErrNotAuthenticated when no token is configured.
type DeviceAuthStart ¶ added in v1.35.0
type DeviceAuthStart struct {
DeviceCode string
UserCode string
VerificationURI string
// ExpiresIn is how long the code is valid (seconds).
ExpiresIn int
// Interval is the minimum poll interval suggested by GitHub (seconds).
Interval int
}
DeviceAuthStart holds the values returned by the first step of the Device Flow: the user-visible code and the URL where they enter it.
func StartDeviceAuth ¶ added in v1.35.0
func StartDeviceAuth(ctx context.Context, host, clientIDOverride string) (*DeviceAuthStart, error)
StartDeviceAuth initiates the GitHub Device Flow against host and returns the codes the user must enter at verification_uri. clientID is the OAuth App client ID to use; pass "" for github.com to use the default/env-configured one. The returned DeviceAuthStart.DeviceCode must be passed to PollDeviceAuth.
type ETagCache ¶ added in v1.12.0
type ETagCache struct {
// contains filtered or unexported fields
}
ETagCache stores ETags and cached PRInfo responses per (owner, repo, prNumber). Using conditional requests (If-None-Match) allows GitHub to return 304 Not Modified responses that cost zero rate-limit quota when the PR has not changed. sync.Map gives lock-free reads in the steady state — entries are written once on first PR discovery and then read on every subsequent poll tick.
func NewETagCache ¶ added in v1.12.0
func NewETagCache() *ETagCache
NewETagCache creates a new empty ETagCache.
type IssueResult ¶ added in v1.35.0
type IssueResult struct {
Number int
Title string
Body string
Author string
State string
URL string
Labels []string
CreatedAt time.Time
UpdatedAt time.Time
IsPR bool
}
IssueResult is the domain return type for ListRepoIssues and GetIssue.
func GetIssue ¶ added in v1.41.0
GetIssue fetches a single issue (including its body) by number. Returns ErrNotAuthenticated when no token is configured.
func ListRepoIssues ¶ added in v1.35.0
func ListRepoIssues(ctx context.Context, owner, repo, state, search string, limit int) ([]IssueResult, error)
ListRepoIssues fetches issues for a specific repo. When search is empty it uses GET /repos/{owner}/{repo}/issues. When search is non-empty it uses GET /search/issues. Returns ErrNotAuthenticated when no token is configured.
type PRAnnotationSession ¶ added in v1.35.0
type PRAnnotationSession struct {
ID string
Branch string
Repo RepoRef
PRNumber int // fallback: match by PR number when branch name doesn't match headRef
}
PRAnnotationSession carries session data needed to annotate UserPR entries. Defined here (not in the session package) to avoid an import cycle: session imports github, so github cannot import session.
Repo is a typed value object: holding a valid RepoRef proves owner and repo are non-empty. Sessions without a resolvable GitHub repo are skipped.
type PRAnnotationWorktree ¶ added in v1.35.0
PRAnnotationWorktree carries worktree data for annotation.
type PRComment ¶
type PRComment struct {
ID int `json:"id"`
Author string `json:"author"`
Body string `json:"body"`
CreatedAt time.Time `json:"createdAt"`
Path string `json:"path,omitempty"` // For review comments
Line int `json:"line,omitempty"` // For review comments
IsReview bool `json:"isReview,omitempty"` // True if this is a review comment
}
PRComment represents a comment on a PR (either issue comment or review comment)
type PRInfo ¶
type PRInfo struct {
Number int `json:"number"`
Title string `json:"title"`
Body string `json:"body"`
HeadRef string `json:"headRefName"`
BaseRef string `json:"baseRefName"`
State string `json:"state"`
Author string `json:"author"`
Labels []string `json:"labels"`
HTMLURL string `json:"url"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
IsDraft bool `json:"isDraft"`
Mergeable string `json:"mergeable"`
Additions int `json:"additions"`
Deletions int `json:"deletions"`
ChangedFiles int `json:"changedFiles"`
// Review and CI status fields (populated by GetPRInfo with extended fields)
ReviewDecision string // "approved" / "changes_requested" / "review_required" / ""
ApprovedCount int // Count of current non-dismissed APPROVED reviews
ChangesRequestedCount int // Count of current non-dismissed CHANGES_REQUESTED reviews
CheckConclusion string // "success" / "failure" / "pending" / "action_required" / "neutral" / ""
CheckStatus string // "completed" / "in_progress" / ""
}
PRInfo contains metadata about a GitHub pull request
func GetPRByNumber ¶ added in v1.41.0
GetPRByNumber fetches a single pull request by its number using the GitHub REST API directly (no gh subprocess). Unlike GetPRForBranch, which looks a PR up by head branch name and can therefore match the wrong PR when a branch is reused or renamed, GetPRByNumber looks a PR up by its immutable number — the root-cause fix for branch-name-keyed lookups matching stale or unrelated PRs.
Returns ErrNoPR when no pull request exists for the given number (HTTP 404). Before returning success, the response's base.repo.full_name is compared against the requested owner/repo; a mismatch returns a non-nil, non-ErrNoPR error rather than trusting the response body blindly.
func GetPRForBranch ¶ added in v1.12.0
GetPRForBranch finds the GitHub PR associated with a branch. Uses the GitHub REST API directly (no gh subprocess) to avoid forkExec lock contention. Returns ErrNoPR when no pull request exists for the branch.
func GetPRForBranchConditional ¶ added in v1.37.0
func GetPRForBranchConditional(ctx context.Context, owner, repo, branch, etag string) (info *PRInfo, newEtag string, changed bool, err error)
GetPRForBranchConditional is GetPRForBranch with ETag conditional request support. Pass the previously returned newEtag (empty string for first call). Returns (nil, etag, false, nil) on 304 Not Modified — caller should treat as unchanged.
func GetPRInfoConditional ¶ added in v1.12.0
func GetPRInfoConditional(ctx context.Context, owner, repo string, prNumber int, cache *ETagCache) (*PRInfo, bool, error)
GetPRInfoConditional fetches PR info using ETag conditional requests. Uses native net/http instead of a gh subprocess to avoid forkExec lock contention. Returns (info, changed, error).
- changed=false means 304 Not Modified; info contains the cached value.
- changed=true means 200 OK; info contains freshly fetched data.
- Both info and changed may be zero values when an error is returned.
type PRPriority ¶ added in v1.12.0
type PRPriority string
PRPriority is a derived single-enum priority computed from compound PR state.
const ( PRPriorityBlocking PRPriority = "blocking" // changes requested or CI failing PRPriorityReady PRPriority = "ready" // approved + CI passing PRPriorityPending PRPriority = "pending" // awaiting review or checks running PRPriorityDraft PRPriority = "draft" // PR is a draft PRPriorityComplete PRPriority = "complete" // PR is merged or closed PRPriorityNoPR PRPriority = "no_pr" // no PR found for branch PRPriorityAuthError PRPriority = "auth_error" // gh CLI not authenticated PRPriorityError PRPriority = "error" // transient error fetching status )
func DerivePRPriority ¶ added in v1.12.0
func DerivePRPriority(info *PRInfo) PRPriority
DerivePRPriority computes a single priority enum from compound PR state. Returns PRPriorityNoPR if info is nil.
type PRResult ¶ added in v1.41.0
PRResult is the domain return type for GetPR — a lean existence check, not the richer PRInfo returned by GetPRInfoCtx (which shells out to `gh`).
func GetPR ¶ added in v1.41.0
GetPR fetches a single pull request by number via the GitHub REST API (native net/http, not the `gh` CLI subprocess GetPRInfoCtx uses) — a lean existence check sharing GetIssue's auth mechanism and error classification. Returns ErrNotAuthenticated when no token is configured.
type ParsedGitHubRef ¶
type ParsedGitHubRef struct {
Type RefType
Host string // GitHub host, e.g. "github.com" or a GHES hostname; "" means github.com
Owner string
Repo string
PRNumber int // Only populated for RefTypePR
IssueNumber int // Only populated for RefTypeIssue
Branch string // Populated for RefTypeBranch, or PR head branch after fetching
CommitSHA string // Only populated for RefTypeCommit
FilePath string // Only populated for RefTypeFile (path within repo)
LineStart int // Only populated for RefTypeFile (optional line number)
LineEnd int // Only populated for RefTypeFile (optional end line for range)
BaseBranch string // Only populated for RefTypeCompare (the base of comparison)
HeadBranch string // Only populated for RefTypeCompare (the head being compared)
Tag string // Only populated for RefTypeRelease
OriginalURL string // The original input string
}
ParsedGitHubRef represents a parsed GitHub URL or reference
func ParseGitHubRef ¶
func ParseGitHubRef(input string) (*ParsedGitHubRef, error)
ParseGitHubRef parses a GitHub URL or shorthand reference into a ParsedGitHubRef Supported formats:
- https://github.com/owner/repo/pull/123
- https://github.com/owner/repo/tree/branch-name
- https://github.com/owner/repo/blob/branch/path/to/file.go
- https://github.com/owner/repo/blob/branch/file.go#L10 (with line number)
- https://github.com/owner/repo/blob/branch/file.go#L10-L20 (with line range)
- https://github.com/owner/repo/commit/abc123
- https://github.com/owner/repo/issues/42
- https://github.com/owner/repo/compare/main...feature
- https://github.com/owner/repo/releases/tag/v1.0.0
- https://github.com/owner/repo
- github.com/owner/repo
- git@github.com:owner/repo.git (SSH)
- ssh://git@github.com/owner/repo (SSH protocol)
- owner/repo:branch-name
- owner/repo
func ParseGitHubRefWithHosts ¶ added in v1.41.0
func ParseGitHubRefWithHosts(input string, enterpriseHosts []string) (*ParsedGitHubRef, error)
ParseGitHubRefWithHosts parses a GitHub URL or shorthand reference into a ParsedGitHubRef, matching either github.com or any of the supplied enterpriseHosts. The Host field of the returned ref is set to the matched host (or left empty for shorthand references, which default to github.com).
func (*ParsedGitHubRef) CloneURL ¶
func (p *ParsedGitHubRef) CloneURL() string
CloneURL returns the HTTPS clone URL for the repository
func (*ParsedGitHubRef) DisplayName ¶
func (p *ParsedGitHubRef) DisplayName() string
DisplayName returns a human-readable name for the reference
func (*ParsedGitHubRef) HTMLURL ¶
func (p *ParsedGitHubRef) HTMLURL() string
HTMLURL returns the human-readable GitHub URL
func (*ParsedGitHubRef) RepoFullName ¶
func (p *ParsedGitHubRef) RepoFullName() string
RepoFullName returns "owner/repo" format
func (*ParsedGitHubRef) SuggestedSessionName ¶
func (p *ParsedGitHubRef) SuggestedSessionName() string
SuggestedSessionName returns a suggested session name based on the reference
type RateLimiter ¶ added in v1.37.0
type RateLimiter struct {
// contains filtered or unexported fields
}
RateLimiter tracks GitHub primary and secondary rate limit state.
Primary rate limit — hourly quota per authenticated token (5000 req/hr for PAT).
Signalled by X-RateLimit-Remaining → 0 and X-RateLimit-Reset (Unix epoch, seconds). Response: 403 or 429 with X-RateLimit-Remaining: 0.
Secondary rate limit — concurrent connection / per-minute burst limits.
Signalled by 429 or 403 with Retry-After header present. X-RateLimit-Remaining may still be nonzero.
Detection order: Retry-After present → secondary; remaining == 0 → primary; neither → auth/permission error (do not pause polling).
func (*RateLimiter) IsLimited ¶ added in v1.37.0
func (r *RateLimiter) IsLimited() (bool, time.Time)
IsLimited returns true and the resume time if the client is currently rate limited.
func (*RateLimiter) Update ¶ added in v1.37.0
func (r *RateLimiter) Update(resp *http.Response)
Update reads GitHub rate-limit headers from resp and updates the limiter. Called automatically by rateLimitTransport on every response — callers do not need to invoke this manually.
func (*RateLimiter) WaitIfLimited ¶ added in v1.37.0
func (r *RateLimiter) WaitIfLimited(ctx context.Context) error
WaitIfLimited blocks until the rate limit clears or ctx is cancelled.
type RefType ¶
type RefType int
RefType represents the type of GitHub reference parsed from a URL or shorthand
type RepoRef ¶ added in v1.35.0
type RepoRef struct {
// contains filtered or unexported fields
}
RepoRef is a value object that bundles a GitHub owner and repository name. Both fields are non-empty by construction — holding a RepoRef proves the invariant holds without any further nil/empty checks at use sites.
func GetOwnerRepoFromRemote ¶ added in v1.35.0
GetOwnerRepoFromRemote returns a RepoRef for a local git repository by reading the origin remote URL and parsing it. Returns an invalid zero-value RepoRef (not an error) when the remote is not a GitHub URL.
func NewRepoRef ¶ added in v1.35.0
NewRepoRef constructs a RepoRef, returning an error if either field is empty.
func (RepoRef) BranchKey ¶ added in v1.35.0
BranchKey returns the map key used to match sessions by branch: "owner/branch".
func (RepoRef) IsValid ¶ added in v1.35.0
IsValid reports whether the ref was constructed with non-empty owner and repo. The zero value (RepoRef{}) is not valid.
type RepoResult ¶ added in v1.35.0
RepoResult is the domain return type for SearchUserRepos.
func SearchUserRepos ¶ added in v1.35.0
SearchUserRepos fetches repos accessible to the authenticated user. When query is empty it uses GET /user/repos (all accessible repos sorted by push time). When non-empty it uses GET /search/repositories. Returns ErrNotAuthenticated when no token is configured.
type UserPR ¶ added in v1.35.0
type UserPR struct {
Owner string
Repo string
Number int
Title string
URL string
HeadRef string
BaseRef string
State string
IsDraft bool
UpdatedAt time.Time
ClosedAt time.Time
MergedAt time.Time
ApprovedCount int
ChangesReqCount int
CheckConclusion string // "success" / "failure" / "pending" / ""
SessionIDs []string
LocalWorktreePath string
}
UserPR is an open GitHub pull request authored by the authenticated user, optionally annotated with local session IDs and worktree paths.
type UserPRCache ¶ added in v1.35.0
type UserPRCache struct {
// contains filtered or unexported fields
}
func NewUserPRCache ¶ added in v1.35.0
func NewUserPRCache() *UserPRCache
NewUserPRCache creates a cache with default configuration.
func NewUserPRCacheWithConfig ¶ added in v1.35.0
func NewUserPRCacheWithConfig(cfg UserPRCacheConfig) *UserPRCache
NewUserPRCacheWithConfig creates a cache with custom configuration.
func (*UserPRCache) Annotate ¶ added in v1.35.0
func (c *UserPRCache) Annotate(sessions []PRAnnotationSession, worktrees []PRAnnotationWorktree)
Annotate enriches the current snapshot with session IDs and worktree paths. It performs a COW update: load → copy → mutate → store. No-op if the snapshot hasn't been populated yet.
func (*UserPRCache) GetAll ¶ added in v1.35.0
func (c *UserPRCache) GetAll() []UserPR
GetAll returns a copy of the current PR snapshot. Returns nil before the first successful fetch.
func (*UserPRCache) GetCachedAccounts ¶ added in v1.41.0
func (c *UserPRCache) GetCachedAccounts() []CachedAccount
GetCachedAccounts returns all connected GitHub accounts with their host.
func (*UserPRCache) GetCachedLogin ¶ added in v1.35.0
func (c *UserPRCache) GetCachedLogin() string
GetCachedLogin returns the first connected GitHub login, or "" if none yet.
func (*UserPRCache) GetCachedLogins ¶ added in v1.35.0
func (c *UserPRCache) GetCachedLogins() []string
GetCachedLogins returns all connected GitHub logins.
func (*UserPRCache) InvalidateLoginCache ¶ added in v1.35.0
func (c *UserPRCache) InvalidateLoginCache()
InvalidateLoginCache clears the cached login state so the next Refresh call re-fetches the authenticated user from the GitHub API. Call this after storing a new token (e.g. after a successful Device Flow auth) so the cache picks up the new credentials immediately.
func (*UserPRCache) Refresh ¶ added in v1.35.0
func (c *UserPRCache) Refresh(ctx context.Context) error
Refresh triggers an immediate fetch from GitHub, coalescing concurrent calls.
func (*UserPRCache) SetOnUpdated ¶ added in v1.35.0
func (c *UserPRCache) SetOnUpdated(fn func(prs []UserPR))
SetOnUpdated atomically registers a callback invoked after every successful refresh. Pass nil to clear. The callback receives the current PR slice. Safe to call at any time, including after Start.
func (*UserPRCache) Start ¶ added in v1.35.0
func (c *UserPRCache) Start(ctx context.Context)
Start launches the background polling goroutine. Safe to call multiple times; only the first call starts the goroutine.
func (*UserPRCache) Stop ¶ added in v1.35.0
func (c *UserPRCache) Stop()
Stop halts background polling and blocks until loop() has actually exited. Without waiting here, a caller (notably a test's t.Cleanup) can return while loop()'s unconditional first fetch (see loop's doc comment) is still running, letting it race the next caller's use of shared package-level state (e.g. go-keyring's mock, which a subsequent test re-initializes via MockInit) — confirmed live via `go test -race`: TestListGitHubAccounts_ AccountOnUnconfiguredEnterpriseHost_IncludesHostInEnterpriseHosts raced against a prior test's still-running fetch() on go-keyring's global state. Safe to call before Start (done is nil, no-op) or more than once (cancel and a receive on an already-closed channel are both idempotent).
func (*UserPRCache) Subscribe ¶ added in v1.35.0
func (c *UserPRCache) Subscribe(id string, ch chan []UserPR)
Subscribe registers a channel to receive PR snapshot updates. The channel must be buffered. The caller is responsible for calling Unsubscribe.
func (*UserPRCache) Unsubscribe ¶ added in v1.35.0
func (c *UserPRCache) Unsubscribe(id string)
Unsubscribe removes a previously registered subscriber channel.
type UserPRCacheConfig ¶ added in v1.35.0
type UserPRCacheConfig struct {
// PollInterval controls how often the cache refreshes from GitHub.
PollInterval time.Duration
// LoginCacheTTL controls how long the authenticated login is cached.
LoginCacheTTL time.Duration
}
UserPRCacheConfig controls polling behaviour.
func DefaultUserPRCacheConfig ¶ added in v1.35.0
func DefaultUserPRCacheConfig() UserPRCacheConfig
DefaultUserPRCacheConfig returns sensible defaults.