provider

package
v0.0.0-...-15cb2bd Latest Latest
Warning

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

Go to latest
Published: Aug 13, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

Documentation

Overview

Package provider defines Wright's provider-agnostic interface for hosting services (GitHub, GitLab) along with the domain types and sentinel errors that adapters map onto. It is a leaf package: everything else in Wright depends on it, and it depends on nothing internal. Adapters live in subpackages (github, gitlab); the factory in factory.go selects one from config.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNotFound is returned when a repo, issue, branch, or PR does not exist
	// (HTTP 404).
	ErrNotFound = errors.New("not found")

	// ErrAlreadyExists is returned when creating something that already exists,
	// e.g. a branch (HTTP 409/422 depending on provider).
	ErrAlreadyExists = errors.New("already exists")

	// ErrAuth is returned for authentication or authorization failures
	// (HTTP 401/403 that are not rate limiting).
	ErrAuth = errors.New("authentication failed")

	// ErrRateLimited is returned when the provider reports rate limiting
	// (HTTP 429, or GitHub's 403 with a rate-limit signal).
	ErrRateLimited = errors.New("rate limited")

	// ErrInvalidRequest is returned for a permanent client-side rejection (any
	// 4xx not already covered above, e.g. 400 or 409). Retrying the identical
	// request will not change the outcome.
	ErrInvalidRequest = errors.New("invalid request")
)

Sentinel errors that adapters map provider HTTP statuses onto. Callers check them with errors.Is; adapters wrap them with context using %w, e.g.

fmt.Errorf("github: create branch %q in %s: %w", branch, repo.FullPath, provider.ErrAlreadyExists)

Functions

func SanitizeRef

func SanitizeRef(s string) string

SanitizeRef makes s safe to use as a git ref (a branch name or a fromRef that is a branch/SHA). A valid ref contains no control characters and no whitespace, so unlike SanitizeText this also drops tab, newline, carriage return, and space rather than preserving them — both because they make a ref invalid and because the ref may reach an unquoted shell position in the sandbox git path. It never rewrites otherwise-valid names (e.g. wright/issue-7).

func SanitizeText

func SanitizeText(s string) string

SanitizeText makes s safe to send as an API payload (a PR/MR title or body, or an issue/PR comment). Text assembled from raw sandbox command output can carry null bytes, other control characters, and invalid UTF-8. GitLab's null-byte middleware in particular rejects any such request with a plain-text "400 Bad Request" before it reaches the API. This coerces s to valid UTF-8 and drops disallowed control runes, keeping the whitespace (tab, newline, carriage return) that Markdown needs.

Adapters apply it at the provider boundary so every outbound text field is covered regardless of caller.

Types

type Comment

type Comment struct {
	Author    string
	Body      string
	CreatedAt time.Time
}

Comment is a single comment (GitLab: note) on an issue's discussion thread.

type Commit

type Commit struct {
	Message string
	Files   []CommitFile
}

Commit is a single commit to be created through the provider's API. It carries the whole set of file changes that make up the commit.

type CommitFile

type CommitFile struct {
	Path    string
	Content string
	Delete  bool
}

CommitFile is one file change within a Commit. When Delete is true the file at Path is removed and Content is ignored; otherwise the file at Path is created or overwritten with Content.

type Issue

type Issue struct {
	Number    int
	Title     string
	Body      string
	Labels    []string
	URL       string
	Author    string
	State     string // "open" or "closed"
	CreatedAt time.Time
	UpdatedAt time.Time
	Comments  []Comment
}

Issue is an open issue on the provider. Labels holds the label names only. Comments holds the issue's discussion thread (oldest first): a lot of the detail an implementer needs — clarifications, decisions, scope changes — only ever shows up there, not in the original Body.

func (Issue) FormatComments

func (i Issue) FormatComments() string

FormatComments renders the issue's discussion thread as plain text suitable for inclusion in an LLM prompt, oldest first. It returns "" when there are no comments.

type MergeMethod

type MergeMethod string

MergeMethod selects how a pull request is merged.

const (
	MergeMerge  MergeMethod = "merge"
	MergeSquash MergeMethod = "squash"
	MergeRebase MergeMethod = "rebase"
)

type MergeOptions

type MergeOptions struct {
	Method       MergeMethod
	DeleteBranch bool
}

MergeOptions controls a merge. An empty Method lets the adapter pick the provider's default.

type Provider

