Help us shape the future of Go! Take the 2026 Go Developer Survey

github

package
v1.0.0-rc.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 1, 2026 License: MIT Imports: 29 Imported by: 0

Documentation

Overview

Package github resolves a worktree's GitHub repository and token the way gh does and talks to the GitHub API.

Index

Constants

View Source
const (
	// JobLogTail is how much of the end of a job log JobLog keeps.
	JobLogTail = 1 << 20
)

Variables

View Source
var (
	// ErrRateLimited is what a *RateLimitError matches.
	ErrRateLimited = errors.New("github: rate limited")
	// ErrNoSHA is returned by an approve or merge given no commit; nothing is sent.
	ErrNoSHA = errors.New("github: no commit given")
	// ErrHeadMoved is returned by a merge whose head commit changed since the review.
	ErrHeadMoved = errors.New("github: the head moved since the review")
	// ErrNotMergeable is returned by a merge GitHub refuses as not mergeable.
	ErrNotMergeable = errors.New("github: not mergeable")
	// ErrPRExists is returned by a create when the branch already has a pull request.
	ErrPRExists = errors.New("github: a pull request already exists")
	// ErrNoPR is returned when a branch has no pull request.
	ErrNoPR = errors.New("github: no pull request")
)
View Source
var (
	// ErrNotImageHost is returned for a URL that may not load; no request is made.
	ErrNotImageHost = errors.New("github: not an image host")
	// ErrImageTooLarge is returned for an image over the fetch limit.
	ErrImageTooLarge = errors.New("github: image too large")
)
View Source
var (
	ErrNotGitHub = errors.New("github: not a GitHub repository")
	ErrNoToken   = errors.New("github: no token")
)
View Source
var ErrJobLogTooLarge = errors.New("github: job log too large")

ErrJobLogTooLarge is returned for a log of more than jobLogReadMax bytes from a server that ignores Range.

Functions

func ImageHost

func ImageHost(rawURL, docHost string) bool

ImageHost reports whether rawURL may be fetched: https with no user info, on port 443 or none, at github.com, a .githubusercontent.com host or docHost, and not an .svg path. Host comparisons ignore case.

func Token

func Token(ctx context.Context, host string, o TokenOptions) (string, error)

Token returns the token for host from the environment or gh's config, else from `gh auth token`. Nothing found is ErrNoToken; an empty or option-like host is refused first. gh's output is never copied into an error.

Types

type Check

type Check struct {
	ID                     int64  // a run's id, which is its job id for an Actions job; 0 for a status
	App                    string // a run's app slug; "" for a status
	Name, Kind, URL        string // Kind "run" or "status"
	State                  CheckState
	Conclusion             string // GitHub's raw conclusion or status state
	StartedAt, CompletedAt time.Time
}

Check is one check run or commit status of a commit.

type CheckRunOutput

type CheckRunOutput struct{ Title, Summary string }

CheckRunOutput is the output a check run reports.

type CheckState

type CheckState string

CheckState is the combined state of a set of checks, or of one check.

const (
	CheckNone    CheckState = ""
	CheckPending CheckState = "pending"
	CheckSuccess CheckState = "success"
	CheckFailure CheckState = "failure"
	CheckSkipped CheckState = "skipped" // one check only: neutral, skipped or stale
)

type Checks

type Checks struct {
	State               CheckState
	Total, Done, Failed int
}

Checks summarises the check runs and status contexts of a head commit.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client talks to one GitHub host. It is safe for concurrent use.

func NewClient

func NewClient(host string, o Options) (*Client, error)

NewClient builds a client for host, which must be named. Host, token and transport are always passed, so go-gh resolves none of them and never logs requests.

func (*Client) Approve

func (c *Client) Approve(ctx context.Context, r Repo, number int, sha string) error

Approve approves number at the reviewed commit sha. An empty sha or a non-positive number sends nothing.

func (*Client) CheckRun

func (c *Client) CheckRun(ctx context.Context, r Repo, id int64) (CheckRunOutput, error)

CheckRun reads the output of check run id: the title and summary a check reports when it is not an Actions job.

func (*Client) Checks

func (c *Client) Checks(ctx context.Context, r Repo, sha string) ([]Check, error)

Checks returns the check runs of commit sha in API order, then its commit statuses by name. Runs are read over at most five pages.

func (*Client) Conversation

