Documentation
¶
Overview ¶
Package github binds GitHub in as a target-system plugin (the same pattern as the gitlab package): a REST client for the agent actions, an optional webhook intake (HMAC-SHA256) and the polling checks that carry the review loop. The unit of work is the issue.
One difference to GitLab runs through everything: a repository is addressed by its NAME ("owner/repo"), not by a numeric id. That is GitHub's natural identifier — it stands in every URL the agent reads, so it does not have to look an id up first.
Index ¶
- func IssueCorrelationKey(repo string, number int) string
- func PullCorrelationKey(repo string, number int) string
- func VerifySignature(secret string, body []byte, header string) bool
- type Branch
- type CheckRun
- type CheckoutResult
- type Client
- func (c *Client) AddAssignees(ctx context.Context, repo string, number int, logins []string) (Issue, error)
- func (c *Client) ApprovePull(ctx context.Context, repo string, number int, body string) (Comment, error)
- func (c *Client) Comment(ctx context.Context, repo string, number int, body string) (Comment, error)
- func (c *Client) CreateIssue(ctx context.Context, repo, title, body string, labels, assignees []string) (Issue, error)
- func (c *Client) CreatePull(ctx context.Context, repo, head, base, title, body string, draft bool) (PullRequest, error)
- func (c *Client) CurrentUser(ctx context.Context) (User, error)
- func (c *Client) DownloadTarball(ctx context.Context, repo, ref string) (io.ReadCloser, error)
- func (c *Client) Escalate(ctx context.Context, repo string, number int, note string) error
- func (c *Client) GetCommitDiff(ctx context.Context, repo, sha string) ([]CommitDiff, error)
- func (c *Client) GetIssue(ctx context.Context, repo string, number int) (Issue, error)
- func (c *Client) GetJobLog(ctx context.Context, repo string, jobID int64) (string, bool, error)
- func (c *Client) GetPull(ctx context.Context, repo string, number int) (PullRequest, error)
- func (c *Client) GetRepo(ctx context.Context, repo string) (Repo, error)
- func (c *Client) ListBranches(ctx context.Context, repo, search string) ([]Branch, error)
- func (c *Client) ListCheckRuns(ctx context.Context, repo, ref string) ([]CheckRun, error)
- func (c *Client) ListComments(ctx context.Context, repo string, number int) ([]Comment, error)
- func (c *Client) ListCommits(ctx context.Context, repo, ref, path, since string) ([]Commit, error)
- func (c *Client) ListIssues(ctx context.Context, repo, state, labels, search, milestone string, ...) ([]Issue, error)
- func (c *Client) ListMyOpenPulls(ctx context.Context) ([]Issue, error)
- func (c *Client) ListPullComments(ctx context.Context, repo string, number int) ([]Comment, error)
- func (c *Client) ListPulls(ctx context.Context, repo, state, search, base string) ([]PullRequest, error)
- func (c *Client) ListRepos(ctx context.Context) ([]Repo, error)
- func (c *Client) ListReviewPulls(ctx context.Context) ([]Issue, error)
- func (c *Client) ListRunJobs(ctx context.Context, repo string, runID int64) ([]Job, error)
- func (c *Client) ListTree(ctx context.Context, repo, path, ref string, recursive bool) ([]TreeEntry, error)
- func (c *Client) ListWorkflowRuns(ctx context.Context, repo, branch string) ([]WorkflowRun, error)
- func (c *Client) LookupUser(ctx context.Context, login string) (User, error)
- func (c *Client) ReadFile(ctx context.Context, repo, filePath, ref string) (content string, truncated bool, err error)
- func (c *Client) RequestChanges(ctx context.Context, repo string, number int, body string) (Comment, error)
- func (c *Client) RequestReviewers(ctx context.Context, repo string, number int, logins []string) (PullRequest, error)
- func (c *Client) RerunFailedJobs(ctx context.Context, repo string, runID int64) error
- func (c *Client) SetLabels(ctx context.Context, repo string, number int, add, remove []string) ([]string, error)
- func (c *Client) SetState(ctx context.Context, repo string, number int, state string) (Issue, error)
- type Comment
- type Commit
- type CommitDiff
- type CommitResult
- type DownloadAttachmentResult
- type Issue
- type Job
- type Label
- type PullRequest
- type Repo
- type System
- func (System) ActionSubject(action string, params json.RawMessage) string
- func (System) Execute(ctx context.Context, actionName string, params json.RawMessage, ...) (any, error)
- func (System) HasWork(ctx context.Context, cred target.Credential) (bool, error)
- func (System) HasWorkKind(ctx context.Context, cred target.Credential, kind string) (bool, error)
- func (System) HasWorkSigned(ctx context.Context, cred target.Credential, kind string) (bool, string, error)
- func (System) Name() string
- func (System) ParseWebhook(body []byte) (target.WebhookEvent, error)
- func (System) Probe(ctx context.Context, cred target.Credential) (string, error)
- func (System) PromptDoc() string
- func (System) VerifyWebhook(secret string, body []byte, header http.Header) bool
- type TreeEntry
- type User
- type WebhookPayload
- type WorkflowRun
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IssueCorrelationKey ¶
IssueCorrelationKey is the stable correlation key for an issue thread. A blocked task carries it and is woken by the matching comment.
func PullCorrelationKey ¶
PullCorrelationKey is the counterpart for a pull request thread.
func VerifySignature ¶
VerifySignature checks the HMAC-SHA256 signature from the X-Hub-Signature-256 header ("sha256=<hex>"). An empty secret = check disabled (dev only — an open endpoint lets anyone create tasks in a foreign org).
Types ¶
type Branch ¶
type Branch struct {
Name string `json:"name"`
Protected bool `json:"protected"`
Default bool `json:"default,omitempty"`
Commit struct {
SHA string `json:"sha"`
} `json:"commit"`
}
Branch is a branch with the head commit it points at.
type CheckRun ¶
type CheckRun struct {
Name string `json:"name"`
Status string `json:"status"`
Conclusion string `json:"conclusion"`
HTMLURL string `json:"html_url"`
}
CheckRun is a check on a commit — GitHub Actions writes them, and so does every external CI hanging off the Checks API. get_pull reports them, because the mergeability alone does not say whether the tests are green.
type CheckoutResult ¶
type CheckoutResult struct {
Path string `json:"path"`
Repo string `json:"repo"`
Ref string `json:"ref,omitempty"`
Files int `json:"files"`
Hint string `json:"hint"`
}
CheckoutResult is the answer of the checkout action to the agent: where the code lies and how it goes on working with it.
func Checkout ¶
Checkout materialises a repository's source in the sandbox: it downloads the archive through the API (the brokered token stays in the daemon, it never lands in the file system — unlike with a git clone using a credential remote) and unpacks it under <workdir>/repos/. An existing state of the same repository/ref is replaced — the agent always works on the current code.
Unlike GitLab, GitHub's archive endpoint knows no sub-path: the tarball always carries the whole repository. A repo too large for the sandbox is therefore not narrowed here but read selectively through list_tree/read_file; the error message says so.
type Client ¶
Client speaks the GitHub REST API with a (brokered) token. The token comes from the SecretStore per call — it is never persisted.
func NewClient ¶
NewClient normalises the endpoint. Three spellings arrive here and all three have to work, because whoever enters github_url takes it from their browser:
"" → https://api.github.com (github.com) https://ghe.example.com → https://ghe.example.com/api/v3 (Enterprise) https://ghe.example.com/api/v3 → taken as it stands
The rule is deliberately mechanical: an address that does not already carry an API path and whose host is not an "api." host gets GitHub Enterprise Server's /api/v3 appended.
func (*Client) AddAssignees ¶
func (c *Client) AddAssignees(ctx context.Context, repo string, number int, logins []string) (Issue, error)
AddAssignees — POST …/issues/{number}/assignees. GitHub adds; it does not replace. That is what the action wants: a handover names an additional person, it does not wipe the existing assignment.
func (*Client) ApprovePull ¶
func (c *Client) ApprovePull(ctx context.Context, repo string, number int, body string) (Comment, error)
ApprovePull — POST …/pulls/{number}/reviews with event=APPROVE: the formal green signal of a reviewer. The merging itself stays with a human.
func (*Client) Comment ¶
func (c *Client) Comment(ctx context.Context, repo string, number int, body string) (Comment, error)
Comment — POST …/issues/{number}/comments. GitHub knows no internal comments: every contribution is visible to whoever can see the repository. The plugin says so instead of pretending to an "internal" that does not exist.
func (*Client) CreateIssue ¶
func (c *Client) CreateIssue(ctx context.Context, repo, title, body string, labels, assignees []string) (Issue, error)
CreateIssue — POST /repos/{owner}/{repo}/issues.
func (*Client) CreatePull ¶
func (c *Client) CreatePull(ctx context.Context, repo, head, base, title, body string, draft bool) (PullRequest, error)
CreatePull — POST …/pulls. head is the source branch, base the target.
func (*Client) CurrentUser ¶
CurrentUser — GET /user: the bot's own identity. Needed everywhere a decision hangs off "did I write that myself?".
func (*Client) DownloadTarball ¶
DownloadTarball — GET …/tarball/{ref}: the repository archive. GitHub redirects to codeload.github.com; Go follows and drops the Authorization header on the host change, which is right — the redirect target carries its own signature. Deliberately not routed through do(): the body is binary and can be large; the caller closes the reader.
func (*Client) Escalate ¶
Escalate posts a comment and hands the item back: the bot removes its OWN assignment so that a human takes the issue over. GitHub knows no internal comments, so the note is visible to whoever can see the repository — the prompt says so, and the agent phrases it accordingly.
func (*Client) GetCommitDiff ¶
GetCommitDiff — GET …/commits/{sha}: the commit with its file changes. Long patches are cut off; the flag says so, so that the agent does not read a half-diff as the whole truth.
func (*Client) GetJobLog ¶
GetJobLog — GET …/actions/jobs/{id}/logs: GitHub redirects to a signed blob URL, Go follows it. Returns the log's end plus a flag saying it was cut.
func (*Client) GetRepo ¶
GetRepo — GET /repos/{owner}/{repo}: needed above all for the default branch, which commit and create_pull_request fall back to.
func (*Client) ListBranches ¶
ListBranches — GET …/branches. search filters afterwards; GitHub's endpoint has no such parameter.
func (*Client) ListCheckRuns ¶
ListCheckRuns — GET …/commits/{ref}/check-runs.
func (*Client) ListComments ¶
ListComments — GET /repos/{owner}/{repo}/issues/{number}/comments. Works for pull requests too: to GitHub a PR is an issue with a branch attached, and its conversation runs through the same endpoint.
Fetched NEWEST first and turned round afterwards. The client does not page, and on a thread longer than perPage the natural (oldest-first) order would hand back the opening exchange and cut off the end — the very part every decision here hangs on ("who wrote last?", "has my question been answered?"). Losing the beginning of a long thread costs context; losing the end produces wrong answers.
func (*Client) ListCommits ¶
ListCommits — GET …/commits. All filters are optional: sha (branch/tag/SHA), path (only commits touching that file) and since (an ISO date).
func (*Client) ListIssues ¶
func (c *Client) ListIssues(ctx context.Context, repo, state, labels, search, milestone string, assigned bool) ([]Issue, error)
ListIssues finds issues — with repo through GET /repos/{owner}/{repo}/issues, without one (repo == "") through the global GET /issues, which returns the issues of every repository the token can see.
Two filters GitHub's list endpoint does not offer are applied here, on the answer: search (a substring of title/body) and milestone by TITLE — GitHub wants the milestone NUMBER, which differs per repository and which the agent therefore cannot know. Filtering afterwards keeps the parameter meaning the same as in the GitLab plugin.
Pull requests are sorted out: GitHub delivers them through the issue endpoints too, but they are worked on through the pull actions.
func (*Client) ListMyOpenPulls ¶
ListMyOpenPulls finds the PRs the bot opened itself, across repositories — GitHub offers no such list endpoint, so it goes through the search API. The PRs come back thin (search returns issue objects); the caller fetches what it needs in detail.
func (*Client) ListPullComments ¶
ListPullComments merges a PR's whole conversation into one chronological list: the ordinary comments, the submitted reviews (with their verdict) and the review comments on lines of the diff. GitHub keeps the three apart; to the agent they are one thread, and a review that only appears in one of the three lists is feedback it would otherwise miss.
func (*Client) ListPulls ¶
func (c *Client) ListPulls(ctx context.Context, repo, state, search, base string) ([]PullRequest, error)
ListPulls — GET …/pulls. state accepts GitLab's vocabulary too; search and base filter afterwards.
func (*Client) ListRepos ¶
ListRepos — GET /user/repos: the repositories the bot user can reach. The entry point for agents that do not yet know their repo names.
func (*Client) ListReviewPulls ¶
ListReviewPulls finds the PRs in which the bot is entered as reviewer — the QA/test agent's working set.
func (*Client) ListRunJobs ¶
ListRunJobs — GET …/actions/runs/{id}/jobs.
func (*Client) ListTree ¶
func (c *Client) ListTree(ctx context.Context, repo, path, ref string, recursive bool) ([]TreeEntry, error)
ListTree lists the repository tree. Two routes, because GitHub splits the job: non-recursively the contents API (one directory), recursively the git trees API filtered by the path prefix. Both are capped at perPage entries — a whole tree does not belong in an agent's context.
func (*Client) ListWorkflowRuns ¶
ListWorkflowRuns — GET …/actions/runs, optionally narrowed to one branch.
func (*Client) LookupUser ¶
LookupUser — GET /users/{login}: checks that a login exists before it is entered as an assignee or reviewer. GitHub silently swallows an unknown assignee (the request succeeds, the assignment does not happen) — that is the kind of failure that only shows up days later.
func (*Client) ReadFile ¶
func (c *Client) ReadFile(ctx context.Context, repo, filePath, ref string) (content string, truncated bool, err error)
ReadFile — GET …/contents/{path}: a single file's content. GitHub delivers it base64-encoded; large files come back without content and need the blob API, which is deliberately not taken here — that size belongs in a checkout.
func (*Client) RequestChanges ¶
func (c *Client) RequestChanges(ctx context.Context, repo string, number int, body string) (Comment, error)
RequestChanges — POST …/pulls/{number}/reviews with event=REQUEST_CHANGES: the reviewer's counterpart to the approval. GitHub blocks the merge with it where the branch protection demands a review, so a defect found does not only stand in a comment but actually holds the PR up.
func (*Client) RequestReviewers ¶
func (c *Client) RequestReviewers(ctx context.Context, repo string, number int, logins []string) (PullRequest, error)
RequestReviewers — POST …/pulls/{number}/requested_reviewers.
func (*Client) RerunFailedJobs ¶
RerunFailedJobs — POST …/actions/runs/{id}/rerun-failed-jobs: starts the failed jobs of a run afresh. For a red pipeline whose cause lay outside the change (a runner missing, a registry down) and has been fixed since.
func (*Client) SetLabels ¶
func (c *Client) SetLabels(ctx context.Context, repo string, number int, add, remove []string) ([]string, error)
SetLabels works additively/subtractively instead of overwriting the whole list — otherwise every state change takes the subject-matter labels with it. GitHub has one endpoint per direction, so this is two calls at most.
type Comment ¶
type Comment struct {
ID int64 `json:"id"`
Kind string `json:"kind,omitempty"` // comment | review | review_comment
Body string `json:"body"`
User User `json:"user"`
CreatedAt string `json:"created_at"`
HTMLURL string `json:"html_url"`
// State carries a review's verdict (APPROVED, CHANGES_REQUESTED,
// COMMENTED); empty for ordinary comments.
State string `json:"state,omitempty"`
// Path/Line locate a review comment in the diff.
Path string `json:"path,omitempty"`
Line int `json:"line,omitempty"`
// SubmittedAt is a review's timestamp; normalised into CreatedAt.
SubmittedAt string `json:"submitted_at,omitempty"`
}
Comment is a contribution to an issue or pull request. GitHub keeps three kinds apart that mean the same thing to the agent — an issue comment, a review (with a verdict) and a review comment on a line of the diff. The plugin merges them into ONE chronological list; Kind says where the entry comes from.
type Commit ¶
type Commit struct {
SHA string `json:"sha"`
Commit struct {
Message string `json:"message"`
Author struct {
Name string `json:"name"`
Date string `json:"date"`
} `json:"author"`
} `json:"commit"`
HTMLURL string `json:"html_url"`
}
Commit is an entry of the commit history.
type CommitDiff ¶
type CommitDiff struct {
Filename string `json:"filename"`
Status string `json:"status"`
Additions int `json:"additions"`
Deletions int `json:"deletions"`
Patch string `json:"patch,omitempty"`
Truncated bool `json:"truncated,omitempty"`
}
CommitDiff is one file's change within a commit.
type CommitResult ¶
type CommitResult struct {
Repo string `json:"repo"`
Branch string `json:"branch"`
BranchCreated bool `json:"branch_created"`
Commit Commit `json:"commit"`
Files []string `json:"files"`
Deleted []string `json:"deleted,omitempty"`
Hint string `json:"hint"`
}
CommitResult is the answer of the commit action: what was pushed and how things continue (opening a pull request).
func CommitFromCheckout ¶
func CommitFromCheckout(ctx context.Context, gc *Client, repo, branch, startBranch, message, checkoutPath string, files, deleted []string, workdir string) (CommitResult, error)
CommitFromCheckout pushes locally edited files from the sandbox checkout as ONE commit onto a feature branch — through the Git Data API (see gitdata.go), so that the brokered token stays in the daemon (no git remote with credentials in the sandbox). If the branch does not exist yet, it is branched off the start branch (default: the repository's default branch). Direct commits onto the default branch are forbidden fail-closed — the route into the main branch leads exclusively through a pull request.
type DownloadAttachmentResult ¶
type DownloadAttachmentResult struct {
Path string `json:"path"`
Filename string `json:"filename"`
ContentType string `json:"content_type,omitempty"`
Bytes int64 `json:"bytes"`
Hint string `json:"hint"`
}
DownloadAttachmentResult is the answer of the download_attachment action: where the image lies in the sandbox and how the agent looks at it.
func DownloadAttachmentToSandbox ¶
func DownloadAttachmentToSandbox(ctx context.Context, gc *Client, rawURL, workdir string) (DownloadAttachmentResult, error)
DownloadAttachmentToSandbox fetches an image attached to an issue/PR into the sandbox in brokered fashion — the token stays in the daemon, the file lands under <workdir>/uploads/. The agent then reads it with the Read tool (vision) and can actually look at the screenshot.
GitHub redirects attachment links to signed storage URLs. Go drops the Authorization header on the host change, which is right: the redirect target carries its own signature and would refuse a foreign token.
type Issue ¶
type Issue struct {
Repo string `json:"repo"`
Number int `json:"number"`
Title string `json:"title"`
Body string `json:"body"`
State string `json:"state"`
Labels []Label `json:"labels"`
HTMLURL string `json:"html_url"`
User User `json:"user"`
Assignees []User `json:"assignees"`
// Milestone attaches the issue to an undertaking (a release, a sprint).
// GitHub returns null when there is none.
Milestone *struct {
Title string `json:"title"`
DueOn string `json:"due_on"`
State string `json:"state"`
} `json:"milestone"`
Comments int `json:"comments"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
// PullRequest is set by GitHub when this "issue" is in fact a PR.
PullRequest *struct {
HTMLURL string `json:"html_url"`
} `json:"pull_request,omitempty"`
// Repository comes back from the global GET /issues only; for the
// repository endpoint the plugin fills Repo in itself.
Repository *struct {
FullName string `json:"full_name"`
} `json:"repository,omitempty"`
}
Issue is an issue. GitHub also lists pull requests through the issue endpoints — PullRequest != nil marks exactly that case, and the plugin sorts those out (a PR is worked on through the pull actions).
func (Issue) IsPullRequest ¶
IsPullRequest reports whether an entry from an issue list is in truth a pull request.
type Job ¶
type Job struct {
ID int64 `json:"id"`
Name string `json:"name"`
Status string `json:"status"`
Conclusion string `json:"conclusion"`
HTMLURL string `json:"html_url"`
StartedAt string `json:"started_at"`
}
Job is one job of a workflow run.
type Label ¶
type Label struct {
Name string `json:"name"`
}
Label carries the name only; colour and description do not belong in the agent's context.
type PullRequest ¶
type PullRequest struct {
Repo string `json:"repo"`
Number int `json:"number"`
Title string `json:"title"`
Body string `json:"body"`
State string `json:"state"` // open | closed
Draft bool `json:"draft"`
// Merged comes back from the single-PR endpoint only. MergedAt is in the
// list answer too, so a "merged" filter over a list costs no extra request
// per entry — which at 100 hits is the difference between one request and
// a hundred.
Merged bool `json:"merged"`
MergedAt string `json:"merged_at,omitempty"`
HTMLURL string `json:"html_url"`
User User `json:"user"`
Head struct {
Ref string `json:"ref"`
SHA string `json:"sha"`
} `json:"head"`
Base struct {
Ref string `json:"ref"`
} `json:"base"`
Assignees []User `json:"assignees"`
RequestedReviewers []User `json:"requested_reviewers"`
// Mergeable/MergeableState are GitHub's review state. Mergeable is null
// while GitHub is still computing the merge — a fact the agent has to see,
// hence the pointer.
Mergeable *bool `json:"mergeable"`
MergeableState string `json:"mergeable_state,omitempty"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
PullRequest is a pull request — GitHub's counterpart to the merge request.
type Repo ¶
type Repo struct {
Full string `json:"repo"`
FullName string `json:"full_name"`
Description string `json:"description"`
HTMLURL string `json:"html_url"`
DefaultBranch string `json:"default_branch"`
Private bool `json:"private"`
Archived bool `json:"archived"`
Permissions struct {
Push bool `json:"push"`
} `json:"permissions"`
}
Repo is a repository. Full ("owner/name") is the identifier every action takes.
type System ¶
type System struct{}
System binds GitHub in as a target-system plugin to the target registry: the webhook entry (HMAC-verified, idempotent), the polling checks for the heartbeat, the agent actions and the action documentation for the system prompt.
func (System) ActionSubject ¶
func (System) ActionSubject(action string, params json.RawMessage) string
ActionSubject maps action+params onto the guard-rail subject. Unlike Zammad and GitLab there is no internal/external split: GitHub knows no internal comments, every contribution is visible to whoever can see the repository. The writing actions therefore each carry their own subject, so a rule can govern "may comment" and "may push" separately.
func (System) Execute ¶
func (System) Execute(ctx context.Context, actionName string, params json.RawMessage, cred target.Credential) (any, error)
func (System) HasWork ¶
HasWork (target.WorkChecker): the control plane's cheap pre-check for nur-wenn: heartbeats — it saves the (expensive) agent wake when there is nothing to do at the moment. Work is present when ONE of the following holds:
- There is an open issue in the intake scope on which the bot has not yet commented last.
- The bot has an open pull request it opened itself with unanswered review feedback. That carries the review loop.
What counts everywhere is the EDGE (has something happened since the bot's last move?), not the level (is anything open anywhere?) — otherwise the same unfinished item wakes the agent afresh in every interval.
func (System) HasWorkKind ¶
HasWorkKind (target.KindWorkChecker) gates a single kind of work so that several heartbeats fire separately:
- "issues"/"issue" → is ANY open issue in the intake scope waiting for a reaction?
- "issues:assigned"/"assigned" → is an open issue waiting that is ASSIGNED to the bot itself? Exactly that is what an agent needs whose playbook works only on its own issues.
- "pr"/"prs"/"mr" → is one of the PRs the bot opened ITSELF waiting for an answer (the author's view, the developer review loop)?
- "review"/"reviews" → is one of the PRs in which the bot is entered as REVIEWER waiting for its review (the QA/test view)?
- otherwise → both of HasWork, fail-open on an unknown scope.
func (System) HasWorkSigned ¶
func (System) HasWorkSigned(ctx context.Context, cred target.Credential, kind string) (bool, string, error)
HasWorkSigned (target.SignedWorkChecker) is the actual check: besides the yes/no it returns the signature of the waiting items so that the control plane does not wake twice on the same state. An agent may thereby end a run silently — the QA colleague's feedback was an approval, there is nothing to do — without being woken again in the next interval. If a new contribution or a push comes along, the signature changes and the agent wakes. Whether a piece of feedback means work (reported defects) or only information (an approval) is thus decided by the agent and not by the gate.
func (System) ParseWebhook ¶
func (System) ParseWebhook(body []byte) (target.WebhookEvent, error)
ParseWebhook (target.Webhooker) turns the payload into the wake event.
type TreeEntry ¶
type TreeEntry struct {
Path string `json:"path"`
Type string `json:"type"` // blob | tree
Size int `json:"size,omitempty"`
SHA string `json:"sha,omitempty"`
}
TreeEntry is one entry of the repository tree.
type User ¶
type User struct {
Login string `json:"login"`
Type string `json:"type"` // "User" | "Bot" | "Organization"
}
User is an account. Login is what every action expects as "username" — the numeric id plays no part in GitHub's API.
type WebhookPayload ¶
type WebhookPayload struct {
Action string `json:"action"`
Repository struct {
FullName string `json:"full_name"`
} `json:"repository"`
Sender User `json:"sender"`
Issue *struct {
Number int `json:"number"`
Title string `json:"title"`
Body string `json:"body"`
HTMLURL string `json:"html_url"`
User User `json:"user"`
PullRequest *struct {
HTMLURL string `json:"html_url"`
} `json:"pull_request,omitempty"`
} `json:"issue"`
PullRequest *struct {
Number int `json:"number"`
Title string `json:"title"`
HTMLURL string `json:"html_url"`
Merged bool `json:"merged"`
} `json:"pull_request"`
Comment *struct {
ID int64 `json:"id"`
Body string `json:"body"`
User User `json:"user"`
Path string `json:"path"`
} `json:"comment"`
Review *struct {
ID int64 `json:"id"`
Body string `json:"body"`
State string `json:"state"`
User User `json:"user"`
} `json:"review"`
}
WebhookPayload is the relevant excerpt of the GitHub webhook JSON. GitHub sends one shape per event type; the fields that do not belong to the event at hand stay nil.
func ParseWebhook ¶
func ParseWebhook(body []byte) (WebhookPayload, error)
ParseWebhook decodes the payload and rejects anything without a repository — every event Covey acts on carries one.
func (WebhookPayload) Event ¶
func (p WebhookPayload) Event() target.WebhookEvent
Event turns a payload into the wake event for the orchestrator. Anything not recognised answers with Wake=false: the delivery is registered (and thereby acknowledged) but changes nothing — GitHub sends whatever the hook was subscribed to, and an unknown shape is not a reason to invent work.
func (WebhookPayload) Kind ¶
func (p WebhookPayload) Kind() string
Kind derives the event kind from the payload shape (see the constants).
type WorkflowRun ¶
type WorkflowRun struct {
ID int64 `json:"id"`
Name string `json:"name"`
Status string `json:"status"` // queued | in_progress | completed
Conclusion string `json:"conclusion"` // success | failure | cancelled | …
HeadBranch string `json:"head_branch"`
HeadSHA string `json:"head_sha"`
Event string `json:"event"`
HTMLURL string `json:"html_url"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
WorkflowRun is a GitHub Actions run — the counterpart to the GitLab pipeline.