Documentation
¶
Overview ¶
Package gh wraps the GitHub REST and GraphQL APIs for syncing issues, PRs, and project items.
Index ¶
- func ParseGitHubURL(gitHubURL string) (owner, name, typ string, number int, err error)
- func QueryWithRetry(ctx context.Context, client *githubv4.Client, q any, variables map[string]any) error
- type ClosingIssue
- type ItemValueType
- type PRApproval
- type Project
- func (p *Project) AddItem(nodeID string) (*string, error)
- func (p *Project) GetItemFieldValuesByNodeID(contentNodeID string, fieldNames []string) (map[string]ProjectItemFieldValue, error)
- func (p *Project) GetItems() ([]ProjectItem, error)
- func (p *Project) HasItem(nodeID string) (*string, error)
- func (p *Project) LoadDetails() error
- func (p *Project) SetItemStatus(itemID, status string) error
- func (p *Project) UpdateItem(itemID string, fields []ProjectItemField) error
- type ProjectDetails
- type ProjectDetailsResult
- type ProjectItem
- type ProjectItemField
- type ProjectItemFieldValue
- type ProjectItemsResult
- type PullRequest
- type Rate
- type RateLimits
- type Repo
- func (r Repo) GetAllIssueEvents(number int) (*[]github.Timeline, error)
- func (r Repo) GetAllIssues(state string) (*[]github.Issue, error)
- func (r Repo) GetAllPullRequests(state string) (*[]github.PullRequest, error)
- func (r Repo) GetAllPullRequestsGQL(states, reviewers []string, limit int, mergedSince *time.Time, ...) (*[]PullRequest, error)
- func (r Repo) GetIssue(number int) (*github.Issue, error)
- func (r Repo) GetLabelsFor(number int) (*[]string, error)
- func (r Repo) GetPullRequest(pr int) (*github.PullRequest, error)
- func (r Repo) GetPullRequestMergeStatus(number int) (mergeable, checkState string, err error)
- func (r Repo) GetPullRequestReviewComments(pr int) ([]*github.PullRequestComment, error)
- func (r Repo) GetPullRequestReviews(pr int) ([]*github.PullRequestReview, error)
- func (r Repo) ListAllIssueEvents(number int, cb func([]*github.Timeline, *github.Response) error) error
- func (r Repo) ListAllIssues(state string, cb func([]*github.Issue, *github.Response) error) error
- func (r Repo) ListAllPullRequests(state string, cb func([]*github.PullRequest, *github.Response) error) error
- func (r Repo) PRReviewDecision(pr int) (*string, error)
- func (r Repo) PrURL(pr int) string
- type ReviewerCommentCount
- type Token
- func (t Token) GraphQLQuery(query string, params [][]string) (*string, error)
- func (t Token) GraphQLQueryUnmarshal(query string, params [][]string, data any) error
- func (t Token) NewClient() (*github.Client, context.Context)
- func (t Token) NewGraphQLClient() (*githubv4.Client, context.Context, error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ParseGitHubURL ¶
ParseGitHubURL parses a GitHub PR/Issue URL and returns the owner, repo name, type, and number.
func QueryWithRetry ¶ added in v0.2.0
func QueryWithRetry(ctx context.Context, client *githubv4.Client, q any, variables map[string]any) error
QueryWithRetry runs a githubv4 query, retrying transient network errors. The retryablehttp transport only guards the round-trip itself; errors while reading the response body (e.g. http2 stream resets mid-body: "stream error: stream ID N; CANCEL") surface here instead, so they need their own retry loop.
Types ¶
type ClosingIssue ¶
type ItemValueType ¶
type ItemValueType int
ItemValueType is the type of a project item field value (text, number, single select, or date).
const ( ItemValueTypeText ItemValueType = iota ItemValueTypeNumber ItemValueTypeSingleSelect ItemValueTypeDate )
func (ItemValueType) String ¶
func (t ItemValueType) String() string
type PRApproval ¶
type Project ¶
type Project struct {
Owner string
Number int
Token
*ProjectDetails
}
func (*Project) GetItemFieldValuesByNodeID ¶
func (p *Project) GetItemFieldValuesByNodeID(contentNodeID string, fieldNames []string) (map[string]ProjectItemFieldValue, error)
GetItemFieldValuesByNodeID looks up the project item for a given content node ID (e.g. an issue) and returns the field values for the requested field names. The returned map is keyed by field name. If the item is not found in the project, returns nil map with no error.
func (*Project) GetItems ¶
func (p *Project) GetItems() ([]ProjectItem, error)
GetItems returns all items in the project. todo: allow configure the fields we want to get
func (*Project) HasItem ¶
HasItem checks whether a given content node (issue or PR) is already in this project. Returns the project item ID if found, nil if not found.
func (*Project) LoadDetails ¶
func (*Project) SetItemStatus ¶
func (*Project) UpdateItem ¶
func (p *Project) UpdateItem(itemID string, fields []ProjectItemField) error
UpdateItem updates the fields of a project item by building a dynamic GraphQL mutation.
type ProjectDetails ¶
type ProjectDetails struct {
ID string
Fields []struct {
ID string
Name string
Options []struct {
ID string
Name string
}
}
FieldIDs map[string]string
StatusIDs map[string]string
FieldTypes map[string]ItemValueType // field name -> type
SingleSelectOptionIDs map[string]map[string]string // field name -> option name -> option ID
SingleSelectOptionNames map[string]map[string]string // field name -> option ID -> option name
}
type ProjectDetailsResult ¶
type ProjectDetailsResult struct {
Data struct {
Organization struct {
ProjectV2 struct {
ID string `json:"id"`
Fields struct {
Nodes []struct {
ID string `json:"id"`
Name string `json:"name"`
Options []struct {
ID string `json:"id"`
Name string `json:"name"`
} `json:"options"`
} `json:"nodes"`
} `json:"fields"`
} `json:"projectV2"`
} `json:"organization"`
} `json:"data"`
}
type ProjectItem ¶
type ProjectItemField ¶
type ProjectItemField struct {
Name string // A short name for this field (used in GraphQL alias, e.g. "set_key")
FieldID string // The GraphQL ID of the field
Type ItemValueType
Value any
}
ProjectItemField represents a single field update for the project item. Type should be either "text" or "number".
type ProjectItemFieldValue ¶
type ProjectItemFieldValue struct {
Type ItemValueType
Value any // string for text/date/singleSelect option ID, float64 for number
}
ProjectItemFieldValue holds a field value read from a project item.
type ProjectItemsResult ¶
type ProjectItemsResult struct {
Data struct {
Organization struct {
ProjectV2 struct {
ID string `json:"id"`
Items struct {
PageInfo struct {
HasNextPage bool `json:"hasNextPage"`
EndCursor string `json:"endCursor"`
} `json:"pageInfo"`
Nodes []struct {
ID string `json:"id"`
Type string `json:"type"`
Status *struct {
SingleSelectOptionID string `json:"singleSelectOptionId"`
}
RequestType *struct {
Text string `json:"text"`
} `json:"requestType"`
DueDate *struct {
Date string `json:"date"`
} `json:"dueDate"`
FieldValues struct {
Nodes []struct {
Typename string `json:"__typename"`
Text string `json:"text"`
Number float64 `json:"number"`
Date string `json:"date"`
SingleSelectOptionID string `json:"singleSelectOptionId"`
Field struct {
Name string `json:"name"`
} `json:"field"`
} `json:"nodes"`
} `json:"fieldValues"`
Content struct {
ID string `json:"id"`
Title string `json:"title"`
URL string `json:"url"`
} `json:"content"`
} `json:"nodes"`
} `json:"items"`
} `json:"projectV2"`
} `json:"organization"`
} `json:"data"`
}
ProjectItemsResult is the result of the project items query; for now we hard code the project fields we want (dueDate and type). TODO in the future we can make this configurable / get all of them
type PullRequest ¶
type PullRequest struct {
NodeID string
Author string
Number int
Title string
State string
ReviewDecision string
CreatedAt time.Time
UpdatedAt time.Time
ClosedAt time.Time
MergedAt time.Time
MergedBy string
ReviewedAt time.Time // when the most recent submitted review (any state except pending) was left, zero when unreviewed
LastReviewer string // who left that review
Draft bool
Milestone string
Mergeable string // MERGEABLE, CONFLICTING, or UNKNOWN (github may still be computing)
CheckState string // combined CI state of the head commit: SUCCESS, FAILURE, ERROR, PENDING, EXPECTED, or "" when the PR has no checks
TotalCommentCount int
TotalReviewCount int
ReviewCommentCount int
FilteredReviewCount int
FilteredReviewCommentCount int
ClosingIssues []ClosingIssue
Assignees []string
ReviewedBy []string // left a changes requested, commented, or dismissed review
ApprovedBy []string // left an approving review
ChangesRequestedBy []ReviewerCommentCount // requested changes, ordered by first request, with comment totals across all their change requests
AssociatedLabels map[string]bool
AssociatedProjectNumbers map[int]bool
}
type RateLimits ¶
type RateLimits struct {
Core Rate
GraphQL Rate
Search Rate
SourceImport Rate
IntegrationManifest Rate
CodeScanning Rate // code_scanning_upload
ActionsRunnerRegistration Rate
Scim Rate
// "rate" (alias for core)
Rate Rate
// Any new/unknown buckets GitHub adds in the future
Other map[string]Rate
}
RateLimits is the flat set of rate limit buckets, without the "resources" nesting of the API response.
func GetRateLimit ¶
func GetRateLimit(ctx context.Context, token string) (*RateLimits, error)
type Repo ¶
func NewRepoOwnerName ¶
func (Repo) GetAllIssueEvents ¶
func (Repo) GetAllPullRequests ¶
func (r Repo) GetAllPullRequests(state string) (*[]github.PullRequest, error)
func (Repo) GetAllPullRequestsGQL ¶
func (r Repo) GetAllPullRequestsGQL(states, reviewers []string, limit int, mergedSince *time.Time, progress func(int)) (*[]PullRequest, error)
GetAllPullRequestsGQL retrieves all pull requests matching the given states. If mergedSince is set only PRs merged at or after that time are returned, and pagination walks PRs by most recently updated so it can stop once it reaches PRs untouched since then (a PR's updatedAt is always >= its mergedAt).
func (Repo) GetPullRequest ¶
func (r Repo) GetPullRequest(pr int) (*github.PullRequest, error)
func (Repo) GetPullRequestMergeStatus ¶ added in v0.2.0
GetPullRequestMergeStatus returns a single PR's mergeable state (MERGEABLE/CONFLICTING/UNKNOWN) and the combined CI state of its head commit (SUCCESS/FAILURE/ERROR/PENDING/EXPECTED, or "" when the PR has no checks). While github reports UNKNOWN it retries for a bit, as the query itself triggers the async mergeability computation; UNKNOWN is returned only if it never settles.
func (Repo) GetPullRequestReviewComments ¶ added in v0.2.0
func (r Repo) GetPullRequestReviewComments(pr int) ([]*github.PullRequestComment, error)
GetPullRequestReviewComments returns all review (inline) comments for a PR; each carries the ID of the review it was submitted with in PullRequestReviewID.
func (Repo) GetPullRequestReviews ¶ added in v0.2.0
func (r Repo) GetPullRequestReviews(pr int) ([]*github.PullRequestReview, error)
GetPullRequestReviews returns all reviews for a PR in submission order (oldest first).
func (Repo) ListAllIssueEvents ¶
func (Repo) ListAllIssues ¶
func (Repo) ListAllPullRequests ¶
type ReviewerCommentCount ¶ added in v0.2.0
ReviewerCommentCount pairs a reviewer login with how many reviews of a given state they left (e.g. changes requested) and the total number of review comments across those reviews.
type Token ¶
type Token struct {
Token *string
}