github

package
v1.1.2 Latest Latest
Warning

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

Go to latest
Published: Sep 12, 2026 License: MIT Imports: 9 Imported by: 0

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

View Source
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

func IssuePath(owner, name string, number int, rest string) string

IssuePath builds /repos/{owner}/{name}/issues/{number}[/rest], with owner and name path-escaped.

func Message added in v1.1.0

func Message(raw []byte) string

Message extracts the "message" field from a JSON error response, or "".

func ParseRemoteURL

func ParseRemoteURL(remote, host string) (owner, name string, err error)

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

func RepoPath(owner, name, rest string) string

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

func SplitRepository(s string) (owner, name string, err error)

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 Error

type Error struct {
	Method  string
	Path    string
	Status  int
	Message string
}

Error is GitHub saying no: the status it answered and the message it sent.

func (*Error) Error

func (e *Error) Error() string

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

func NewGH(baseURL, token string) *GH

NewGH creates a Client that shells out to `gh api` against baseURL, authenticating with token.

func (*GH) AddIssueAssignees added in v1.1.0

func (g *GH) AddIssueAssignees(owner, name string, number int, logins []string) error

func (*GH) AddIssueLabels added in v1.1.0

func (g *GH) AddIssueLabels(owner, name string, number int, labels []string) error

func (*GH) CreateIssueComment added in v1.1.0

func (g *GH) CreateIssueComment(owner, name string, number int, body string) error

func (*GH) GetAuthenticatedUser added in v1.1.0

func (g *GH) GetAuthenticatedUser() (*User, error)

func (*GH) GetIssue added in v1.1.0

func (g *GH) GetIssue(owner, name string, number int) (*Issue, error)

func (*GH) GetIssueRaw added in v1.1.0

func (g *GH) GetIssueRaw(owner, name string, number int) (json.RawMessage, error)

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 (g *GH) ListIssueCommentsRaw(owner, name string, number int) (json.RawMessage, error)

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

func (g *GH) RemoveIssueAssignees(owner, name string, number int, logins []string) error

func (*GH) RemoveIssueLabel added in v1.1.0

func (g *GH) RemoveIssueLabel(owner, name string, number int, label string) error

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.

type User

type User struct {
	Login string `json:"login"`
	Type  string `json:"type"`
}

User is an account: the author of an issue or comment, an assignee, or the token's owner.

Jump to

Keyboard shortcuts

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