func (c *Client) Conversation(ctx context.Context, r Repo, number int) (Conversation, error)

Conversation reads a pull request's description and its newest 500 timeline items. A pull request that does not exist is ErrNoPR.

func (*Client) CreatePR

func (c *Client) CreatePR(ctx context.Context, r Repo, n NewPR) (PR, error)

CreatePR opens a pull request. A branch that already has one is ErrPRExists.

func (*Client) JobLog

func (c *Client) JobLog(ctx context.Context, r Repo, jobID int64) (data []byte, cut bool, err error)

JobLog reads the last JobLogTail bytes of the log of Actions job jobID. cut reports that earlier bytes were left out. A log GitHub has no bytes for (416) is empty, not an error. The storage host GitHub redirects to gets no credentials, and no error holds its signed URL.

func (*Client) Merge

func (c *Client) Merge(ctx context.Context, r Repo, pr PR, info RepoInfo, m MergeOptions) (Merged, error)

Merge merges pr at the reviewed commit m.SHA, so GitHub refuses it when the head moved. Every check runs before any request.

func (*Client) MyPRs

func (c *Client) MyPRs(ctx context.Context, since time.Time) (MyPRs, error)

MyPRs searches the host for the open pull requests that ask for the viewer's review and the ones the viewer opened, at most 100 of each, in repositories that are not archived. A since that is not zero limits the review requests to pull requests updated on or after its UTC date.

func (*Client) PRForBranch

func (c *Client) PRForBranch(ctx context.Context, r Repo, branch string) (PR, error)

PRForBranch returns the same-repository pull request for branch: the newest open one, else the newest of any state. A branch with none is ErrNoPR.

func (*Client) PullRequests

func (c *Client) PullRequests(ctx context.Context, r Repo) (RepoInfo, []PR, RateLimit, error)

PullRequests returns the repository's open pull requests, newest update first, with its merge settings and the GraphQL budget left.

type Commit

type Commit struct{ Subject, Body string }

Commit is the part of a commit that fills a pull request.

type Conversation

type Conversation struct {
	PR      PR
	Created time.Time
	Body    Text
	Items   []TimelineItem // oldest first
	Cut     bool           // older items were not read
}

Conversation is a pull request's description and timeline.

type Draft

type Draft struct{ Title, Body string }

Draft is the title and body a new pull request starts with.

func Fill

func Fill(branch string, commits []Commit, template string) Draft

Fill returns the defaults of `gh pr create --fill`: the only commit's subject as the title, else the branch name made readable; a non-blank template as the body, else the only commit's body or one "- subject" line per commit.

type FocusedChecks

type FocusedChecks struct {
	Number  int
	HeadOID string
	Checks  []Check
}

FocusedChecks are the checks of the focused PR's head commit.

type ImageFetcher

type ImageFetcher struct {
	// contains filtered or unexported fields
}

ImageFetcher fetches images from GitHub's hosts, sending the document host's token to that host only.

func NewImageFetcher

func NewImageFetcher(o ImageOptions) *ImageFetcher

NewImageFetcher returns a fetcher; it looks up each host's token once.

func (*ImageFetcher) Fetch

func (f *ImageFetcher) Fetch(ctx context.Context, rawURL, docHost string, limit int64) ([]byte, error)

Fetch returns the image at rawURL, at most limit bytes. The token goes only to docHost and is dropped for good once a redirect has left it.

type ImageOptions

type ImageOptions struct {
	Token     func(ctx context.Context, host string) (string, error) // nil = Token with default options
	Transport http.RoundTripper                                      // nil = http.DefaultTransport
}

ImageOptions are the seams of an ImageFetcher.

type ItemKind

type ItemKind uint8

ItemKind is the kind of a timeline item.

const (
	ItemComment ItemKind = iota
	ItemReview
	ItemCommits // a push: a run of commits with no other item between them
	ItemForcePush
	ItemReviewRequest
	ItemMerged
	ItemClosed
)

type JobLog

type JobLog struct {
	Lines      []LogLine
	Groups     []LogGroup
	FirstError int
	Cut        bool
}

JobLog is a parsed job log. FirstError is the index of the first error line, -1 for none; Cut says the log starts partway.

func ParseJobLog

func ParseJobLog(data []byte, cut bool) JobLog