type Provider interface {
	// Name reports the provider identifier: "github" or "gitlab".
	Name() string

	// ListLabeledIssues returns open issues in repo that carry label. It
	// returns only genuine issues (pull/merge requests are excluded).
	ListLabeledIssues(ctx context.Context, repo Repo, label string) ([]Issue, error)

	// GetIssue fetches a single issue by number, without its comment thread.
	// Used to resolve cross-issue references (e.g. "blocked by #12") against
	// live state rather than trusting stale issue text.
	GetIssue(ctx context.Context, repo Repo, number int) (*Issue, error)

	// ReadRepoFile returns the content of the file at path, at ref (a branch
	// name or SHA; the empty string means the repo's default branch). Returns
	// ErrNotFound when path does not exist or is a directory.
	ReadRepoFile(ctx context.Context, repo Repo, ref, path string) (string, error)

	// ListRepoDir returns the entry names at path, at ref (a branch name or
	// SHA; the empty string means the repo's default branch). Directory
	// entries are suffixed with "/". The empty path lists the repo root.
	ListRepoDir(ctx context.Context, repo Repo, ref, path string) ([]string, error)

	// CommentOnIssue posts body as a comment on the given issue.
	CommentOnIssue(ctx context.Context, repo Repo, issueNumber int, body string) error

	// AddIssueLabel adds label to the given issue.
	AddIssueLabel(ctx context.Context, repo Repo, issueNumber int, label string) error

	// RemoveIssueLabel removes label from the given issue. Removing a label that is
	// already absent succeeds.
	RemoveIssueLabel(ctx context.Context, repo Repo, issueNumber int, label string) error

	// CommentOnPullRequest posts body as a comment on the given pull request
	// (GitLab: merge request). This is distinct from CommentOnIssue because
	// GitLab keeps issue notes and merge-request notes in separate namespaces.
	CommentOnPullRequest(ctx context.Context, repo Repo, number int, body string) error

	// DefaultBranch returns the repo's default branch name.
	DefaultBranch(ctx context.Context, repo Repo) (string, error)

	// CreateBranch creates branch pointing at fromRef (a branch name or SHA).
	CreateBranch(ctx context.Context, repo Repo, branch, fromRef string) error

	// DeleteBranch deletes branch.
	DeleteBranch(ctx context.Context, repo Repo, branch string) error

	// PushCommits creates commits on branch through the provider's commit API
	// (no local clone in Phase 0) and returns the resulting head SHA.
	PushCommits(ctx context.Context, repo Repo, branch string, commits []Commit) (string, error)

	// FindOpenPullRequestByHead returns an open PR whose head/source branch matches
	// headBranch, or nil when no such PR exists.
	FindOpenPullRequestByHead(ctx context.Context, repo Repo, headBranch string) (*PullRequest, error)

	// OpenPullRequest opens a pull request (GitLab: merge request) per spec.
	OpenPullRequest(ctx context.Context, repo Repo, spec PullRequestSpec) (*PullRequest, error)

	// GetPullRequest fetches a pull request by number, regardless of its
	// state (open, closed, or merged) — unlike FindOpenPullRequestByHead,
	// which only ever returns open ones.
	GetPullRequest(ctx context.Context, repo Repo, number int) (*PullRequest, error)

	// UpdatePullRequestBase retargets an existing pull request onto a new
	// base branch. Idempotent: retargeting onto the branch it already points
	// at succeeds without effect.
	UpdatePullRequestBase(ctx context.Context, repo Repo, number int, baseBranch string) error

	// MergePullRequest merges the pull request identified by number.
	MergePullRequest(ctx context.Context, repo Repo, number int, opts MergeOptions) error

	// ClosePullRequest closes the pull request identified by number without
	// merging.
	ClosePullRequest(ctx context.Context, repo Repo, number int) error
}

Provider is the write-path abstraction over a hosting service. All methods take a Repo so a single Provider value can operate across repos on the same host. Methods return the sentinel errors in errors.go (wrapped with context) so callers can branch with errors.Is.

type PullRequest

type PullRequest struct {
	Number     int
	URL        string
	HeadBranch string
	BaseBranch string
	State      string // "open", "closed", or "merged"
}

PullRequest is a pull request (GitLab: merge request) as returned by the provider. For GitLab, Number is the merge request IID.

type PullRequestSpec

type PullRequestSpec struct {
	Title      string
	Body       string
	HeadBranch string
	BaseBranch string
	Draft      bool
}

PullRequestSpec describes a pull request (GitLab: merge request) to open.

type Repo

type Repo struct {
	FullPath string
}

Repo identifies a repository or project. FullPath is a single string ("owner/name" on GitHub, or a full project path like "group/subgroup/name" on GitLab) so that GitLab's arbitrarily nested groups work without a separate owner/name split.

Directories

Path Synopsis
Package factory constructs a provider.Provider from a repo's config entry.
Package factory constructs a provider.Provider from a repo's config entry.
Package github implements provider.Provider against the GitHub REST API using google/go-github.
Package github implements provider.Provider against the GitHub REST API using google/go-github.
Package gitlab implements provider.Provider against the GitLab REST API using the official gitlab.com/gitlab-org/api/client-go (the successor to the archived xanzy/go-gitlab).
Package gitlab implements provider.Provider against the GitLab REST API using the official gitlab.com/gitlab-org/api/client-go (the successor to the archived xanzy/go-gitlab).
Package logging decorates a provider.Provider with structured logging of every call: the method and its key arguments on entry, and the duration plus outcome (a brief result summary, or the full error chain) on exit.
Package logging decorates a provider.Provider with structured logging of every call: the method and its key arguments on entry, and the duration plus outcome (a brief result summary, or the full error chain) on exit.
Package providertest holds shared, provider-agnostic assertions that both the GitHub and GitLab adapter test suites run against their own httptest fakes.
Package providertest holds shared, provider-agnostic assertions that both the GitHub and GitLab adapter test suites run against their own httptest fakes.
Package retrying decorates a provider.Provider with configurable retries around every connection attempt to the hosting API.
Package retrying decorates a provider.Provider with configurable retries around every connection attempt to the hosting API.

Jump to

Keyboard shortcuts

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