Documentation
¶
Overview ¶
Package github is falconet's adapter to the GitHub API: an interface the verbs depend on, the types GitHub answers with, and the handful of environment and URL helpers a verb needs to find its repository and its token. The one implementation shells out to the `gh` CLI (ghcli.go); nothing in the verbs knows that.
Nothing here retries, paginates or caches. A verb makes a call or three and reports each result, and a call that fails is an error carrying the status and the message GitHub sent, which is what a run log needs and all it needs. The list reads ask for 100 per page and read one page; each says so in its own comment, so a caller that could be handed the 101st item knows it will not be.
A 404 from GitHub means "not found" OR "no access": a private repository answers a token without permission exactly as it answers a name that does not exist, by design. The error says both, because both are true of what the caller knows.
The test suite points GITHUB_API_URL at tests/fixtures/fake-github.py, a loopback server that answers from fixtures and records what it was asked; the gh adapter sends to that URL the same way it sends to api.github.com.
Index ¶
- Constants
- func APIURLFromEnv() string
- func IssuePath(owner, name string, number int, rest string) string
- func Message(raw []byte) string
- func ParseRemoteURL(remote, host string) (owner, name string, err error)
- func RepoPath(owner, name, rest string) string
- func ServerHostFromEnv() string
- func SplitRepository(s string) (owner, name string, err error)
- func TokenFromEnv() string
- type Client
- type Error
- type GH
- func (g *GH) AddIssueAssignees(owner, name string, number int, logins []string) error
- func (g *GH) AddIssueLabels(owner, name string, number int, labels []string) error
- func (g *GH) CreateIssueComment(owner, name string, number int, body string) error
- func (g *GH) GetAuthenticatedUser() (*User, error)
- func (g *GH) GetIssue(owner, name string, number int) (*Issue, error)
- func (g *GH) GetIssueRaw(owner, name string, number int) (json.RawMessage, error)
- func (g *GH) ListIssueComments(owner, name string, number int) ([]IssueComment, error)
- func (g *GH) ListIssueCommentsRaw(owner, name string, number int) (json.RawMessage, error)
- func (g *GH) ListOpenPulls(owner, name string) ([]PullRequest, error)
- func (g *GH) RemoveIssueAssignees(owner, name string, number int, logins []string) error
- func (g *GH) RemoveIssueLabel(owner, name string, number int, label string) error
- type Issue
- type IssueComment
- type Label
- type PullRequest
- type User
Constants ¶
const DefaultAPIURL = "https://api.github.com"
DefaultAPIURL is api.github.com, which is what Actions sets GITHUB_API_URL to on github.com; a GitHub Enterprise Server run sets its own.
Variables ¶
This section is empty.
Functions ¶
func APIURLFromEnv ¶
func APIURLFromEnv() string
APIURLFromEnv is $GITHUB_API_URL, or the default, with no trailing slash.
func IssuePath ¶ added in v1.1.0
IssuePath builds /repos/{owner}/{name}/issues/{number}[/rest], with owner and name path-escaped.
func Message ¶ added in v1.1.0
Message extracts the "message" field from a JSON error response, or "".
func ParseRemoteURL ¶
ParseRemoteURL reads owner and name out of a git remote URL that points at host — the three shapes git writes for a GitHub clone:
https://HOST/owner/name[.git][/] git@HOST:owner/name[.git] ssh://git@HOST[:port]/owner/name[.git]
Credentials in the URL (https://user:token@HOST/…) are ignored, not compared. Hosts compare case-insensitively, as DNS does. Any other host, or a URL that does not reduce to owner/name, is an error: a verb that operates on "the repository this clone came from" must never guess one from a remote that points somewhere else.
func RepoPath ¶
RepoPath is /repos/{owner}/{name}{rest}, with owner and name path-escaped, so that every call spells the repository the same way.
func ServerHostFromEnv ¶
func ServerHostFromEnv() string
ServerHostFromEnv is the host of $GITHUB_SERVER_URL — the variable Actions sets, "https://github.com" on github.com and an enterprise server's own URL there — or "github.com" when it is unset or does not parse.
func SplitRepository ¶
SplitRepository reads "owner/name" — the shape of $GITHUB_REPOSITORY — into its two halves. Anything else is an error naming what was expected.
func TokenFromEnv ¶
func TokenFromEnv() string
TokenFromEnv is $GH_TOKEN, or $GITHUB_TOKEN, or empty — the two names the workflow hands the verbs, and the two names `gh` reads.
Types ¶
type Client ¶
type Client interface {
GetIssue(owner, name string, number int) (*Issue, error)
GetIssueRaw(owner, name string, number int) (json.RawMessage, error)
ListIssueComments(owner, name string, number int) ([]IssueComment, error)
ListIssueCommentsRaw(owner, name string, number int) (json.RawMessage, error)
ListOpenPulls(owner, name string) ([]PullRequest, error)
GetAuthenticatedUser() (*User, error)
CreateIssueComment(owner, name string, number int, body string) error
AddIssueLabels(owner, name string, number int, labels []string) error
RemoveIssueLabel(owner, name string, number int, label string) error
AddIssueAssignees(owner, name string, number int, logins []string) error
RemoveIssueAssignees(owner, name string, number int, logins []string) error
}
Client is the adapter: the verbs talk to GitHub through it.
type GH ¶ added in v1.1.0
type GH struct {
// contains filtered or unexported fields
}
GH is a Client backed by the `gh` CLI. It shells out to `gh api` for every call, sending full URLs so the fake-github.py test server and a real GITHUB_API_URL are reached the same way. The token is passed explicitly via -H so that non-github.com hosts (the test server, GitHub Enterprise Server) are authenticated the same way github.com is. The verbs check TokenFromEnv before constructing a GH, so a missing token is a clear early error rather than a gh diagnostic mid-run.
func NewGH ¶ added in v1.1.0
NewGH creates a Client that shells out to `gh api` against baseURL, authenticating with token.
func (*GH) AddIssueAssignees ¶ added in v1.1.0
func (*GH) AddIssueLabels ¶ added in v1.1.0
func (*GH) CreateIssueComment ¶ added in v1.1.0
func (*GH) GetAuthenticatedUser ¶ added in v1.1.0
func (*GH) GetIssueRaw ¶ added in v1.1.0
func (*GH) ListIssueComments ¶ added in v1.1.0
func (g *GH) ListIssueComments(owner, name string, number int) ([]IssueComment, error)
func (*GH) ListIssueCommentsRaw ¶ added in v1.1.0
func (*GH) ListOpenPulls ¶ added in v1.1.0
func (g *GH) ListOpenPulls(owner, name string) ([]PullRequest, error)
ListOpenPulls is GET /repos/{owner}/{name}/pulls?state=open, one page of 100 — the 101st open pull request is not read.
func (*GH) RemoveIssueAssignees ¶ added in v1.1.0
type Issue ¶
type Issue struct {
Number int `json:"number"`
Title string `json:"title"`
Body string `json:"body"`
State string `json:"state"`
Labels []Label `json:"labels"`
User User `json:"user"`
Assignees []User `json:"assignees"`
PullRequest *struct {
URL string `json:"url"`
} `json:"pull_request"`
}
Issue is an issue — or a pull request, which the issues endpoint also answers for: PullRequest is non-nil exactly when the "issue" is one.
type IssueComment ¶
type IssueComment struct {
User User `json:"user"`
CreatedAt string `json:"created_at"`
Body string `json:"body"`
}
IssueComment is one comment on an issue.
type Label ¶
type Label struct {
Name string `json:"name"`
Color string `json:"color,omitempty"`
Description string `json:"description,omitempty"`
}
Label is a repository label, as an issue carries it.
type PullRequest ¶
type PullRequest struct {
Number int `json:"number"`
Head struct {
Ref string `json:"ref"`
} `json:"head"`
}
PullRequest is the part of a pull request the gate reads: its number and the branch it comes from.