ParseJobLog turns the bytes of a job log into lines. Only printable text survives in the spans: every escape sequence but a foreground colour or bold is dropped, as are controls and invisible characters. When cut, the first line is partial and is dropped.

type LogGroup

type LogGroup struct {
	Title string
	Head  int
	End   int
}

LogGroup is a "##[group]" section. Head is its head line and End one past its last line.

type LogKind

type LogKind uint8

LogKind says how a job log line is drawn.

const (
	LogText LogKind = iota
	// LogGroupHead is a group's head line.
	LogGroupHead
	LogError
	LogWarning
	LogNotice
	LogCommand
	LogDebug
)

The kinds of a job log line.

type LogLine

type LogLine struct {
	At    time.Time
	Kind  LogKind
	Spans []LogSpan
	Group int
}

LogLine is one line of a job log. At is zero without a timestamp; Group is -1 outside a group, else the group's index (its head line too).

type LogSpan

type LogSpan struct {
	Text  string
	Color int8
	Bold  bool
}

LogSpan is a run of text in one style. Color is -1 for the default or 0-15 for an ANSI colour.

type MergeMethod

type MergeMethod string

MergeMethod is a way GitHub can merge a pull request.

const (
	MergeCommit MergeMethod = "merge"
	Squash      MergeMethod = "squash"
	Rebase      MergeMethod = "rebase"
)

type MergeOptions

type MergeOptions struct {
	Method       MergeMethod
	SHA          string // the reviewed head: git Result.Head
	DeleteBranch bool
}

MergeOptions say how to merge. SHA is the reviewed head commit; a merge without one is refused before any request.

type Merged

type Merged struct {
	SHA           string // the merge commit
	BranchDeleted bool
	DeleteErr     error
}

Merged is the outcome of a merge that went through. A failed branch delete does not undo it: DeleteErr carries that failure.

type MyPRs

type MyPRs struct {
	Requested, Authored []SearchPR
}

MyPRs holds the open pull requests that ask for the viewer's review and the ones the viewer opened.

type NewPR

type NewPR struct {
	Title, Body, Base, Head string
	Draft                   bool
}

NewPR describes a pull request to create.

type Options

type Options struct {
	Token     string            // required
	Transport http.RoundTripper // nil = http.DefaultTransport
	Timeout   time.Duration     // per request; 0 = 30 s
}

Options configure a Client.

type PR

type PR struct {
	Number                          int
	Title, URL, Author              string
	State                           string // OPEN, MERGED, CLOSED
	Draft, CrossRepo                bool
	ViewerAuthored                  bool // the token's user wrote it; REST answers leave it false
	HeadBranch, HeadOID, BaseBranch string
	ReviewDecision, MergeState      string // GitHub's enums as given; "" when null
	Checks                          Checks
	UpdatedAt                       time.Time
}

PR is a pull request as the poll sees it.

type Poller

type Poller struct {
	// contains filtered or unexported fields
}

Poller polls the open pull requests of every watched repository, one goroutine each, and sends a Snapshot per poll on Updates. It is safe for concurrent use.

func NewPoller

func NewPoller(o PollerOptions) *Poller

NewPoller returns a Poller that watches nothing until Set is called.

func (*Poller) Close

func (p *Poller) Close() error

Close cancels every request, waits for every goroutine and closes Updates. Every call returns only once Updates is closed, and is safe to repeat.

func (*Poller) Refresh

func (p *Poller) Refresh(r Repo)

Refresh polls a watched repository now; any other is ignored. During a rate limit wait the poll comes at the reset instead; after another error it still comes at once.

func (*Poller) Set

func (p *Poller) Set(ws []Watch)

Set replaces the watched repositories. A new one is polled at once, a removed one stops, and one whose focused PR changed is polled at once.

func (*Poller) Updates

func (p *Poller) Updates() <-chan Snapshot

Updates delivers snapshots until Close, which closes the channel.

type PollerOptions

type PollerOptions struct {
	// Client returns the client for a host; a success is kept per host.
	Client                 func(ctx context.Context, host string) (*Client, error)
	Fast, Slow, MaxBackoff time.Duration // 0 = 10 s, 60 s, 5 min
	// contains filtered or unexported fields
}

PollerOptions configure a Poller.

type RateLimit

type RateLimit struct {
	Remaining int
	Reset     time.Time
}

RateLimit is the GraphQL budget left after a query.

type RateLimitError

