Documentation
¶
Overview ¶
Package github provides GitHub integration for querying PR status.
Package github provides GitHub integration.
Index ¶
- Constants
- Variables
- func CloneErrorMessage(stderr string) string
- func DefaultCloneRoot() string
- func IsNewerVersion(current, latest string) bool
- func LooksLikeRepoRef(input string) bool
- func MarshalPRInfo(info *PRInfo) string
- func PollInterval(info *PRInfo) time.Duration
- type AccountType
- type AuthStatus
- type BranchFetcher
- type BranchPRs
- type CheckState
- type CloneDestination
- type CloneError
- type Cloner
- type CommandBuilder
- type Finding
- type LatestRelease
- type PRInfo
- type PRPoller
- type PRResult
- type PRState
- type PRTarget
- type RateLimitError
- type RepoRef
- type Severity
Constants ¶
const ( // PRPollActive applies while checks run or GitHub is still computing // mergeability — the states a human is watching change. PRPollActive = 30 * time.Second // PRPollSettled applies to an open PR nothing is currently moving on. PRPollSettled = 3 * time.Minute // PRPollNoPR applies to a branch with no PR yet, waiting for one to appear. PRPollNoPR = 2 * time.Minute )
Poll cadence. A PR whose state is still settling is asked about often; a settled one rarely; a merged or closed one never again.
const DefaultHost = "github.com"
DefaultHost is the host assumed for shorthand refs ("owner/repo").
Variables ¶
ErrGHUnavailable means gh is missing or cannot authenticate. Callers treat it like any other failed lookup: keep the last known state and back off.
Functions ¶
func CloneErrorMessage ¶
CloneErrorMessage distills git's stderr to the lines worth showing: progress chatter and the "Cloning into…" banner are dropped, the rest is kept verbatim.
func DefaultCloneRoot ¶
func DefaultCloneRoot() string
DefaultCloneRoot is where clones land unless told otherwise: ~/Projects.
func IsNewerVersion ¶
IsNewerVersion returns true if latest is a newer version than current. Both should be semver strings, optionally prefixed with "v".
func LooksLikeRepoRef ¶
LooksLikeRepoRef reports whether input is shaped like a repo URL at all — used to decide whether a parse failure is worth an inline error (a paste gone wrong) or just an ordinary search term.
func MarshalPRInfo ¶
MarshalPRInfo converts a PRInfo to JSON string for database storage.
func PollInterval ¶
PollInterval reports how long a PR state stays fresh. Zero means the state is terminal and never needs asking again.
Types ¶
type AccountType ¶
type AccountType string
AccountType classifies the identity that `gh` is authenticated as.
const ( // AccountTypeUnknown means we could not determine the identity. AccountTypeUnknown AccountType = "unknown" // AccountTypePersonal is a regular GitHub user account (e.g. via `gh auth login`). // Personal accounts share a single 5,000 pt/hr GraphQL bucket PER-USER across // every machine authenticated as that user — the root cause of bucket exhaustion. AccountTypePersonal AccountType = "personal" // AccountTypeApp is a GitHub App / bot identity (login ends in "[bot]", // API type "Bot"). Each App installation token gets its OWN GraphQL bucket, // so it does not contend with other servers. AccountTypeApp AccountType = "app" )
type AuthStatus ¶
type AuthStatus struct {
GHInstalled bool
LoggedIn bool
TokenValid bool // false when the token is expired/revoked (401 Bad credentials)
Account string
AccountType AccountType
// GraphQL rate-limit headroom. Remaining/Limit are -1 when unknown.
GraphQLRemaining int
GraphQLLimit int
GraphQLResetAt time.Time
// Err holds an unexpected error encountered while probing (not auth state).
Err error
}
AuthStatus is the result of inspecting the local `gh` authentication.
func CheckAuth ¶
func CheckAuth(ctx context.Context) AuthStatus
CheckAuth inspects the local `gh` CLI authentication and rate-limit headroom. It never returns an error for ordinary auth states (not installed, logged out, expired token); those are reported via the returned AuthStatus fields.
func (AuthStatus) Findings ¶
func (s AuthStatus) Findings() []Finding
Findings translates the auth status into ordered diagnostic findings. The most severe issues come first. This is the data `ty doctor` renders.
func (AuthStatus) HasProblems ¶
func (s AuthStatus) HasProblems() bool
HasProblems reports whether any finding is a warning or error.
type BranchFetcher ¶
BranchFetcher looks up the PRs for a set of branches in one repository.
type BranchPRs ¶
type BranchPRs struct {
// PRs maps branch name to its PR. A branch that was asked about and is
// absent here definitively has no PR — the query succeeded.
PRs map[string]*PRInfo
// RateRemaining is GraphQL budget left after the query, -1 if unknown.
RateRemaining int
RateResetAt time.Time
}
BranchPRs is the answer to one batched lookup.
func FetchPRsForBranches ¶
func FetchPRsForBranches(ctx context.Context, repoDir string, branches []string) (*BranchPRs, error)
FetchPRsForBranches looks up the newest PR for each branch in the repository that repoDir's origin points at, in as few GraphQL calls as the batch size allows. Any failed call fails the whole lookup: a partial answer would make the missing branches look PR-less.
type CheckState ¶
type CheckState string
CheckState represents the state of CI checks.
const ( CheckStatePending CheckState = "PENDING" CheckStatePassing CheckState = "SUCCESS" CheckStateFailing CheckState = "FAILURE" CheckStateNone CheckState = "" )
type CloneDestination ¶
type CloneDestination struct {
Path string
// Reuse is true when Path already holds a checkout of the same repo, so
// there's nothing to clone — the caller can adopt it as-is.
Reuse bool
// Renamed is true when the natural directory name was taken by something
// else and a non-colliding one was picked instead.
Renamed bool
}
CloneDestination is where a clone will land, and how we got there.
type CloneError ¶
CloneError carries git's own stderr so the UI can show the user exactly what git said (bad auth, no such repo, no network).
func (*CloneError) Error ¶
func (e *CloneError) Error() string
func (*CloneError) Unwrap ¶
func (e *CloneError) Unwrap() error
type Cloner ¶
type Cloner struct {
// Root is where clones land. Empty means ~/Projects.
Root string
// RemoteURL returns dir's origin remote. Nil means ask git.
RemoteURL func(dir string) (string, error)
// Run performs the clone itself. Nil means run `git clone`.
Run func(ctx context.Context, cloneURL, dest string) error
// Command builds the git invocations. Nil means run them locally.
Command CommandBuilder
}
Cloner clones repos into a root directory. The zero value clones into ~/Projects using the git binary on this machine; tests substitute the seams.
func (Cloner) Clone ¶
Clone clones ref into dest. A failed or cancelled clone leaves nothing behind: whatever git managed to write is removed, and a directory that existed (empty) beforehand is restored empty.
func (Cloner) IsCheckoutOf ¶
IsCheckoutOf reports whether dir is a git checkout whose origin is ref.
func (Cloner) Resolve ¶
func (c Cloner) Resolve(ref RepoRef) (CloneDestination, error)
Resolve picks the directory ref should be cloned into. An existing checkout of the same repo is reused; an unrelated directory of the same name is stepped around ("repo-2"); an existing empty directory is used as-is, because git clones into those happily.
type CommandBuilder ¶
CommandBuilder builds a command to run in workDir. It is the signature of executor.Runner's Command method, restated here because internal/executor imports this package and the dependency can only point one way.
A clone has to happen wherever the checkout is going to live, so the git binary is invoked through one of these rather than directly. Nil means the local machine, which is what it has always been.
type LatestRelease ¶
LatestRelease holds information about the latest GitHub release.
func CLIVersionCheck ¶
func CLIVersionCheck(currentVersion string) *LatestRelease
CLIVersionCheck checks if a newer version is available, using a 24h on-disk cache. Returns the latest release if an upgrade is available, nil otherwise. Skips the check entirely for "dev" builds.
func FetchLatestRelease ¶
func FetchLatestRelease() *LatestRelease
FetchLatestRelease queries the GitHub API for the latest release. Returns nil if the request fails or no release exists.
type PRInfo ¶
type PRInfo struct {
Number int `json:"number"`
URL string `json:"url"`
State PRState `json:"state"`
IsDraft bool `json:"isDraft"`
Title string `json:"title"`
CheckState CheckState `json:"checkState"`
Mergeable string `json:"mergeable"` // "MERGEABLE", "CONFLICTING", "UNKNOWN"
// MergeStateStatus is GitHub's fuller merge verdict: CLEAN, BLOCKED, BEHIND,
// DIRTY, UNSTABLE, HAS_HOOKS, DRAFT or UNKNOWN.
MergeStateStatus string `json:"mergeStateStatus,omitempty"`
// ReviewDecision is APPROVED, CHANGES_REQUESTED, REVIEW_REQUIRED or "".
ReviewDecision string `json:"reviewDecision,omitempty"`
UpdatedAt time.Time `json:"updatedAt"`
Additions int `json:"additions"` // Lines added
Deletions int `json:"deletions"` // Lines deleted
}
PRInfo contains information about a pull request.
func LookupPR ¶
LookupPR returns the PR for one branch. (nil, nil) means the branch has no PR; a non-nil error means GitHub could not be asked and the caller must not treat the task as PR-less.
func UnmarshalPRInfo ¶
UnmarshalPRInfo converts a JSON string from database back to PRInfo.
func (*PRInfo) StatusDescription ¶
StatusDescription returns a human-readable description. For an open PR it names the one thing most in the way of merging, in the order a human has to deal with them: conflicts, then red checks, then requested changes.
func (*PRInfo) StatusIcon ¶
StatusIcon returns a unicode icon representing the PR state.
type PRPoller ¶
type PRPoller struct {
// contains filtered or unexported fields
}
PRPoller decides which branches are due and asks GitHub about them, one query per repository. It is the single background owner of PR status: the daemon runs one, and every surface reads what it stores.
func NewPRPoller ¶
func NewPRPoller() *PRPoller
NewPRPoller returns a poller that talks to GitHub through gh.
func NewPRPollerWithFetcher ¶
func NewPRPollerWithFetcher(fetch BranchFetcher) *PRPoller
NewPRPollerWithFetcher returns a poller that looks PRs up with fetch, for callers that need to stand in for GitHub.
type PRResult ¶
PRResult is a successful lookup. Info nil means the branch has no PR. Targets whose lookup failed produce no result, so their last good state stands.
type PRTarget ¶
type PRTarget struct {
TaskID int64
RepoDir string
Branch string
// Known is the last stored state, nil if none. It drives the cadence.
Known *PRInfo
}
PRTarget is one branch whose PR status someone wants kept current.
type RateLimitError ¶
RateLimitError reports that GitHub refused the query for rate limiting. ResetAt is zero when GitHub didn't say when the budget returns.
func (*RateLimitError) Error ¶
func (e *RateLimitError) Error() string
type RepoRef ¶
type RepoRef struct {
Host string // e.g. "github.com"
Owner string
Name string
// SSH records that the user pasted an ssh URL. We clone back over ssh so
// their key-based auth keeps working for private repos.
SSH bool
}
RepoRef identifies a repository on a git host. It is the normalized form of every URL shape a user might paste (https, scp-style ssh, or shorthand).
func ParseRepoRef ¶
ParseRepoRef normalizes the repo URL forms people actually paste:
https://github.com/owner/repo (with or without .git or a trailing /) git@github.com:owner/repo.git ssh://git@github.com/owner/repo.git github.com/owner/repo owner/repo
Anything else returns an error whose text names the next step, so it can be shown inline. Nothing is shelled out to git before this succeeds.
func RepoForDir ¶
RepoForDir resolves which GitHub repository a checkout's origin points at, locally and without an API call. Successful answers are cached per directory.
func (RepoRef) SameRepo ¶
SameRepo reports whether two refs point at the same repository. Host, owner and name are compared case-insensitively; the transport is ignored, so an https clone matches an ssh remote.