Documentation
¶
Overview ¶
Package forge defines the interface for interacting with git forges (GitHub, GitLab, Forgejo). All forge-specific operations flow through the Client interface, keeping the rest of the codebase forge-agnostic.
Index ¶
- Constants
- Variables
- func IsNotFound(err error) bool
- type ChangeProposal
- type Client
- type CommitFilesRecord
- type DismissedReviewRecord
- type FakeClient
- func (f *FakeClient) CloseIssue(_ context.Context, _, _ string, _ int) error
- func (f *FakeClient) CommitFiles(_ context.Context, owner, repo, message string, files []TreeFile) (bool, error)
- func (f *FakeClient) CreateBranch(_ context.Context, owner, repo, branchName string) error
- func (f *FakeClient) CreateChangeProposal(_ context.Context, owner, repo, title, body, head, base string) (*ChangeProposal, error)
- func (f *FakeClient) CreateFile(_ context.Context, owner, repo, path, message string, content []byte) error
- func (f *FakeClient) CreateFileOnBranch(_ context.Context, owner, repo, branch, path, message string, content []byte) error
- func (f *FakeClient) CreateIssue(_ context.Context, _, _, _, _ string) (*Issue, error)
- func (f *FakeClient) CreateIssueComment(_ context.Context, owner, repo string, number int, body string) (*IssueComment, error)
- func (f *FakeClient) CreateOrUpdateFile(_ context.Context, owner, repo, path, message string, content []byte) error
- func (f *FakeClient) CreateOrUpdateFileOnBranch(_ context.Context, owner, repo, branch, path, message string, content []byte) error
- func (f *FakeClient) CreateOrUpdateRepoVariable(_ context.Context, owner, repo, name, value string) error
- func (f *FakeClient) CreateOrgSecret(_ context.Context, org, name, value string, selectedRepoIDs []int64) error
- func (f *FakeClient) CreatePullRequestReview(_ context.Context, owner, repo string, number int, ...) error
- func (f *FakeClient) CreateRepo(_ context.Context, org, name, description string, private bool) (*Repository, error)
- func (f *FakeClient) CreateRepoSecret(_ context.Context, owner, repo, name, value string) error
- func (f *FakeClient) DeleteFile(_ context.Context, owner, repo, path, message string) error
- func (f *FakeClient) DeleteOrgSecret(_ context.Context, org, name string) error
- func (f *FakeClient) DeleteRepo(_ context.Context, owner, repo string) error
- func (f *FakeClient) DismissPullRequestReview(_ context.Context, owner, repo string, number, reviewID int, message string) error
- func (f *FakeClient) DispatchWorkflow(_ context.Context, _, _, _, _ string, _ map[string]string) error
- func (f *FakeClient) GetAppClientID(_ context.Context, slug string) (string, error)
- func (f *FakeClient) GetAuthenticatedUser(_ context.Context) (string, error)
- func (f *FakeClient) GetFileContent(_ context.Context, owner, repo, path string) ([]byte, error)
- func (f *FakeClient) GetLatestWorkflowRun(_ context.Context, owner, repo, workflowFile string) (*WorkflowRun, error)
- func (f *FakeClient) GetOrgSecretRepos(_ context.Context, org, name string) ([]int64, error)
- func (f *FakeClient) GetPullRequestHeadSHA(_ context.Context, _, _ string, _ int) (string, error)
- func (f *FakeClient) GetRepo(_ context.Context, owner, repo string) (*Repository, error)
- func (f *FakeClient) GetTokenScopes(_ context.Context) ([]string, error)
- func (f *FakeClient) GetWorkflowRun(_ context.Context, owner, repo string, runID int) (*WorkflowRun, error)
- func (f *FakeClient) GetWorkflowRunLogs(_ context.Context, _, _ string, _ int) (string, error)
- func (f *FakeClient) ListIssueComments(_ context.Context, owner, repo string, number int) ([]IssueComment, error)
- func (f *FakeClient) ListOrgInstallations(_ context.Context, _ string) ([]Installation, error)
- func (f *FakeClient) ListOrgRepos(_ context.Context, _ string) ([]Repository, error)
- func (f *FakeClient) ListPullRequestReviews(_ context.Context, owner, repo string, number int) ([]PullRequestReview, error)
- func (f *FakeClient) ListRepoPullRequests(_ context.Context, owner, repo string) ([]ChangeProposal, error)
- func (f *FakeClient) ListWorkflowRuns(_ context.Context, owner, repo, workflowFile string) ([]WorkflowRun, error)
- func (f *FakeClient) MergeChangeProposal(_ context.Context, _, _ string, _ int) error
- func (f *FakeClient) MinimizeComment(_ context.Context, nodeID, reason string) error
- func (f *FakeClient) OrgSecretExists(_ context.Context, org, name string) (bool, error)
- func (f *FakeClient) RepoSecretExists(_ context.Context, owner, repo, name string) (bool, error)
- func (f *FakeClient) RepoVariableExists(_ context.Context, owner, repo, name string) (bool, error)
- func (f *FakeClient) SetOrgSecretRepos(_ context.Context, org, name string, repoIDs []int64) error
- func (f *FakeClient) UpdateIssueComment(_ context.Context, owner, repo string, commentID int, body string) error
- type FileRecord
- type Installation
- type Issue
- type IssueComment
- type MinimizedCommentRecord
- type OrgSecretRecord
- type PullRequestReview
- type Repository
- type ReviewRecord
- type SecretRecord
- type TreeFile
- type UpdatedCommentRecord
- type VariableRecord
- type WorkflowRun
Constants ¶
const ConfigRepoName = ".fullsend"
ConfigRepoName is the conventional name for the org-level fullsend configuration repository. See ADR-0003.
Variables ¶
var ErrNotFound = errors.New("not found")
ErrNotFound indicates a requested resource was not found on the forge.
Functions ¶
func IsNotFound ¶
IsNotFound reports whether err indicates a resource was not found.
Types ¶
type ChangeProposal ¶
ChangeProposal represents a pull request or merge request.
type Client ¶
type Client interface {
// Repository operations
// ListOrgRepos returns repositories eligible for fullsend installation.
// It excludes archived repos (no active development) and forks.
//
// Forks are excluded because fullsend's trust model is org-centric:
// trust derives from org repository permissions and CODEOWNERS
// governance. Forks may live outside the org's permission boundary
// or lack the same CODEOWNERS configuration, which could bypass
// human-approval gates. Installing on both a fork and its upstream
// also risks duplicate agent PRs and conflicting changes.
ListOrgRepos(ctx context.Context, org string) ([]Repository, error)
GetRepo(ctx context.Context, owner, repo string) (*Repository, error)
CreateRepo(ctx context.Context, org, name, description string, private bool) (*Repository, error)
DeleteRepo(ctx context.Context, owner, repo string) error
// File operations
CreateFile(ctx context.Context, owner, repo, path, message string, content []byte) error
// CreateOrUpdateFile creates a file or updates it if it already exists.
// On GitHub, updating an existing file requires the current file's SHA
// (optimistic concurrency control). The GitHub implementation handles
// this by fetching the existing SHA before writing. Without it, the
// API returns a 422 "sha wasn't supplied" error.
CreateOrUpdateFile(ctx context.Context, owner, repo, path, message string, content []byte) error
GetFileContent(ctx context.Context, owner, repo, path string) ([]byte, error)
DeleteFile(ctx context.Context, owner, repo, path, message string) error
// CommitFiles atomically commits multiple files to the repository's
// default branch in a single commit. It is idempotent: if all files
// already have the expected content and mode, no commit is created
// and it returns (false, nil).
CommitFiles(ctx context.Context, owner, repo, message string, files []TreeFile) (committed bool, err error)
// Branch operations
CreateBranch(ctx context.Context, owner, repo, branchName string) error
CreateFileOnBranch(ctx context.Context, owner, repo, branch, path, message string, content []byte) error
// CreateOrUpdateFileOnBranch creates or updates a file on a specific branch.
// Combines SHA-aware upsert with branch targeting.
CreateOrUpdateFileOnBranch(ctx context.Context, owner, repo, branch, path, message string, content []byte) error
// Change proposals (PRs/MRs)
CreateChangeProposal(ctx context.Context, owner, repo, title, body, head, base string) (*ChangeProposal, error)
ListRepoPullRequests(ctx context.Context, owner, repo string) ([]ChangeProposal, error)
// Authentication
GetAuthenticatedUser(ctx context.Context) (string, error)
// GetTokenScopes returns the OAuth scopes granted to the current token.
// On GitHub, this is read from the X-OAuth-Scopes response header.
// Returns nil (not an error) if the forge doesn't support scope introspection.
GetTokenScopes(ctx context.Context) ([]string, error)
// Secrets and variables
CreateRepoSecret(ctx context.Context, owner, repo, name, value string) error
RepoSecretExists(ctx context.Context, owner, repo, name string) (bool, error)
CreateOrUpdateRepoVariable(ctx context.Context, owner, repo, name, value string) error
RepoVariableExists(ctx context.Context, owner, repo, name string) (bool, error)
// Org-level secrets (for cross-repo dispatch tokens)
CreateOrgSecret(ctx context.Context, org, name, value string, selectedRepoIDs []int64) error
OrgSecretExists(ctx context.Context, org, name string) (bool, error)
DeleteOrgSecret(ctx context.Context, org, name string) error
SetOrgSecretRepos(ctx context.Context, org, name string, repoIDs []int64) error
// GetOrgSecretRepos returns the list of repository IDs that have access
// to the given org-level secret.
GetOrgSecretRepos(ctx context.Context, org, name string) ([]int64, error)
// CI/Workflow operations
GetLatestWorkflowRun(ctx context.Context, owner, repo, workflowFile string) (*WorkflowRun, error)
GetWorkflowRun(ctx context.Context, owner, repo string, runID int) (*WorkflowRun, error)
DispatchWorkflow(ctx context.Context, owner, repo, workflowFile, ref string, inputs map[string]string) error
// Issue operations
CreateIssue(ctx context.Context, owner, repo, title, body string) (*Issue, error)
CloseIssue(ctx context.Context, owner, repo string, number int) error
ListIssueComments(ctx context.Context, owner, repo string, number int) ([]IssueComment, error)
CreateIssueComment(ctx context.Context, owner, repo string, number int, body string) (*IssueComment, error)
UpdateIssueComment(ctx context.Context, owner, repo string, commentID int, body string) error
MinimizeComment(ctx context.Context, nodeID, reason string) error
// Pull request operations
GetPullRequestHeadSHA(ctx context.Context, owner, repo string, number int) (string, error)
// Pull request review operations.
// commitSHA, when non-empty, pins the review to a specific commit.
// GitHub rejects the request if the commit is not the PR's current HEAD.
CreatePullRequestReview(ctx context.Context, owner, repo string, number int, event, body, commitSHA string) error
ListPullRequestReviews(ctx context.Context, owner, repo string, number int) ([]PullRequestReview, error)
DismissPullRequestReview(ctx context.Context, owner, repo string, number, reviewID int, message string) error
// Change proposal merge
MergeChangeProposal(ctx context.Context, owner, repo string, number int) error
// Workflow run listing
ListWorkflowRuns(ctx context.Context, owner, repo, workflowFile string) ([]WorkflowRun, error)
// GetWorkflowRunLogs downloads the logs for a workflow run as plain text.
// On GitHub, this fetches job logs for each job in the run.
GetWorkflowRunLogs(ctx context.Context, owner, repo string, runID int) (string, error)
// App installation operations
ListOrgInstallations(ctx context.Context, org string) ([]Installation, error)
// GetAppClientID returns the Client ID for a GitHub App identified by slug.
GetAppClientID(ctx context.Context, slug string) (string, error)
}
Client abstracts all git forge operations. Implementations exist for GitHub (and eventually GitLab, Forgejo).
type CommitFilesRecord ¶ added in v0.6.0
CommitFilesRecord records a CommitFiles call.
type DismissedReviewRecord ¶ added in v0.6.0
DismissedReviewRecord records a review dismissal call.
type FakeClient ¶
type FakeClient struct {
// Pre-populated data
Repos []Repository
FileContents map[string][]byte // key: "owner/repo/path"
WorkflowRuns map[string]*WorkflowRun // key: "owner/repo/workflow"
AuthenticatedUser string
Installations []Installation
Secrets map[string]bool // key: "owner/repo/name"
PullRequests map[string][]ChangeProposal // key: "owner/repo"
TokenScopes []string // scopes returned by GetTokenScopes
VariablesExist map[string]bool // key: "owner/repo/name"
// App client IDs for GetAppClientID
AppClientIDs map[string]string // key: app slug → client ID
// Org-level secret state
OrgSecrets map[string]bool // key: "org/name"
OrgSecretRepoIDs map[string][]int64 // key: "org/name" → repo IDs
// Error injection: key is method name, value is error to return.
Errors map[string]error
// Issue comments for ListIssueComments / UpdateIssueComment.
IssueComments map[string][]IssueComment // key: "owner/repo/number"
// CommitFilesChanged controls the return value of CommitFiles (default true).
CommitFilesChanged *bool
// Pull request head SHA for GetPullRequestHeadSHA.
PullRequestHeadSHA string
// Pull request reviews for ListPullRequestReviews.
PRReviews map[string][]PullRequestReview // key: "owner/repo/number"
// Call recorders
CreatedRepos []Repository
CreatedFiles []FileRecord
CreatedBranches []string // "owner/repo/branch"
CreatedProposals []ChangeProposal
DeletedRepos []string // "owner/repo"
DeletedFiles []FileRecord
CreatedSecrets []SecretRecord
Variables []VariableRecord
DeletedOrgSecrets []string // "org/name"
CreatedOrgSecrets []OrgSecretRecord
UpdatedComments []UpdatedCommentRecord
MinimizedComments []MinimizedCommentRecord
CreatedReviews []ReviewRecord
DismissedReviews []DismissedReviewRecord
CommittedFiles []CommitFilesRecord
// contains filtered or unexported fields
}
FakeClient is a thread-safe test double for forge.Client. Pre-populate its fields to control return values, and inspect recorder slices after the test to verify which calls were made.
func NewFakeClient ¶
func NewFakeClient() *FakeClient
NewFakeClient returns a FakeClient with all maps initialised.
func (*FakeClient) CloseIssue ¶ added in v0.0.3
func (*FakeClient) CommitFiles ¶ added in v0.6.0
func (*FakeClient) CreateBranch ¶
func (f *FakeClient) CreateBranch(_ context.Context, owner, repo, branchName string) error
func (*FakeClient) CreateChangeProposal ¶
func (f *FakeClient) CreateChangeProposal(_ context.Context, owner, repo, title, body, head, base string) (*ChangeProposal, error)
func (*FakeClient) CreateFile ¶
func (*FakeClient) CreateFileOnBranch ¶
func (*FakeClient) CreateIssue ¶ added in v0.0.3
func (*FakeClient) CreateIssueComment ¶ added in v0.2.0
func (f *FakeClient) CreateIssueComment(_ context.Context, owner, repo string, number int, body string) (*IssueComment, error)
func (*FakeClient) CreateOrUpdateFile ¶
func (*FakeClient) CreateOrUpdateFileOnBranch ¶
func (*FakeClient) CreateOrUpdateRepoVariable ¶
func (f *FakeClient) CreateOrUpdateRepoVariable(_ context.Context, owner, repo, name, value string) error
func (*FakeClient) CreateOrgSecret ¶
func (*FakeClient) CreatePullRequestReview ¶ added in v0.2.0
func (*FakeClient) CreateRepo ¶
func (f *FakeClient) CreateRepo(_ context.Context, org, name, description string, private bool) (*Repository, error)
func (*FakeClient) CreateRepoSecret ¶
func (f *FakeClient) CreateRepoSecret(_ context.Context, owner, repo, name, value string) error
func (*FakeClient) DeleteFile ¶ added in v0.1.0
func (f *FakeClient) DeleteFile(_ context.Context, owner, repo, path, message string) error
func (*FakeClient) DeleteOrgSecret ¶
func (f *FakeClient) DeleteOrgSecret(_ context.Context, org, name string) error
func (*FakeClient) DeleteRepo ¶
func (f *FakeClient) DeleteRepo(_ context.Context, owner, repo string) error
func (*FakeClient) DismissPullRequestReview ¶ added in v0.6.0
func (*FakeClient) DispatchWorkflow ¶
func (*FakeClient) GetAppClientID ¶ added in v0.1.0
func (*FakeClient) GetAuthenticatedUser ¶
func (f *FakeClient) GetAuthenticatedUser(_ context.Context) (string, error)
func (*FakeClient) GetFileContent ¶
func (*FakeClient) GetLatestWorkflowRun ¶
func (f *FakeClient) GetLatestWorkflowRun(_ context.Context, owner, repo, workflowFile string) (*WorkflowRun, error)
func (*FakeClient) GetOrgSecretRepos ¶ added in v0.5.0
func (*FakeClient) GetPullRequestHeadSHA ¶ added in v0.2.0
func (*FakeClient) GetRepo ¶
func (f *FakeClient) GetRepo(_ context.Context, owner, repo string) (*Repository, error)
func (*FakeClient) GetTokenScopes ¶
func (f *FakeClient) GetTokenScopes(_ context.Context) ([]string, error)
func (*FakeClient) GetWorkflowRun ¶
func (f *FakeClient) GetWorkflowRun(_ context.Context, owner, repo string, runID int) (*WorkflowRun, error)
func (*FakeClient) GetWorkflowRunLogs ¶ added in v0.0.3
func (*FakeClient) ListIssueComments ¶ added in v0.0.4
func (f *FakeClient) ListIssueComments(_ context.Context, owner, repo string, number int) ([]IssueComment, error)
func (*FakeClient) ListOrgInstallations ¶
func (f *FakeClient) ListOrgInstallations(_ context.Context, _ string) ([]Installation, error)
func (*FakeClient) ListOrgRepos ¶
func (f *FakeClient) ListOrgRepos(_ context.Context, _ string) ([]Repository, error)
func (*FakeClient) ListPullRequestReviews ¶ added in v0.2.0
func (f *FakeClient) ListPullRequestReviews(_ context.Context, owner, repo string, number int) ([]PullRequestReview, error)
func (*FakeClient) ListRepoPullRequests ¶
func (f *FakeClient) ListRepoPullRequests(_ context.Context, owner, repo string) ([]ChangeProposal, error)
func (*FakeClient) ListWorkflowRuns ¶ added in v0.0.3
func (f *FakeClient) ListWorkflowRuns(_ context.Context, owner, repo, workflowFile string) ([]WorkflowRun, error)
func (*FakeClient) MergeChangeProposal ¶ added in v0.0.3
func (*FakeClient) MinimizeComment ¶ added in v0.2.0
func (f *FakeClient) MinimizeComment(_ context.Context, nodeID, reason string) error
func (*FakeClient) OrgSecretExists ¶
func (*FakeClient) RepoSecretExists ¶
func (*FakeClient) RepoVariableExists ¶
func (*FakeClient) SetOrgSecretRepos ¶
func (*FakeClient) UpdateIssueComment ¶ added in v0.2.0
type FileRecord ¶
FileRecord records a file creation/update call.
type Installation ¶
Installation represents an app installation on an org.
type IssueComment ¶ added in v0.0.4
type IssueComment struct {
ID int
NodeID string
HTMLURL string
Body string
Author string
CreatedAt string
}
IssueComment represents a comment on an issue.
type MinimizedCommentRecord ¶ added in v0.2.0
MinimizedCommentRecord records a comment minimize call.
type OrgSecretRecord ¶
OrgSecretRecord records an org-level secret creation call.
type PullRequestReview ¶ added in v0.2.0
type PullRequestReview struct {
ID int
NodeID string
User string
State string // "APPROVED", "CHANGES_REQUESTED", "COMMENTED", "DISMISSED"
Body string
SubmittedAt string
}
PullRequestReview represents a formal review on a pull request.
type Repository ¶
type Repository struct {
ID int64
Name string
FullName string
DefaultBranch string
Private bool
Archived bool
Fork bool
}
Repository represents a repository on a git forge.
type ReviewRecord ¶ added in v0.2.0
ReviewRecord records a pull request review creation call.
type SecretRecord ¶
type SecretRecord struct {
Owner, Repo, Name, Value string
}
SecretRecord records a secret creation call.
type TreeFile ¶ added in v0.6.0
TreeFile represents a file to be committed via the Git Trees API. Mode controls file permissions: "100644" for regular files, "100755" for executable files (e.g., shell scripts).
type UpdatedCommentRecord ¶ added in v0.2.0
UpdatedCommentRecord records an issue comment update call.
type VariableRecord ¶
type VariableRecord struct {
Owner, Repo, Name, Value string
}
VariableRecord records a variable creation/update call.