type RateLimitError struct {
	Reset time.Time
	// contains filtered or unexported fields
}

RateLimitError reports a primary or secondary rate limit; it matches ErrRateLimited and keeps the API error it came from reachable.

func (*RateLimitError) Error

func (e *RateLimitError) Error() string

func (*RateLimitError) Is

func (e *RateLimitError) Is(target error) bool

func (*RateLimitError) Unwrap

func (e *RateLimitError) Unwrap() error

type Repo

type Repo struct{ Host, Owner, Name string }

Repo identifies a repository on a GitHub host.

func ParseRemoteURL

func ParseRemoteURL(raw string) (Repo, error)

ParseRemoteURL reads host, owner and name from a remote URL. Errors never echo the URL, which may carry credentials.

func (Repo) String

func (r Repo) String() string

type RepoInfo

type RepoInfo struct {
	DefaultBranch       string
	Methods             []MergeMethod // allowed, in the order merge, squash, rebase
	DeleteBranchOnMerge bool
}

RepoInfo holds the repository settings a merge needs.

type Resolver

type Resolver struct {
	// contains filtered or unexported fields
}

Resolver turns remote URLs into repositories, mapping ssh aliases through ssh itself and accepting only github.com and hosts gh knows.

func NewResolver

func NewResolver(o ResolverOptions) *Resolver

func (*Resolver) Resolve

func (r *Resolver) Resolve(ctx context.Context, rawURL string) (Repo, error)

Resolve returns the repository a remote URL points at, or ErrNotGitHub. A context that ends while ssh runs is an error of its own, never ErrNotGitHub.

type ResolverOptions

type ResolverOptions struct {
	SSH        string          // the ssh binary; "" = "ssh" on PATH
	KnownHosts func() []string // nil = auth.KnownHosts
}

ResolverOptions configure a Resolver.

type ReviewComment

type ReviewComment struct {
	Path string
	Line int // 0 when unknown
	Hunk string
	Body Text
}

ReviewComment is an inline comment of a review.

type SearchPR

type SearchPR struct {
	Repo Repo
	PR   PR
}

SearchPR is a pull request found by a search, with the repository it is in.

type Snapshot

type Snapshot struct {
	Repo      Repo
	Info      RepoInfo
	PRs       []PR
	Focused   *FocusedChecks
	RateLimit RateLimit
	Err       error // the poll failed; Info, PRs and Focused are empty
	At        time.Time
}

Snapshot is the result of one poll of one repository.

type Template

type Template struct{ Name, Path, Body string }

Template is a pull request template found in a worktree.

func Templates

func Templates(root string) ([]Template, error)

Templates returns the pull request templates under root: the single-file ones in the root, .github and docs, then the files of each PULL_REQUEST_TEMPLATE directory there, by name. Every read goes through os.OpenRoot, so a symlink that leaves root is skipped. A missing location, a symlink that leaves root or dangles, a non-regular file and a file over 64 KiB are skipped. Any other read error is joined into the returned error, and the templates that could be read are returned with it.

type Text

type Text struct {
	Markdown string
	Images   map[string]string // image source as written to the signed URL; nil when none
}

Text is a markdown body and the signed URLs of its private images.

type TimelineItem

type TimelineItem struct {
	Kind ItemKind
	ID   string // the node id; the last commit's oid for ItemCommits
	// Author is a login ("ghost" for none), or a git author name when Named.
	Author string
	Bot    bool
	Named  bool
	At     time.Time

	Body     Text
	State    string // a review's: APPROVED, CHANGES_REQUESTED, COMMENTED or DISMISSED
	Comments []ReviewComment

	Commits            int    // ItemCommits
	Ref, Before, After string // ItemForcePush: abbreviated oids
	Reviewer           string // ItemReviewRequest: a login or org/slug
	Commit, Base       string // ItemMerged
}

TimelineItem is one entry of a pull request's conversation. Only the fields of its Kind are set, besides the common ones.

type TokenOptions

type TokenOptions struct {
	FromEnvOrConfig func(host string) string // nil = auth.TokenFromEnvOrConfig's token
	GH              string                   // the gh binary; "" = "gh" on PATH
}

TokenOptions configure Token.

type Watch

type Watch struct {
	Repo    Repo
	Visible []int // PR numbers on screen
	Focused int   // the PR whose checks are fetched over REST; 0 = none
}

Watch is one repository to poll.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL