Documentation
¶
Index ¶
- Constants
- Variables
- func ClassifyWriteError(err error) retry.Classification
- func IsUncertainWriteError(err error) bool
- func ParsePRURL(prURL string) (owner string, repo string, number int, err error)
- func ParseRepoOwner(repoFlag string) []string
- func SanitizeCommitHeadline(englishSummary, originalInstruction, shortSHA string) string
- func ValidateCommitOID(sha string) error
- type AppAuth
- func (a *AppAuth) CreatePushCredential(ctx context.Context, owner, repo string, repoID int64) (*PushCredential, error)
- func (a *AppAuth) CreateRetrievalCredential(ctx context.Context, owner, repo string, repoID int64) (*RetrievalCredential, error)
- func (a *AppAuth) GetServiceActor(ctx context.Context) (*ServiceActor, error)
- func (a *AppAuth) RevokePushCredential(ctx context.Context, cred *PushCredential) error
- func (a *AppAuth) RevokeRetrievalCredential(ctx context.Context, cred *RetrievalCredential) error
- type Client
- func NewAppClient(appID int64, privateKeyPath string) (*Client, error)
- func NewAppClientFromKey(appID int64, keyData []byte) (*Client, error)
- func NewClient(token string) *Client
- func NewClientFromConfig(cfg *config.Config) *Client
- func NewTestAppClient(baseURL string, appID int64, privateKey *rsa.PrivateKey) (*Client, error)
- func NewTestClient(baseURL string) (*Client, error)
- func NewTestClientWithToken(baseURL, token string) (*Client, error)
- func (c *Client) AddLabels(ctx context.Context, owner, repo string, number int, labels []string) error
- func (c *Client) AppAuth() *AppAuth
- func (c *Client) CanWriteRepository(ctx context.Context, owner, repo, username string) (bool, error)
- func (c *Client) CommitFileAtExpectedHead(ctx context.Context, ...) (string, error)
- func (c *Client) CommitFilesAtExpectedHead(ctx context.Context, ...) (string, error)
- func (c *Client) CreateComment(ctx context.Context, owner, repo string, number int, body string) (int64, error)
- func (c *Client) CreatePushCredential(ctx context.Context, owner, repo string, repoID int64) (*PushCredential, error)
- func (c *Client) CreateRetrievalCredential(ctx context.Context, owner, repo string, repoID int64) (*RetrievalCredential, error)
- func (c *Client) EditComment(ctx context.Context, owner, repo string, commentID int64, body string) error
- func (c *Client) FindOwnedComment(ctx context.Context, opts FindOwnedCommentOptions) (*OwnedCommentMatch, error)
- func (c *Client) GetBlob(ctx context.Context, owner, repo, sha string) (*github.Blob, error)
- func (c *Client) GetBlobRaw(ctx context.Context, owner, repo, sha string) ([]byte, error)
- func (c *Client) GetComment(ctx context.Context, owner, repo string, commentID int64) (*github.IssueComment, error)
- func (c *Client) GetComments(ctx context.Context, owner, repo string, number int) ([]Comment, []DiscussionThread, error)
- func (c *Client) GetCommit(ctx context.Context, owner, repo, sha string) (*github.RepositoryCommit, error)
- func (c *Client) GetDiffAtCommits(ctx context.Context, owner, repo, baseOID, headOID string) (string, error)
- func (c *Client) GetFileContent(ctx context.Context, owner, repo, path, ref string) (*FileContent, error)
- func (c *Client) GetLabels(ctx context.Context, owner, repo string, number int) ([]string, error)
- func (c *Client) GetPR(ctx context.Context, owner, repo string, number int) (*PRDetails, error)
- func (c *Client) GetRawDiff(ctx context.Context, owner, repo string, number int) (string, error)
- func (c *Client) GetRepoID(ctx context.Context, owner, repo string) (int64, error)
- func (c *Client) GetTree(ctx context.Context, owner, repo, sha string, recursive bool) (*github.Tree, error)
- func (c *Client) NewScopedClient(token string) *Client
- func (c *Client) PostComment(ctx context.Context, owner, repo string, number int, body string) error
- func (c *Client) PostDecisionReview(ctx context.Context, owner, repo string, number int, commitSHA string, ...) (*github.PullRequestReview, error)
- func (c *Client) PostSuggestions(ctx context.Context, owner, repo string, number int, commitSHA string, ...) error
- func (c *Client) RevokePushCredential(ctx context.Context, cred *PushCredential) error
- func (c *Client) RevokeRetrievalCredential(ctx context.Context, cred *RetrievalCredential) error
- func (c *Client) ServiceActor(ctx context.Context, owner, repo string) (*ServiceActor, error)
- func (c *Client) ServiceActorID(ctx context.Context, owner, repo string) (int64, error)
- func (c *Client) SetClock(clk retry.Clock)
- func (c *Client) SetGraphQLURL(u string)
- func (c *Client) SetRetryPolicy(p retry.Policy)
- func (c *Client) UpdateFile(ctx context.Context, owner, repo, path, branch, sha, content, message string) (string, error)
- func (c *Client) UpdatePRBody(ctx context.Context, owner, repo string, number int, body string) error
- type Comment
- type DecisionWriteError
- type DiscussionThread
- type FileContent
- type FindOwnedCommentOptions
- type HeadMovedError
- type InlineSuggestion
- type OwnedCommentMatch
- type PRDetails
- type PushCredential
- type RetrievalCredential
- type ServiceActor
Constants ¶
const ( // EventApprove represents GitHub review event APPROVE. EventApprove = "APPROVE" // EventRequestChanges represents GitHub review event REQUEST_CHANGES. EventRequestChanges = "REQUEST_CHANGES" )
Variables ¶
var ( ErrInvalidRepoID = errors.New("invalid or empty repository ID") ErrScopeTooBroad = errors.New("retrieval credential scope too broad or unverified") ErrServiceActorPermission = errors.New("service actor permission error") ErrServiceActorMalformed = errors.New("service actor response malformed") )
var ( // ErrHeadMoved indicates that the branch head moved away from expectedHeadOid. ErrHeadMoved = errors.New("branch head moved") // ErrInvalidCommitOID indicates that a commit SHA is not a 40- or 64-character hex string. ErrInvalidCommitOID = errors.New("commit SHA must be 40 or 64 hex characters (full OID required)") )
var ( // ErrInvalidDecisionEvent indicates that the decision event is not APPROVE or REQUEST_CHANGES. ErrInvalidDecisionEvent = errors.New("decision event must be APPROVE or REQUEST_CHANGES") // ErrMissingOwnerOrRepo indicates that owner or repo is empty. ErrMissingOwnerOrRepo = errors.New("owner and repo must not be empty") )
Functions ¶
func ClassifyWriteError ¶
func ClassifyWriteError(err error) retry.Classification
ClassifyWriteError classifies an error from a GitHub write operation (comment create/edit, label or body mutation) using the shared retry classifier. It is the write-path reconcile-first guard: callers must route ClassUncertainWrite outcomes to reconciliation/operator attention instead of blind POST retries, because the remote effect is unprovable.
func IsUncertainWriteError ¶
IsUncertainWriteError reports whether a write error has an unprovable remote outcome (timeout, lost response, ambiguous 5xx on POST).
func ParsePRURL ¶
ParsePRURL extracts owner, repo, and PR number from a standard GitHub PR URL Supports various URL formats: - https://github.com/owner/repo/pull/123 - http://github.com/owner/repo/pull/123 - https://github.com/owner/repo/pull/123/ - https://github.com/owner/repo/pull/123?query=params
func ParseRepoOwner ¶
ParseRepoOwner splits "owner/repo" into [owner, repo]
func SanitizeCommitHeadline ¶
SanitizeCommitHeadline builds the single bot-authored commit headline `pr-review: <english-summary> "<original>" (<short-sha>)`, capped at 140 chars on one line (D-32, D-35).
englishSummary is the caller-supplied English verdict summary (derived executor-side from the ClassifyEditIntent LLM session; this function never calls the LLM). originalInstruction is always quoted verbatim (TR preserved). When the summary is empty after whitespace-collapse, and only then, the TR-quote-only fallback `pr-review: "<original>" (<sha>)` is used. shortSHA must be 7 hex chars; anything else yields the 0000000 placeholder.
func ValidateCommitOID ¶
ValidateCommitOID ensures the commit hash is a full 40-char (SHA-1) or 64-char (SHA-256) hex string. Short prefixes, non-hex characters, and empty strings are rejected (SAFE-01, SAFE-03).
Types ¶
type AppAuth ¶
type AppAuth struct {
// contains filtered or unexported fields
}
AppAuth manages repository-scoped GitHub App installation authentication. It resolves installations per requested repository (rather than globally caching the first installation returned) and isolates token refreshes per owner/repo.
func (*AppAuth) CreatePushCredential ¶
func (a *AppAuth) CreatePushCredential(ctx context.Context, owner, repo string, repoID int64) (*PushCredential, error)
CreatePushCredential requests an uncached, short-lived GitHub App installation token restricted to exactly one head repository ID with contents:write permission (D-29). It verifies the returned token expiry, scope, and repository selection, rejecting broader or unverifiable credentials. It does not alter the cached review client tokens in a.repos.
func (*AppAuth) CreateRetrievalCredential ¶
func (a *AppAuth) CreateRetrievalCredential(ctx context.Context, owner, repo string, repoID int64) (*RetrievalCredential, error)
CreateRetrievalCredential requests an uncached, short-lived GitHub App installation token restricted to exactly one head repository ID with contents:read permission (D-10, SAFE-01). It verifies the returned token expiry, scope, and repository selection, rejecting broader or unverifiable credentials. It does not alter the cached review client tokens in a.repos.
func (*AppAuth) GetServiceActor ¶
func (a *AppAuth) GetServiceActor(ctx context.Context) (*ServiceActor, error)
func (*AppAuth) RevokePushCredential ¶
func (a *AppAuth) RevokePushCredential(ctx context.Context, cred *PushCredential) error
RevokePushCredential revokes the short-lived push installation access token via DELETE /installation/token and wipes the token string from memory (D-29). Zeroize runs deferred so memory wipes even on revoke failure.
func (*AppAuth) RevokeRetrievalCredential ¶
func (a *AppAuth) RevokeRetrievalCredential(ctx context.Context, cred *RetrievalCredential) error
RevokeRetrievalCredential revokes the short-lived installation access token via DELETE /installation/token and wipes the token string from memory (D-10, D-11).
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
func NewAppClientFromKey ¶
NewAppClientFromKey creates a GitHub App client from raw PEM private key bytes.
func NewClientFromConfig ¶
func NewTestAppClient ¶
NewTestAppClient creates an App-authenticated client pointed at a custom base URL for testing.
func NewTestClient ¶
NewTestClient creates a GitHub client pointed at a custom base URL for testing.
func NewTestClientWithToken ¶
NewTestClientWithToken creates a GitHub client pointed at a custom base URL with a static token for testing.
func (*Client) CanWriteRepository ¶
func (c *Client) CanWriteRepository(ctx context.Context, owner, repo, username string) (bool, error)
CanWriteRepository checks the comment author's current repository permission.
func (*Client) CommitFileAtExpectedHead ¶
func (c *Client) CommitFileAtExpectedHead(ctx context.Context, owner, repo, branch, expectedHeadOID, path, content, message string) (string, error)
CommitFileAtExpectedHead creates a single commit on branch containing only path with content, conditional on the branch head matching expectedHeadOID exactly, using GitHub GraphQL createCommitOnBranch (D-16, SAFE-03). If the branch head does not match expectedHeadOID, it maps the conflict to *HeadMovedError.
func (*Client) CommitFilesAtExpectedHead ¶
func (c *Client) CommitFilesAtExpectedHead(ctx context.Context, owner, repo, branchName, expectedHeadOID, messageHeadline string, files map[string]string, deletions []string) (string, error)
CommitFilesAtExpectedHead creates a single atomic commit on the caller-supplied PR head branch containing every entry of files plus every path in deletions, conditional on the branch head matching expectedHeadOID exactly, using one GitHub GraphQL createCommitOnBranch mutation (D-22, D-24, D-31).
The branch is used exactly as passed (modulo a refs/heads/ prefix strip); this function never substitutes main or any other branch, and fork refusal plus branch selection stay executor-side. Exactly one HTTP mutation runs per call: no REST fallback, no retry on head-moved. Head-moved conflicts map to *HeadMovedError; 403/permission rejections surface as explanatory errors for the executor to relay as comments (D-25), never bypasses.
func (*Client) CreateComment ¶
func (c *Client) CreateComment(ctx context.Context, owner, repo string, number int, body string) (int64, error)
CreateComment creates a comment on an issue or pull request and returns its numeric ID.
func (*Client) CreatePushCredential ¶
func (c *Client) CreatePushCredential(ctx context.Context, owner, repo string, repoID int64) (*PushCredential, error)
CreatePushCredential creates a short-lived App token scoped to exactly one head repository with contents:write permission. If the client is configured with a PAT instead of a GitHub App, it returns ErrPushAuthUnavailable; broad PAT substitution is explicitly denied (D-29).
func (*Client) CreateRetrievalCredential ¶
func (c *Client) CreateRetrievalCredential(ctx context.Context, owner, repo string, repoID int64) (*RetrievalCredential, error)
CreateRetrievalCredential creates a short-lived App token scoped to exactly one head repository with contents:read permission. If the client is configured with a PAT instead of a GitHub App, it returns ErrRetrievalAuthUnavailable; broad PAT substitution is explicitly denied (D-10, SAFE-01).
func (*Client) EditComment ¶
func (c *Client) EditComment(ctx context.Context, owner, repo string, commentID int64, body string) error
EditComment updates an existing issue or pull request comment by its numeric ID.
func (*Client) FindOwnedComment ¶
func (c *Client) FindOwnedComment(ctx context.Context, opts FindOwnedCommentOptions) (*OwnedCommentMatch, error)
FindOwnedComment scans pull request issue comments for a comment matching the verified service actor, stable marker, and optional body digest. Uses pagination (100/page, maximum 20 pages). An incomplete or failed scan yields uncertain, never an absent verdict. Copied markers from ordinary users are ignored.
func (*Client) GetBlobRaw ¶
GetBlobRaw retrieves raw bytes of a git blob by SHA.
func (*Client) GetComment ¶
func (c *Client) GetComment(ctx context.Context, owner, repo string, commentID int64) (*github.IssueComment, error)
GetComment retrieves an existing issue or pull request comment by its numeric ID.
func (*Client) GetComments ¶
func (*Client) GetCommit ¶
func (c *Client) GetCommit(ctx context.Context, owner, repo, sha string) (*github.RepositoryCommit, error)
GetCommit retrieves a commit by full SHA from the repository.
func (*Client) GetDiffAtCommits ¶
func (c *Client) GetDiffAtCommits(ctx context.Context, owner, repo, baseOID, headOID string) (string, error)
GetDiffAtCommits retrieves the diff between baseOID and headOID using the GitHub commit comparison endpoint. It requires complete 40 or 64 hex character OIDs (SAFE-03) and sends the GitHub diff media type. Never generates from the mutable PR diff endpoint to prevent ABA head movement risks (D-16).
func (*Client) GetFileContent ¶
func (*Client) GetRawDiff ¶
func (*Client) GetTree ¶
func (c *Client) GetTree(ctx context.Context, owner, repo, sha string, recursive bool) (*github.Tree, error)
GetTree retrieves a git tree by SHA, optionally recursive.
func (*Client) NewScopedClient ¶
NewScopedClient returns a new Client configured with the provided access token while preserving custom BaseURL if set on this client.
func (*Client) PostComment ¶
func (*Client) PostDecisionReview ¶
func (c *Client) PostDecisionReview(ctx context.Context, owner, repo string, number int, commitSHA string, event string, body string, suggestions []InlineSuggestion) (*github.PullRequestReview, error)
PostDecisionReview creates ONE review with event APPROVE or REQUEST_CHANGES containing summary body, inline comments, and bound to the exact commit SHA (D-02, D-15).
func (*Client) PostSuggestions ¶
func (c *Client) PostSuggestions(ctx context.Context, owner, repo string, number int, commitSHA string, suggestions []InlineSuggestion) error
PostSuggestions creates one COMMENT review containing inline GitHub suggestion blocks.
func (*Client) RevokePushCredential ¶
func (c *Client) RevokePushCredential(ctx context.Context, cred *PushCredential) error
RevokePushCredential revokes the scoped App push token and zeroes it in memory.
func (*Client) RevokeRetrievalCredential ¶
func (c *Client) RevokeRetrievalCredential(ctx context.Context, cred *RetrievalCredential) error
RevokeRetrievalCredential revokes the scoped App retrieval token and zeroes it in memory.
func (*Client) ServiceActor ¶
ServiceActor returns the authenticated user or bot identity of the service.
func (*Client) ServiceActorID ¶
ServiceActorID returns the numeric user/bot ID of the authenticated service actor.
func (*Client) SetGraphQLURL ¶
SetGraphQLURL sets an explicit GraphQL endpoint override (for testing or custom enterprise setups).
func (*Client) SetRetryPolicy ¶
SetRetryPolicy customizes retry policy for GitHub read operations.
type Comment ¶
type Comment struct {
ID int64 `json:"id"`
User string `json:"user"`
Body string `json:"body"`
CreatedAt time.Time `json:"created_at"`
// Inline review comment specific fields
Path string `json:"path,omitempty"`
Line int `json:"line,omitempty"`
DiffHunk string `json:"diff_hunk,omitempty"`
InReplyToID int64 `json:"in_reply_to_id,omitempty"`
}
Comment represents either an issue comment or inline review comment
type DecisionWriteError ¶
type DecisionWriteError struct {
Err error
Classification retry.Classification
}
DecisionWriteError wraps an error from a decision review write and captures its retry classification.
func (*DecisionWriteError) Error ¶
func (e *DecisionWriteError) Error() string
func (*DecisionWriteError) IsUncertain ¶
func (e *DecisionWriteError) IsUncertain() bool
IsUncertain reports whether the write error has an unprovable remote outcome (D-16).
func (*DecisionWriteError) Unwrap ¶
func (e *DecisionWriteError) Unwrap() error
type DiscussionThread ¶
type DiscussionThread struct {
Path string `json:"path"`
Line int `json:"line"`
DiffHunk string `json:"diff_hunk"`
Comments []Comment `json:"comments"`
}
DiscussionThread groups inline comments on the same code location
type FileContent ¶
type FindOwnedCommentOptions ¶
type FindOwnedCommentOptions struct {
Owner string
Repo string
PRNumber int
Marker string
BodyDigest string // hex SHA-256; if non-empty, requires matching body digest
Actor *ServiceActor
MaxPages int // defaults to 20 if <= 0
}
FindOwnedCommentOptions configures bounded owned-comment searches.
type HeadMovedError ¶
HeadMovedError indicates that an expected-head conditional commit mutation failed because the branch head on GitHub moved away from the expected commit OID (D-16, SAFE-03).
func (*HeadMovedError) Error ¶
func (e *HeadMovedError) Error() string
func (*HeadMovedError) Is ¶
func (e *HeadMovedError) Is(target error) bool
type InlineSuggestion ¶
InlineSuggestion is a one-click replacement attached to a changed PR line.
type OwnedCommentMatch ¶
type OwnedCommentMatch struct {
Found bool
CommentID int64
Body string
Uncertain bool
Reason string
}
OwnedCommentMatch carries the outcome of an owned-comment lookup.
type PRDetails ¶
type PRDetails struct {
Owner string
Repo string
Number int
Title string
Body string
Author string
BaseRef string
BaseSHA string // Captured immutable base commit OID (D-16, SAFE-03)
HeadRef string
HeadSHA string
HeadRepoOwner string
HeadRepoName string
HeadRepoID int64
CloneURL string
CreatedAt time.Time
}
PRDetails holds basic metadata of the pull request
type PushCredential ¶
type PushCredential struct {
Token string `json:"token"`
ExpiresAt time.Time `json:"expires_at"`
RepositoryID int64 `json:"repository_id"`
RepoOwner string `json:"repo_owner"`
RepoName string `json:"repo_name"`
Permissions map[string]string `json:"permissions"`
// contains filtered or unexported fields
}
PushCredential holds a short-lived, least-privilege App token scoped to exactly one PR head repository with contents:write permission for the gated same-PR push path (D-24, D-29). It lives only in host gateway memory: it is never passed into the container or the LLM prompt/context (T-05-02), and it is revoked plus zeroized after exactly one push call.
func (*PushCredential) IsRevoked ¶
func (c *PushCredential) IsRevoked() bool
IsRevoked returns true if the credential has been revoked or zeroized.
func (*PushCredential) Zeroize ¶
func (c *PushCredential) Zeroize()
Zeroize securely wipes the token from memory, even on revoke failure.
type RetrievalCredential ¶
type RetrievalCredential struct {
Token string `json:"token"`
ExpiresAt time.Time `json:"expires_at"`
RepositoryID int64 `json:"repository_id"`
RepoOwner string `json:"repo_owner"`
RepoName string `json:"repo_name"`
Permissions map[string]string `json:"permissions"`
// contains filtered or unexported fields
}
RetrievalCredential holds a short-lived, least-privilege App token scoped to exactly one head repository with contents:read permission for private source retrieval (D-10, SAFE-01).
func (*RetrievalCredential) IsRevoked ¶
func (c *RetrievalCredential) IsRevoked() bool
IsRevoked returns true if the credential has been revoked or zeroized.
func (*RetrievalCredential) Zeroize ¶
func (c *RetrievalCredential) Zeroize()
Zeroize securely wipes the token from memory.
type ServiceActor ¶
ServiceActor represents the verified authenticated identity of the service.