provider

package
v0.47.0 Latest Latest
Warning

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

Go to latest
Published: Aug 28, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Index

Constants

View Source
const (
	DefaultPage    = 1
	DefaultPerPage = 20
	MaxPerPage     = 100
)

Variables

View Source
var (
	ErrNotFound             = errors.New("resource not found")
	ErrAuthentication       = errors.New("authentication failed")
	ErrRateLimited          = errors.New("rate limited")
	ErrForbidden            = errors.New("forbidden")
	ErrConflict             = errors.New("conflict")
	ErrNotImplemented       = errors.New("not implemented")
	ErrInvalidInput         = errors.New("invalid input")
	ErrWebhookValidation    = errors.New("webhook validation failed")
	ErrConnectionFailed     = errors.New("connection failed")
	ErrPlatformNotSupported = errors.New("platform not supported")
)

Sentinel errors classify transport and provider failures so callers can branch on category without inspecting status codes or wrapped causes.

Functions

func BuildRawDiff

func BuildRawDiff(files []*ChangedFile) string

BuildRawDiff constructs a raw diff string from a list of ChangedFiles.

func ClassifyStatus

func ClassifyStatus(statusCode int) error

ClassifyStatus maps an HTTP status code to a sentinel error. Exposed so transports and platform implementations can produce consistent error categories without importing each other.

func CountDiffLines

func CountDiffLines(diff string) (additions, deletions int)

CountDiffLines counts additions and deletions in a unified diff string.

func ExtractOwnerFromFullName

func ExtractOwnerFromFullName(fullName string) string

ExtractOwnerFromFullName returns just the owner portion of "owner/repo".

func HashToken

func HashToken(token string) string

HashToken returns the first 16 hex characters of SHA-256(token). It is the default token hasher used by Manager and is exported so callers can compute cache keys for diagnostics or external caches.

An empty token hashes to an empty string (no anonymous cache entries).

func Ignores added in v0.45.0

func Ignores(divs []Divergence, method, field string) bool

Ignores reports whether the ledger registers an ignore of field on method.

func IsAuthentication

func IsAuthentication(err error) bool

IsAuthentication reports whether err wraps ErrAuthentication (HTTP 401).

func IsConflict

func IsConflict(err error) bool

IsConflict reports whether err wraps ErrConflict (HTTP 409).

func IsForbidden

func IsForbidden(err error) bool

IsForbidden reports whether err wraps ErrForbidden (HTTP 403).

func IsInvalidInput

func IsInvalidInput(err error) bool

IsInvalidInput reports whether err wraps ErrInvalidInput.

func IsNotFound

func IsNotFound(err error) bool

IsNotFound reports whether err wraps ErrNotFound (HTTP 404).

func IsNotImplemented

func IsNotImplemented(err error) bool

IsNotImplemented reports whether err wraps ErrNotImplemented.

func IsPlatformNotSupported

func IsPlatformNotSupported(err error) bool

IsPlatformNotSupported reports whether err wraps ErrPlatformNotSupported.

func IsRateLimited

func IsRateLimited(err error) bool

IsRateLimited reports whether err wraps ErrRateLimited (HTTP 429).

func IsRegistered

func IsRegistered(p Platform) bool

IsRegistered checks if a platform has been registered.

func IsWebhookValidation

func IsWebhookValidation(err error) bool

IsWebhookValidation reports whether err wraps ErrWebhookValidation.

func New

func New(platform Platform, op string, status int, body string) error

New builds a ProviderError directly from the given status code.

func NormalizePageOpts

func NormalizePageOpts(page, perPage int) (int, int)

NormalizePageOpts applies default values for page/perPage.

func ParseTotalCountHeader

func ParseTotalCountHeader(headers http.Header, fallback int) int

ParseTotalCountHeader reads X-Total-Count or X-Total from response headers. Falls back to the provided default if neither header is present or valid.

func ReadAndRestoreBody

func ReadAndRestoreBody(r *http.Request) ([]byte, error)

ReadAndRestoreBody reads the full body of r and replaces it with a fresh NopCloser so that downstream readers (signature verification, JSON decoding) can still consume it. Use it at the entry point of webhook handlers that need to inspect the raw bytes.

func Register

func Register(p Platform, ctor ProviderConstructor)

Register registers a provider constructor for a platform. This is typically called from init() functions in platform implementation files.

func ResolveMRSHAs

func ResolveMRSHAs(diffRefsHead, diffRefsBase, diffRefsStart, mergeCommitSHA, lastCommitID string) (head, base, start string)

ResolveMRSHAs derives the (head, base, start) SHAs for a GitLab-style merge request from the raw webhook fields. This encodes the shared priority used by the GitLab, TencentCode (and future GitCode) backends:

  • head: diff_refs.head_sha when present, otherwise last_commit.id
  • base: merge_commit_sha when present, otherwise diff_refs.base_sha
  • start: diff_refs.start_sha (may be empty)

Keeping this in one place guarantees identical fallback semantics across the GitLab-family backends and avoids behavioural drift.

func SplitFullName

func SplitFullName(fullName string) (owner, name string)

SplitFullName splits "owner/repo" into (owner, repo). If the input doesn't contain "/", owner is empty.

func Stubs added in v0.45.0

func Stubs(divs []Divergence, method string) bool

Stubs reports whether the ledger registers method as a stub.

func SumDiffStats

func SumDiffStats(files []*ChangedFile) (additions, deletions int)

SumDiffStats returns total additions and deletions from a list of ChangedFiles.

func Wrap

func Wrap(platform Platform, op string, err error) error

Wrap creates a ProviderError from a raw error, classifying it when the cause is a transport error with a known status code. Use this in platform implementations to convert transport errors into the unified shape.

func WrapStatusError

func WrapStatusError(err error, statusCode int) error

WrapStatusError wraps an error with an explicit HTTP status code. This is the preferred way to attach status codes to third-party SDK errors instead of relying on reflection-based detection.

func Wrapf

func Wrapf(platform Platform, op, format string, args ...any) error

Wrapf is a convenience for creating a ProviderError with a formatted message. The format is intentionally simple ("%s/%s") so platform code can embed the resource identifier without re-implementing the prefix logic.

Types

type BranchManager

type BranchManager interface {
	ListBranches(ctx context.Context, owner, repo string) ([]*PlatformBranch, error)
	CreateBranch(ctx context.Context, owner, repo, branch, ref string) (*PlatformBranch, error)
	DeleteBranch(ctx context.Context, owner, repo, branch string) error
}

BranchManager handles branch operations.

type CRComment

type CRComment struct {
	ID        int64     `json:"id"`
	Body      string    `json:"body"`
	Author    *CRUser   `json:"author"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

CRComment represents a comment on a change request.

type CRCommit

type CRCommit struct {
	SHA       string    `json:"sha"`
	Message   string    `json:"message"`
	Author    *CRUser   `json:"author"`
	CreatedAt time.Time `json:"created_at"`
}

CRCommit represents a commit in a change request.

type CRState

type CRState string

CRState represents the state of a change request.

const (
	CRStateOpened CRState = "opened"
	CRStateMerged CRState = "merged"
	CRStateClosed CRState = "closed"
)

func MapBoolStateToCR

func MapBoolStateToCR(state string, merged bool) CRState

MapBoolStateToCR is a convenience for platforms with a separate merged boolean (Gitea, Forgejo).

func MapMRStateToCR

func MapMRStateToCR(state string) CRState

MapMRStateToCR is a convenience for platforms with explicit "merged" state (GitLab, Tencent Code).

func MapStateToCR

func MapStateToCR(state string, mergedFn func() bool) CRState

MapStateToCR maps common string state representations to CRState. mergedFn is called when state is "closed" to determine if it was merged. For platforms that use a separate "merged" field (Gitea, Forgejo), pass a non-nil mergedFn. For platforms where "merged" is a distinct state string (GitLab, Tencent Code), pass nil.

type CRUser

type CRUser struct {
	ID        int64  `json:"id"`
	Username  string `json:"username"`
	Name      string `json:"name"`
	AvatarURL string `json:"avatar_url"`
}

CRUser represents a user on a platform.

type CapabilitySet added in v0.38.0

type CapabilitySet struct {
	Issues         bool // provider.IssueManager
	Search         bool // provider.SearchManager
	Labels         bool // provider.LabelManager
	Milestones     bool // provider.MilestoneManager
	Reviews        bool // provider.ReviewManager
	CommitStatuses bool // provider.CommitStatusManager
}

CapabilitySet statically declares which optional capability interfaces a Provider implements. Values are compile-time constants per backend; no runtime probing is performed. Consumers should route on these flags instead of probing with type assertions:

if p.Capabilities().Labels {
	lm := p.(provider.LabelManager)
	// ...
}

When a new optional capability interface is added to the SDK, add a field here and update every backend's Capabilities method; the contract suite enforces that declarations match implementations.

type ChangeRequest

type ChangeRequest struct {
	ID           int64   `json:"id"`
	Number       string  `json:"number"`
	Title        string  `json:"title"`
	Description  string  `json:"description"`
	State        CRState `json:"state"`
	SourceBranch string  `json:"source_branch"`
	TargetBranch string  `json:"target_branch"`
	// HeadSHA is the SHA of the source-branch tip.
	// BaseSHA is the diff base: the merge-base (common ancestor) where GitLab/TencentCode
	// expose it via diff_refs.base_sha. GitHub/Gitea do not expose a distinct merge base in
	// webhook payloads, so BaseSHA there is the target-branch tip (equivalent to StartSHA).
	// StartSHA is the SHA of the target-branch tip at event time (GitLab diff_refs.start_sha).
	// On GitHub/Gitea it equals BaseSHA since no separate value is exposed.
	HeadSHA  string `json:"head_sha,omitempty"`
	BaseSHA  string `json:"base_sha,omitempty"`
	StartSHA string `json:"start_sha,omitempty"`
	// Draft reports the work-in-progress / draft state uniformly across platforms
	// (GitHub pr.draft, Gitea draft, GitLab/TencentCode work_in_progress).
	Draft       bool      `json:"draft"`
	Author      *CRUser   `json:"author"`
	Reviewers   []*CRUser `json:"reviewers"`
	Labels      []string  `json:"labels"`
	MergeStatus string    `json:"merge_status"`
	WebURL      string    `json:"web_url"`
	CreatedAt   time.Time `json:"created_at"`
	UpdatedAt   time.Time `json:"updated_at"`
}

ChangeRequest represents a pull request or merge request. Number is the platform's change-request identifier as a string (numeric on every current platform), mirroring Issue.Number.

type ChangeRequestManager

type ChangeRequestManager interface {
	CreateCR(ctx context.Context, opts CreateCROptions) (*ChangeRequest, error)
	GetCR(ctx context.Context, owner, repo, number string) (*ChangeRequest, error)
	ListCRs(ctx context.Context, opts ListCROptions) ([]*ChangeRequest, int, error)
	MergeCR(ctx context.Context, owner, repo, number string, opts MergeCROptions) (*ChangeRequest, error)
	CloseCR(ctx context.Context, owner, repo, number string) (*ChangeRequest, error)
	ReopenCR(ctx context.Context, owner, repo, number string) (*ChangeRequest, error)
	UpdateCR(ctx context.Context, owner, repo, number string, opts UpdateCROptions) (*ChangeRequest, error)
	UpdateCRLabels(ctx context.Context, owner, repo, number string, labels []string) error
	ListCRComments(ctx context.Context, owner, repo, number string) ([]*CRComment, error)
	ListCRCommits(ctx context.Context, owner, repo, number string) ([]*CRCommit, error)
}

ChangeRequestManager handles pull request / merge request lifecycle. Change request numbers are strings (same addressing scheme as IssueManager); numeric platforms parse with strconv and fail with a wrapped "invalid pull request number" error.

type ChangedFile

type ChangedFile struct {
	OldPath   string `json:"old_path"`
	NewPath   string `json:"new_path"`
	Diff      string `json:"diff"`
	Additions int    `json:"additions"`
	Deletions int    `json:"deletions"`
	IsNew     bool   `json:"new_file"`
	IsDeleted bool   `json:"deleted_file"`
	IsRenamed bool   `json:"renamed_file"`
	IsBinary  bool   `json:"binary"`
}

ChangedFile represents a file changed in a change request.

type CommitInfo

type CommitInfo struct {
	SHA       string    `json:"sha"`
	Message   string    `json:"message"`
	Author    *CRUser   `json:"author"`
	Committer *CRUser   `json:"committer"`
	CreatedAt time.Time `json:"created_at"`
	Additions int       `json:"additions"`
	Deletions int       `json:"deletions"`
}

CommitInfo represents a commit.

type CommitManager

type CommitManager interface {
	GetCommit(ctx context.Context, owner, repo, sha string) (*CommitInfo, error)
	ListCommits(ctx context.Context, owner, repo string, opts ListCommitsOptions) ([]*CommitInfo, error)
	CompareCommits(ctx context.Context, owner, repo, base, head string) (*CompareResult, error)
}

CommitManager handles commit operations.

Commit statuses are NOT part of CommitManager: they are a CI reporting concern that not every platform exposes (Gitee's public REST API has no commit-status endpoint). See the optional CommitStatusManager capability interface and CapabilitySet.CommitStatuses.

type CommitStatusManager added in v0.45.0

type CommitStatusManager interface {
	CreateCommitStatus(ctx context.Context, owner, repo, sha string, opts CommitStatusOptions) error
}

CommitStatusManager reports CI statuses on commits. It is an optional capability interface: consumers should gate on Provider.Capabilities().CommitStatuses (or type-assert) before use.

It is deliberately separate from CommitManager: commit statuses are a CI reporting concern that not every platform exposes (Gitee's public REST API has no commit-status endpoint), so absence is expressed by not declaring the capability instead of stubbing the method.

type CommitStatusOptions

type CommitStatusOptions struct {
	State       string `json:"state"`
	Context     string `json:"context"`
	Description string `json:"description,omitempty"`
	TargetURL   string `json:"target_url,omitempty"`
}

CommitStatusOptions contains options for creating a commit status.

type CompareResult

type CompareResult struct {
	Commits      []*CommitInfo  `json:"commits"`
	Files        []*ChangedFile `json:"files"`
	TotalCommits int            `json:"total_commits"`
	AheadBy      int            `json:"ahead_by"`
	BehindBy     int            `json:"behind_by"`
}

CompareResult represents the result of comparing two commits.

type Config

type Config struct {
	Platform Platform
	BaseURL  string
	Token    string
	SkipTLS  bool

	// Logger for provider operations. Defaults to a no-op logger.
	Logger Logger
	// RetryConfig for automatic retry on transient failures. nil means no retry.
	RetryConfig *RetryConfig
	// Hooks for request/response lifecycle interception.
	Hooks *Hooks
}

Config holds the configuration for creating a Provider.

type CreateCROptions

type CreateCROptions struct {
	Owner              string   `json:"owner"`
	Repo               string   `json:"repo"`
	Title              string   `json:"title"`
	Description        string   `json:"description,omitempty"`
	SourceBranch       string   `json:"source_branch"`
	TargetBranch       string   `json:"target_branch"`
	Labels             []string `json:"labels,omitempty"`
	RemoveSourceBranch bool     `json:"remove_source_branch,omitempty"`
}

CreateCROptions contains options for creating a change request.

type CreateIssueOptions

type CreateIssueOptions struct {
	Owner     string   `json:"owner"`
	Repo      string   `json:"repo"`
	Title     string   `json:"title"`
	Body      string   `json:"body,omitempty"`
	Assignees []string `json:"assignees,omitempty"`
	Labels    []string `json:"labels,omitempty"`
	Milestone string   `json:"milestone,omitempty"` // milestone number/ID as a string; "" = do not set
}

CreateIssueOptions contains options for creating an issue.

type CreateLabelOptions added in v0.38.0

type CreateLabelOptions struct {
	Name        string `json:"name"`
	Color       string `json:"color"`
	Description string `json:"description,omitempty"`
}

CreateLabelOptions contains options for creating a repository label. Color uses the canonical 6-digit hex form without '#' (e.g. "ff0000").

type CreateMilestoneOptions added in v0.40.0

type CreateMilestoneOptions struct {
	Title       string     `json:"title"`
	Description string     `json:"description,omitempty"`
	DueOn       *time.Time `json:"due_on,omitempty"`
}

CreateMilestoneOptions contains options for creating a repository milestone.

type CreateReleaseOptions

type CreateReleaseOptions struct {
	TagName    string `json:"tag_name"`
	Target     string `json:"target,omitempty"`
	Title      string `json:"title"`
	Body       string `json:"body,omitempty"`
	Draft      bool   `json:"draft,omitempty"`
	Prerelease bool   `json:"prerelease,omitempty"`
}

CreateReleaseOptions contains options for creating a release.

type CreateRepoOptions

type CreateRepoOptions struct {
	Name          string `json:"name"`
	Description   string `json:"description,omitempty"`
	Private       bool   `json:"private,omitempty"`
	AutoInit      bool   `json:"auto_init,omitempty"`
	DefaultBranch string `json:"default_branch,omitempty"`
}

CreateRepoOptions contains options for creating a repository.

type CreateReviewOptions

type CreateReviewOptions struct {
	CommitID string          `json:"commit_id,omitempty"`
	Event    string          `json:"event,omitempty"`
	Body     string          `json:"body,omitempty"`
	Comments []ReviewComment `json:"comments,omitempty"`
}

CreateReviewOptions contains options for creating a review.

type CreateWebhookOptions

type CreateWebhookOptions struct {
	Owner  string   `json:"owner"`
	Repo   string   `json:"repo"`
	URL    string   `json:"url"`
	Secret string   `json:"secret,omitempty"`
	Events []string `json:"events,omitempty"`
}

CreateWebhookOptions contains options for creating a webhook.

type DetectResult

type DetectResult struct {
	Platform Platform
	Owner    string
	Repo     string
	BaseURL  string
}

DetectResult holds the platform, owner, repo, and base API URL extracted from a git remote URL by DetectPlatform.

func DetectPlatform

func DetectPlatform(remoteURL string) (*DetectResult, error)

DetectPlatform parses a git remote URL (HTTPS, SSH, or ssh://) and returns the detected platform, owner, repo name, and base API URL. Returns ErrPlatformNotSupported for unrecognized hosts; use NewProvider with explicit Config for self-hosted instances not in the known-host list.

type DiffManager

type DiffManager interface {
	GetCRDiff(ctx context.Context, owner, repo, number string) (*MergeDiff, error)
	GetCRFiles(ctx context.Context, owner, repo, number string) ([]*ChangedFile, error)
	CreateNote(ctx context.Context, owner, repo, number, body string) (string, error)
	DeleteNote(ctx context.Context, owner, repo, number string, noteID string) error
	CreateDiscussion(ctx context.Context, owner, repo, number string, opts DiscussionOptions) (string, error)
}

DiffManager handles diff and discussion operations. Review operations (CreateReview and friends) live on the optional ReviewManager capability interface; DiffManager itself carries five methods. Change request numbers are strings (same addressing scheme as IssueManager); numeric platforms parse with strconv and fail with a wrapped "invalid pull request number" error.

type DiscussionOptions

type DiscussionOptions struct {
	Body         string `json:"body"`
	FilePath     string `json:"file_path,omitempty"`
	NewLine      int    `json:"new_line,omitempty"`
	OldLine      int    `json:"old_line,omitempty"`
	StartNewLine int    `json:"start_new_line,omitempty"`
	BaseSHA      string `json:"base_sha,omitempty"`
	StartSHA     string `json:"start_sha,omitempty"`
	HeadSHA      string `json:"head_sha,omitempty"`
}

DiscussionOptions contains options for creating a discussion comment.

type Divergence added in v0.45.0

type Divergence struct {
	Capability string
	Method     string
	Field      string
	Kind       DivergenceKind
	Reason     string
}

Divergence is one registered entry of a backend's divergence ledger. Capability and Method carry the provider interface and method names; Field names the affected option/result field for ignore and mapping entries (empty when the divergence is method-scoped). Reason is a one-sentence explanation surfaced in docs/divergence-ledger.md.

Backends expose their ledger via a package-level Divergences function and the Provider.Divergences method; the ledger is the machine-readable successor of the former "(spec §4.6)" comment registrations.

func FindByMethod added in v0.45.0

func FindByMethod(divs []Divergence, method string) []Divergence

FindByMethod returns the ledger entries registered for method.

type DivergenceKind added in v0.45.0

type DivergenceKind string

DivergenceKind classifies how a backend's behavior departs from the unified provider semantics for a given method.

const (
	// DivergenceStub marks a method the platform cannot serve at all: the
	// call returns an error wrapping ErrNotImplemented and touches no wire.
	DivergenceStub DivergenceKind = "stub"
	// DivergenceIgnore marks a field or parameter that is silently dropped:
	// the call succeeds but the ignored input has no effect.
	DivergenceIgnore DivergenceKind = "ignore"
	// DivergenceMapping marks a semantic mapping: the call succeeds and
	// returns the closest platform equivalent, an approximation of the
	// unified semantics.
	DivergenceMapping DivergenceKind = "mapping"
	// DivergenceDetour marks an implementation detour: the method bypasses
	// the platform's third-party SDK and drives the raw transport client.
	// Behavior is unchanged; the entry exists for maintainers.
	DivergenceDetour DivergenceKind = "detour"
)

type EventRepo

type EventRepo struct {
	ID       int64  `json:"id"`
	FullName string `json:"full_name"`
	Owner    string `json:"owner"`
	Name     string `json:"name"`
}

EventRepo represents the repository in a webhook event.

func BuildEventRepo

func BuildEventRepo(fullName string) *EventRepo

BuildEventRepo creates an EventRepo from a full name string.

type FileDeleteOptions

type FileDeleteOptions struct {
	Path    string `json:"path"`
	Message string `json:"message"`
	Branch  string `json:"branch,omitempty"`
	SHA     string `json:"sha,omitempty"`
	Author  string `json:"author,omitempty"`
	Email   string `json:"email,omitempty"`
}

FileDeleteOptions contains options for deleting a file.

type FileManager

type FileManager interface {
	GetFileContent(ctx context.Context, owner, repo, path, ref string) (string, error)
	CreateFile(ctx context.Context, owner, repo string, opts FileOptions) (*FileResult, error)
	UpdateFile(ctx context.Context, owner, repo string, opts FileOptions) (*FileResult, error)
	DeleteFile(ctx context.Context, owner, repo string, opts FileDeleteOptions) (*FileResult, error)
}

FileManager handles file CRUD operations on repositories.

type FileOptions

type FileOptions struct {
	Path    string `json:"path"`
	Content string `json:"content"`
	Message string `json:"message"`
	Branch  string `json:"branch,omitempty"`
	SHA     string `json:"sha,omitempty"`
	Author  string `json:"author,omitempty"`
	Email   string `json:"email,omitempty"`
}

FileOptions contains options for creating or updating a file.

type FileResult

type FileResult struct {
	SHA       string `json:"sha,omitempty"`
	CommitSHA string `json:"commit_sha,omitempty"`
}

FileResult is the result of a file operation.

type ForkRepoOptions

type ForkRepoOptions struct {
	Organization string `json:"organization,omitempty"`
	Name         string `json:"name,omitempty"`
}

ForkRepoOptions contains options for forking a repository.

type HMACSHA256Validator

type HMACSHA256Validator struct {
	Header string
}

HMACSHA256Validator verifies a "Header: sha256=<hex>" style signature using HMAC-SHA256 over the request body. The expected header is configurable so it works for GitHub (X-Hub-Signature-256), Gitea (X-Gitea-Signature), Gitee (X-Gitee-Token) and others.

func (HMACSHA256Validator) Name

func (HMACSHA256Validator) Name() string

Name implements WebhookValidator.

func (HMACSHA256Validator) Validate

func (h HMACSHA256Validator) Validate(r *http.Request, body []byte, secret string) error

Validate implements WebhookValidator. The signature must be exactly "sha256=<hex>" or just "<hex>". Comparison is done in constant time.

type HmacValidator

type HmacValidator struct {
	Header    string
	Algorithm string // "sha1", "sha256", "sha512"
	Prefix    string // expected signature prefix ("sha256=")
}

HmacValidator is a lower-level helper that supports arbitrary hash algorithms. It is intended for use by platform implementations that need something other than SHA-256.

func (*HmacValidator) Name

func (h *HmacValidator) Name() string

Name implements WebhookValidator.

func (*HmacValidator) Validate

func (h *HmacValidator) Validate(r *http.Request, body []byte, secret string) error

Validate implements WebhookValidator.

type Hooks

type Hooks struct {
	Request  []RequestHook
	Response []ResponseHook
}

Hooks holds request and response lifecycle hooks. These are mapped into transport.Hooks by each backend's constructor; direct callers should use the Hooks struct to register hooks via provider.Config.

func (*Hooks) AddRequestHook

func (h *Hooks) AddRequestHook(hook RequestHook)

AddRequestHook appends a request hook.

func (*Hooks) AddResponseHook

func (h *Hooks) AddResponseHook(hook ResponseHook)

AddResponseHook appends a response hook.

type Issue

type Issue struct {
	ID        int64         `json:"id"`
	Number    string        `json:"number"`
	Title     string        `json:"title"`
	Body      string        `json:"body"`
	State     IssueState    `json:"state"`
	Author    *CRUser       `json:"author,omitempty"`
	Labels    []string      `json:"labels,omitempty"`
	Assignees []string      `json:"assignees,omitempty"`
	Milestone *MilestoneRef `json:"milestone,omitempty"`
	WebURL    string        `json:"web_url,omitempty"`
	CreatedAt time.Time     `json:"created_at"`
	UpdatedAt time.Time     `json:"updated_at"`
	ClosedAt  *time.Time    `json:"closed_at,omitempty"`
}

Issue represents an issue on a platform. Number is the platform's issue identifier as a string (numeric on every current platform except Gitee, whose identifiers are alphanumeric).

type IssueComment

type IssueComment struct {
	ID        int64     `json:"id"`
	Body      string    `json:"body"`
	Author    *CRUser   `json:"author,omitempty"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

IssueComment represents a comment on an issue.

type IssueLabel

type IssueLabel struct {
	ID    int64  `json:"id"`
	Name  string `json:"name"`
	Color string `json:"color,omitempty"`
}

IssueLabel represents a label on a repository.

type IssueManager

type IssueManager interface {
	ListIssues(ctx context.Context, opts ListIssuesOptions) ([]*Issue, int, error)
	GetIssue(ctx context.Context, owner, repo, number string) (*Issue, error)
	CreateIssue(ctx context.Context, opts CreateIssueOptions) (*Issue, error)
	UpdateIssue(ctx context.Context, owner, repo, number string, opts UpdateIssueOptions) (*Issue, error)
	CloseIssue(ctx context.Context, owner, repo, number string) (*Issue, error)
	ReopenIssue(ctx context.Context, owner, repo, number string) (*Issue, error)
	ListIssueComments(ctx context.Context, owner, repo, number string) ([]*IssueComment, error)
	CreateIssueComment(ctx context.Context, owner, repo, number, body string) (*IssueComment, error)
	ListIssueLabels(ctx context.Context, owner, repo string) ([]*IssueLabel, error)
	AddIssueLabels(ctx context.Context, owner, repo, number string, labels []string) error
	RemoveIssueLabel(ctx context.Context, owner, repo, number, name string) error
}

IssueManager provides issue CRUD, comments, and label management. Issue numbers are strings: every platform address is representable as a string, and Gitee natively uses alphanumeric identifiers (e.g. "IAINVA"). Backends on numeric platforms parse with strconv.Atoi and fail with a wrapped "invalid issue number" error.

type IssueState

type IssueState string

IssueState represents the state of an issue.

const (
	IssueStateOpen   IssueState = "open"
	IssueStateClosed IssueState = "closed"
)

type Label added in v0.38.0

type Label struct {
	ID          int64  `json:"id"`
	Name        string `json:"name"`
	Color       string `json:"color,omitempty"`
	Description string `json:"description,omitempty"`
}

Label represents a repository label. Color is canonicalized to 6-digit hex without a leading '#' (e.g. "ff0000"); backends add the '#' when a platform requires it (GitLab, Gitea, Forgejo) and strip it on the way in.

type LabelManager added in v0.38.0

type LabelManager interface {
	// ListLabels lists the repository's labels.
	ListLabels(ctx context.Context, owner, repo string, opts ListLabelsOptions) ([]*Label, error)
	// CreateLabel creates a repository label.
	CreateLabel(ctx context.Context, owner, repo string, opts CreateLabelOptions) (*Label, error)
	// UpdateLabel updates the label with the given name. Nil fields in opts
	// are left unchanged.
	UpdateLabel(ctx context.Context, owner, repo, name string, opts UpdateLabelOptions) (*Label, error)
	// DeleteLabel deletes the label with the given name.
	DeleteLabel(ctx context.Context, owner, repo, name string) error
}

LabelManager provides repository-level label CRUD. It is an optional capability interface: consumers should gate on Provider.Capabilities() (or type-assert) before use. Labels are addressed by name; backends whose platform API addresses labels by numeric ID (GitLab, Gitea, Forgejo) resolve the name internally. Such backends scan labels with server-side pagination (100 per page, bounded to 50 pages); beyond that bound a label may be reported as not found by UpdateLabel/DeleteLabel even though it exists.

The issue-scoped operations (ListIssueLabels, AddIssueLabels, RemoveIssueLabel) remain on IssueManager because they operate on an issue, not on the repository's label set.

type ListCROptions

type ListCROptions struct {
	Owner        string  `json:"owner"`
	Repo         string  `json:"repo"`
	State        CRState `json:"state,omitempty"`
	SourceBranch string  `json:"source_branch,omitempty"`
	TargetBranch string  `json:"target_branch,omitempty"`
	Page         int     `json:"page,omitempty"`
	PerPage      int     `json:"per_page,omitempty"`
}

ListCROptions contains options for listing change requests.

type ListCommitsOptions

type ListCommitsOptions struct {
	Page    int    `json:"page,omitempty"`
	PerPage int    `json:"per_page,omitempty"`
	Branch  string `json:"branch,omitempty"`
	Since   string `json:"since,omitempty"` // RFC3339
	Until   string `json:"until,omitempty"` // RFC3339
}

ListCommitsOptions contains options for listing commits in a repository.

type ListIssuesOptions

type ListIssuesOptions struct {
	Owner    string     `json:"owner"`
	Repo     string     `json:"repo"`
	State    IssueState `json:"state,omitempty"`
	Assignee string     `json:"assignee,omitempty"`
	Labels   string     `json:"labels,omitempty"`
	Page     int        `json:"page,omitempty"`
	PerPage  int        `json:"per_page,omitempty"`
}

ListIssuesOptions contains options for listing issues.

type ListLabelsOptions added in v0.38.0

type ListLabelsOptions struct {
	Page    int `json:"page,omitempty"`
	PerPage int `json:"per_page,omitempty"`
}

ListLabelsOptions contains options for listing repository labels.

type ListMilestonesOptions added in v0.40.0

type ListMilestonesOptions struct {
	State   string `json:"state,omitempty"`
	Page    int    `json:"page,omitempty"`
	PerPage int    `json:"per_page,omitempty"`
}

ListMilestonesOptions contains options for listing repository milestones. State filters by "open" or "closed"; an empty State lists whatever the platform defaults to (GitHub/Gitea/Forgejo/Gitee default to open, GitLab to all). Tencent Code ignores State entirely — gongfeng's list options expose pagination only, so all states are listed.

type ListRepoOptions

type ListRepoOptions struct {
	Owner   string `json:"owner,omitempty"`
	Page    int    `json:"page,omitempty"`
	PerPage int    `json:"per_page,omitempty"`
}

ListRepoOptions contains options for listing repositories on a platform.

type Logger

type Logger interface {
	Debug(msg string, keysAndValues ...any)
	Info(msg string, keysAndValues ...any)
	Warn(msg string, keysAndValues ...any)
	Error(msg string, keysAndValues ...any)
}

Logger is a minimal logging interface compatible with most Go logging libraries. Implementations include slog, zap, zerolog, logrus, etc.

func NewNoopLogger

func NewNoopLogger() Logger

NewNoopLogger returns a Logger that discards all output.

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager provides a caching layer over Provider creation.

It automatically detects the platform from clone URLs and reuses existing Provider instances within the TTL window. The cache key is derived from platform + baseURL + a SHA-256 hash of the token, so different tokens map to different entries without leaking the token itself in logs or memory dumps.

func NewManager

func NewManager(ttl time.Duration, opts ...ManagerOption) *Manager

NewManager creates a new Provider Manager with the given TTL. A TTL of 0 means providers never expire (until the process exits).

func (*Manager) Cleanup

func (m *Manager) Cleanup()

Cleanup removes expired entries from the cache. Safe to call manually; also invoked periodically by StartJanitor.

func (*Manager) Get

func (m *Manager) Get(cfg Config) (Provider, error)

Get returns a cached or newly created Provider for the given config. The cache key is platform + baseURL + hash(token), so the same (platform, baseURL) with a different token gets a distinct entry.

func (*Manager) GetByURL

func (m *Manager) GetByURL(cloneURL, token string) (Provider, error)

GetByURL detects the platform from the clone URL and returns a cached or newly created Provider.

func (*Manager) Len

func (m *Manager) Len() int

Len returns the number of cached Providers.

func (*Manager) Purge

func (m *Manager) Purge()

Purge removes all cached Providers.

func (*Manager) Remove

func (m *Manager) Remove(cfg Config)

Remove removes a cached Provider by config.

func (*Manager) ResetStats

func (m *Manager) ResetStats()

ResetStats zeroes the hit/miss/eviction counters. Cache entries are not affected.

func (*Manager) StartJanitor

func (m *Manager) StartJanitor(ctx context.Context, interval time.Duration)

StartJanitor launches a background goroutine that calls Cleanup every interval until ctx is cancelled or Stop is called. Calling StartJanitor more than once without an intervening Stop is a no-op.

func (*Manager) Stats

func (m *Manager) Stats() Stats

Stats returns a snapshot of cache counters. The counters continue to accumulate across calls; reset them with ResetStats.

func (*Manager) Stop

func (m *Manager) Stop()

Stop halts the background janitor and blocks until it has exited.

type ManagerOption

type ManagerOption func(*Manager)

ManagerOption configures a Manager at construction time.

func WithHasher

func WithHasher(h func(token string) string) ManagerOption

WithHasher overrides the default SHA-256 token hasher. Useful for tests that want deterministic, human-readable keys.

func WithMaxSize

func WithMaxSize(n int) ManagerOption

WithMaxSize caps the cache at n entries. When the cap is reached, the least recently used entry is evicted before a new one is inserted.

type MergeCROptions

type MergeCROptions struct {
	MergeCommitMessage string `json:"merge_commit_message,omitempty"`
	Squash             bool   `json:"squash,omitempty"`
	RemoveSourceBranch bool   `json:"remove_source_branch,omitempty"`
}

MergeCROptions contains options for merging a change request.

type MergeDiff

type MergeDiff struct {
	Files    []*ChangedFile
	TotalAdd int
	TotalDel int
	RawDiff  string
}

MergeDiff represents the diff of a change request.

type Milestone added in v0.40.0

type Milestone struct {
	Number      string         `json:"number"`
	Title       string         `json:"title"`
	Description string         `json:"description"`
	State       MilestoneState `json:"state"`
	DueOn       *time.Time     `json:"due_on,omitempty"`
}

Milestone represents a repository milestone. Number carries the platform's milestone addressing identifier as a string — the same value MilestoneRef.Number uses and MilestoneManager methods accept: the milestone number on GitHub, the platform milestone ID on GitLab, Gitea, Forgejo, GitCode, and Tencent Code, and the milestone serial number on Gitee (see MilestoneManager for the per-platform truth).

type MilestoneManager added in v0.40.0

type MilestoneManager interface {
	// ListMilestones lists the repository's milestones.
	ListMilestones(ctx context.Context, owner, repo string, opts ListMilestonesOptions) ([]Milestone, error)
	// GetMilestone fetches the milestone with the given number.
	GetMilestone(ctx context.Context, owner, repo, number string) (*Milestone, error)
	// CreateMilestone creates a repository milestone.
	CreateMilestone(ctx context.Context, owner, repo string, opts CreateMilestoneOptions) (*Milestone, error)
	// UpdateMilestone updates the milestone with the given number. Nil
	// fields in opts are left unchanged.
	UpdateMilestone(ctx context.Context, owner, repo, number string, opts UpdateMilestoneOptions) (*Milestone, error)
	// DeleteMilestone deletes the milestone with the given number.
	DeleteMilestone(ctx context.Context, owner, repo, number string) error
}

MilestoneManager provides repository-level milestone CRUD. It is an optional capability interface: consumers should gate on Provider.Capabilities() (or type-assert) before use.

Milestones are addressed by a string `number`, but what that string carries is platform-specific — the same identifier MilestoneRef.Number and Milestone.Number expose:

  • GitHub: the milestone *number* (its per-repo serial number).
  • GitLab, Gitea, Forgejo, GitCode, Tencent Code: the platform milestone *ID* (the write endpoints take exactly that identifier, so per-platform round-trips hold).
  • Gitee: the milestone *serial number* (the "number" field of Gitee's milestone payload — the identifier Gitee's own issue and milestone write endpoints take; the SDK model exposes no id).

Values obtained from MilestoneRef.Number (issue payloads) or Milestone.Number (list/get results) round-trip back into these methods on the platform they came from.

type MilestoneRef added in v0.39.0

type MilestoneRef struct {
	Number string `json:"number"`
	Title  string `json:"title,omitempty"`
}

MilestoneRef references a milestone from an issue. Number carries the platform's milestone addressing identifier as a string: the milestone *number* on GitHub, the platform milestone *ID* on GitLab, Gitea, Forgejo, GitCode, and Tencent Code (whose write endpoints take exactly that identifier, so per-platform round-trips hold), and Gitee's milestone *serial number* (the "number" field of Gitee's milestone payload — the identifier Gitee's own issue and milestone write endpoints take; the SDK model exposes no id). This is the same identifier Milestone.Number exposes and MilestoneManager methods accept, so refs round-trip through the milestone manager on the platform they came from.

type MilestoneState added in v0.40.0

type MilestoneState string

MilestoneState represents the state of a milestone.

const (
	MilestoneStateOpen   MilestoneState = "open"
	MilestoneStateClosed MilestoneState = "closed"
)

type NormalizedEvent

type NormalizedEvent struct {
	ID         string          `json:"id"`
	Type       string          `json:"type"`
	Source     Platform        `json:"source"`
	Timestamp  time.Time       `json:"timestamp"`
	Actor      *CRUser         `json:"actor"`
	Repo       *EventRepo      `json:"repo"`
	CR         *ChangeRequest  `json:"cr,omitempty"`
	Branch     string          `json:"branch,omitempty"`
	Tag        string          `json:"tag,omitempty"`
	CommitSHA  string          `json:"commit_sha,omitempty"`
	Action     string          `json:"action,omitempty"`
	RawPayload json.RawMessage `json:"raw_payload"`
}

NormalizedEvent represents a normalized webhook event from any platform.

type Platform

type Platform string

Platform represents a Git hosting platform.

const (
	PlatformGitLab      Platform = "gitlab"
	PlatformGitHub      Platform = "github"
	PlatformGitea       Platform = "gitea"
	PlatformGitee       Platform = "gitee"
	PlatformForgejo     Platform = "forgejo"
	PlatformTencentCode Platform = "tencent_code"
	PlatformGitCode     Platform = "gitcode"
)

func RegisteredPlatforms

func RegisteredPlatforms() []Platform

RegisteredPlatforms returns a list of all registered platforms.

type PlatformBranch

type PlatformBranch struct {
	Name string `json:"name"`
}

PlatformBranch represents a branch on a platform.

type PlatformRepo

type PlatformRepo struct {
	ID            int64    `json:"id"`
	FullName      string   `json:"full_name"`
	Name          string   `json:"name"`
	Owner         string   `json:"owner"`
	Description   string   `json:"description"`
	CloneURL      string   `json:"clone_url"`
	SSHURL        string   `json:"ssh_url"`
	DefaultBranch string   `json:"default_branch"`
	Private       bool     `json:"private"`
	Platform      Platform `json:"platform"`
}

PlatformRepo represents a repository on a platform.

type PlatformWebhook

type PlatformWebhook struct {
	ID     int64    `json:"id"`
	URL    string   `json:"url"`
	Events []string `json:"events"`
}

PlatformWebhook represents a webhook on a platform.

type Provider

type Provider interface {
	// Platform returns the platform type.
	Platform() Platform
	// TestConnection verifies the connection and checks capabilities.
	TestConnection(ctx context.Context) (*TestConnectionResult, error)
	// Capabilities statically declares the optional capability interfaces
	// this provider implements. See CapabilitySet.
	Capabilities() CapabilitySet
	// Divergences statically declares this backend's divergence ledger: the
	// registered places where its behavior departs from the unified
	// semantics (stub / ignore / mapping / detour). Consumers can route on
	// these entries — e.g. provider.Ignores — and docs/divergence-ledger.md
	// is generated from them. Like CapabilitySet this is a compile-time
	// declaration; the contract suite locks ledger entries to behavior.
	Divergences() []Divergence

	RepoManager
	ChangeRequestManager
	WebhookManager
	BranchManager
	DiffManager
	CommitManager
	FileManager
	ReleaseManager
}

Provider is the unified interface for all Git hosting platforms. It composes 8 focused sub-interfaces for high cohesion and low coupling.

Consumers can depend on smaller interfaces (e.g., WebhookManager) when they don't need full Provider capabilities.

IssueManager, SearchManager, and CommitStatusManager are NOT part of Provider: only some platforms support them. Consumers that need issues, search, or commit statuses should type-assert against the optional capability interfaces:

if ism, ok := p.(provider.IssueManager); ok { ... }
if sm, ok := p.(provider.SearchManager); ok { ... }
if csm, ok := p.(provider.CommitStatusManager); ok { ... }

Caps declares the same information programmatically: consumers can route
on p.Capabilities() instead of probing with type assertions.

func NewProvider

func NewProvider(cfg Config) (Provider, error)

NewProvider creates a Provider for the given platform using the registry. Returns ErrPlatformNotSupported if the platform is not registered.

Platform backends are registered via init() functions. Import "github.com/yi-nology/git-platform-sdk/backends/all" with a blank identifier to register every platform shipped with the SDK.

type ProviderConstructor

type ProviderConstructor func(cfg Config) (Provider, error)

ProviderConstructor is a function that creates a Provider from a Config.

type ProviderError

type ProviderError struct {
	Platform   Platform
	Op         string // operation name, e.g., "ListRepos"
	Resource   string // optional resource identifier, e.g., "owner/repo"
	StatusCode int    // 0 when not applicable (e.g. configuration errors)
	Cause      error  // underlying cause; nil when constructed from raw fields
}

ProviderError is a structured error from a provider operation. It carries enough context (platform, op, resource, status code, cause) to support logging, retry, and user-facing messages. It implements errors.Is so the sentinel errors above are matched by Cause, and errors.As for typed access.

func (*ProviderError) Error

func (e *ProviderError) Error() string

Error implements the error interface.

func (*ProviderError) Is

func (e *ProviderError) Is(target error) bool

Is implements errors.Is. It matches when the wrapped Cause equals the target, which lets callers write `errors.Is(err, provider.ErrNotFound)`.

func (*ProviderError) IsClientError

func (e *ProviderError) IsClientError() bool

IsClientError reports 4xx.

func (*ProviderError) IsServerError

func (e *ProviderError) IsServerError() bool

IsServerError reports 5xx.

func (*ProviderError) IsStatus

func (e *ProviderError) IsStatus(code int) bool

IsStatus reports whether the error has the given HTTP status code.

func (*ProviderError) Unwrap

func (e *ProviderError) Unwrap() error

Unwrap implements errors.Unwrap.

type ReleaseInfo

type ReleaseInfo struct {
	ID          int64     `json:"id"`
	TagName     string    `json:"tag_name"`
	Title       string    `json:"title"`
	Body        string    `json:"body"`
	URL         string    `json:"url"`
	Draft       bool      `json:"draft"`
	Prerelease  bool      `json:"prerelease"`
	CreatedAt   time.Time `json:"created_at"`
	PublishedAt time.Time `json:"published_at"`
}

ReleaseInfo represents a release.

type ReleaseManager

type ReleaseManager interface {
	ListTags(ctx context.Context, owner, repo string) ([]*TagInfo, error)
	ListReleases(ctx context.Context, owner, repo string) ([]*ReleaseInfo, error)
	CreateRelease(ctx context.Context, owner, repo string, opts CreateReleaseOptions) (*ReleaseInfo, error)
	GetReleaseByTag(ctx context.Context, owner, repo, tag string) (*ReleaseInfo, error)
	UpdateRelease(ctx context.Context, owner, repo, tag string, opts UpdateReleaseOptions) (*ReleaseInfo, error)
	DeleteRelease(ctx context.Context, owner, repo, tag string) error
	GetArchive(ctx context.Context, owner, repo, ref, format string) ([]byte, error)
}

ReleaseManager handles tags, releases, and archives. Releases are addressed by tag name across every method: tag names are stable and human-addressable, while the underlying numeric release IDs are not.

type RepoManager

type RepoManager interface {
	ListRepos(ctx context.Context, opts ListRepoOptions) ([]*PlatformRepo, error)
	GetRepo(ctx context.Context, owner, repo string) (*PlatformRepo, error)
	CreateRepo(ctx context.Context, owner string, opts CreateRepoOptions) (*PlatformRepo, error)
	DeleteRepo(ctx context.Context, owner, repo string) error
	UpdateRepo(ctx context.Context, owner, repo string, opts UpdateRepoOptions) (*PlatformRepo, error)
	ForkRepo(ctx context.Context, owner, repo string, opts ForkRepoOptions) (*PlatformRepo, error)
}

RepoManager handles repository CRUD operations.

type RequestHook

type RequestHook func(ctx context.Context, req *http.Request) context.Context

RequestHook is called before an HTTP request is sent. It can modify the context (e.g., add tracing headers) or inspect the request.

type ResponseHook

type ResponseHook func(ctx context.Context, req *http.Request, resp *http.Response, duration time.Duration, err error)

ResponseHook is called after an HTTP response is received.

type RetryConfig

type RetryConfig struct {
	// MaxRetries is the maximum number of retry attempts (not counting the
	// initial request). <= 0 disables retry.
	MaxRetries int
	// BaseDelay is the initial backoff delay before the first retry.
	BaseDelay time.Duration
	// MaxDelay caps the backoff delay. Zero means 30s (the transport
	// default).
	MaxDelay time.Duration
	// RetryOn lists extra HTTP status codes to retry on, in addition to the
	// transport's default set (429 and 5xx).
	RetryOn []int
}

RetryConfig controls automatic retry behavior for HTTP requests issued by the transport layer. It is the public-facing configuration type passed via provider.Config; the transport package has its own internal transport.RetryConfig that this is mapped into.

func DefaultRetryConfig

func DefaultRetryConfig() RetryConfig

DefaultRetryConfig returns a sensible default retry configuration: 3 retries, 500ms base delay, 30s cap, no extra status codes.

type Review added in v0.40.0

type Review struct {
	ID          int64       `json:"id"`
	User        string      `json:"user"`
	State       ReviewState `json:"state"`
	Body        string      `json:"body"`
	SubmittedAt time.Time   `json:"submitted_at"`
}

Review represents a code review on a change request (the ReviewManager view; ReviewResult above is the create-call response).

type ReviewComment

type ReviewComment struct {
	Path      string `json:"path"`
	Body      string `json:"body"`
	Line      int    `json:"line,omitempty"`
	StartLine int    `json:"start_line,omitempty"`
	EndLine   int    `json:"end_line,omitempty"`
	Side      string `json:"side,omitempty"`
}

ReviewComment is a single inline comment in a code review.

type ReviewCommentResult

type ReviewCommentResult struct {
	Path       string `json:"path,omitempty"`
	Line       int    `json:"line,omitempty"`
	ExternalID string `json:"external_id,omitempty"`
	Error      string `json:"error,omitempty"`
}

ReviewCommentResult is the result of posting a single inline comment.

type ReviewManager added in v0.40.0

type ReviewManager interface {
	CreateReview(ctx context.Context, owner, repo, number string, opts CreateReviewOptions) (*ReviewResult, error)
	ListReviews(ctx context.Context, owner, repo, number string) ([]Review, error)
	GetReview(ctx context.Context, owner, repo, number string, reviewID int64) (*Review, error)
	RequestReviewers(ctx context.Context, owner, repo, number string, reviewers []string) error
	DismissReview(ctx context.Context, owner, repo, number string, reviewID int64, message string) error
}

ReviewManager provides code-review operations on change requests. Change request numbers are strings (same addressing scheme as IssueManager); individual reviews are addressed by their numeric platform ID. It is an optional capability: consumers should check Capabilities().Reviews before type-asserting.

type ReviewResult

type ReviewResult struct {
	ID       string                `json:"id"`
	Body     string                `json:"body,omitempty"`
	HTMLURL  string                `json:"html_url,omitempty"`
	User     *CRUser               `json:"user,omitempty"`
	Comments []ReviewCommentResult `json:"comments,omitempty"`
}

ReviewResult is the result of a CreateReview call.

type ReviewState added in v0.40.0

type ReviewState string

ReviewState is the normalized state of a code review.

const (
	ReviewStateApproved         ReviewState = "approved"
	ReviewStateChangesRequested ReviewState = "changes_requested"
	ReviewStateCommented        ReviewState = "commented"
	ReviewStatePending          ReviewState = "pending"
)

type SearchIssueResult

type SearchIssueResult struct {
	Number    string     `json:"number"`
	Title     string     `json:"title"`
	Body      string     `json:"body,omitempty"`
	State     IssueState `json:"state"`
	WebURL    string     `json:"web_url,omitempty"`
	Labels    []string   `json:"labels,omitempty"`
	Comments  int        `json:"comments,omitempty"`
	CreatedAt time.Time  `json:"created_at"`
}

SearchIssueResult is a single result from an issue search. Number is the platform's issue addressing identifier as a string, so results feed GetIssue(number string) directly (numeric platforms return "1", Gitee's alphanumeric identifiers return e.g. "IAINVA").

type SearchIssuesOptions

type SearchIssuesOptions struct {
	Query   string `json:"q"`
	Repo    string `json:"repo,omitempty"`
	State   string `json:"state,omitempty"`
	Sort    string `json:"sort,omitempty"`
	Order   string `json:"order,omitempty"`
	Page    int    `json:"page,omitempty"`
	PerPage int    `json:"per_page,omitempty"`
}

SearchIssuesOptions contains options for searching issues.

type SearchManager

type SearchManager interface {
	SearchRepos(ctx context.Context, opts SearchReposOptions) ([]*SearchRepoResult, *int, error)
	SearchIssues(ctx context.Context, opts SearchIssuesOptions) ([]*SearchIssueResult, *int, error)
	SearchUsers(ctx context.Context, opts SearchUsersOptions) ([]*SearchUserResult, *int, error)
}

SearchManager provides cross-platform search for repositories, issues, and users.

The *int return is the server-side total when the platform reports one, and nil when it does not — callers must not treat a total as guaranteed.

type SearchRepoResult

type SearchRepoResult struct {
	FullName      string `json:"full_name"`
	Description   string `json:"description,omitempty"`
	WebURL        string `json:"web_url,omitempty"`
	Stars         int    `json:"stars,omitempty"`
	Forks         int    `json:"forks,omitempty"`
	DefaultBranch string `json:"default_branch,omitempty"`
	Private       bool   `json:"private,omitempty"`
}

SearchRepoResult is a single result from a repository search.

type SearchReposOptions

type SearchReposOptions struct {
	Query   string `json:"q"`
	Sort    string `json:"sort,omitempty"`
	Order   string `json:"order,omitempty"`
	Page    int    `json:"page,omitempty"`
	PerPage int    `json:"per_page,omitempty"`
}

SearchReposOptions contains options for searching repositories.

Sort and Order are platform-dependent: each backend forwards them to its platform's own vocabulary (e.g. GitHub's stars/forks/updated with asc/desc), so values valid on one platform may be ignored or rejected on another (gitea/forgejo reject unknown sort/order values with HTTP 422; gitlab's search API exposes no sort/order at all — a registered ignore). Consult the target platform's search documentation for the accepted values.

type SearchUserResult

type SearchUserResult struct {
	Login     string `json:"login"`
	Name      string `json:"name,omitempty"`
	AvatarURL string `json:"avatar_url,omitempty"`
	WebURL    string `json:"web_url,omitempty"`
}

SearchUserResult is a single result from a user search.

type SearchUsersOptions

type SearchUsersOptions struct {
	Query   string `json:"q"`
	Sort    string `json:"sort,omitempty"`
	Order   string `json:"order,omitempty"`
	Page    int    `json:"page,omitempty"`
	PerPage int    `json:"per_page,omitempty"`
}

SearchUsersOptions contains options for searching users.

type StaticTokenValidator

type StaticTokenValidator struct {
	Header string
}

StaticTokenValidator compares a static token header against the configured secret in constant time. Used for GitLab's X-Gitlab-Token.

func (StaticTokenValidator) Name

Name implements WebhookValidator.

func (StaticTokenValidator) Validate

func (s StaticTokenValidator) Validate(r *http.Request, body []byte, secret string) error

Validate implements WebhookValidator.

type Stats

type Stats struct {
	Hits      int64
	Misses    int64
	Evictions int64
	Size      int
}

Stats reports cache hit/miss counters and the current size. Counters are atomically incremented and safe to read concurrently.

type StatusError

type StatusError struct {
	Status int
	Cause  error
}

StatusError wraps an error with an explicit HTTP status code. Use this in platform backends when you need to attach a status code to an error from a third-party SDK that doesn't implement the statusCoder interface. This avoids the need for the reflection-based fallback in Wrap.

Example:

err := someSDK.DoSomething()
if err != nil {
    return provider.WrapStatusError(err, 404)
}

func (*StatusError) Error

func (e *StatusError) Error() string

func (*StatusError) StatusCode

func (e *StatusError) StatusCode() int

func (*StatusError) Unwrap

func (e *StatusError) Unwrap() error

type TagInfo

type TagInfo struct {
	Name   string `json:"name"`
	Commit string `json:"commit"`
}

TagInfo represents a tag.

type TestConnectionResult

type TestConnectionResult struct {
	Connected    bool   `json:"connected"`
	Platform     string `json:"platform"`
	UserName     string `json:"user_name"`
	Message      string `json:"message,omitempty"`
	CanListRepos bool   `json:"can_list_repos"`
	CanReadCR    bool   `json:"can_read_cr"`
	CanWriteCR   bool   `json:"can_write_cr"`
	CanWebhook   bool   `json:"can_webhook"`
}

TestConnectionResult contains the result of a connection test.

type UpdateCROptions

type UpdateCROptions struct {
	Title        string `json:"title,omitempty"`
	Description  string `json:"description,omitempty"`
	TargetBranch string `json:"target_branch,omitempty"`
}

UpdateCROptions contains options for updating a change request.

type UpdateIssueOptions

type UpdateIssueOptions struct {
	Title     string     `json:"title,omitempty"`
	Body      string     `json:"body,omitempty"`
	State     IssueState `json:"state,omitempty"`
	Assignees []string   `json:"assignees,omitempty"`
	Labels    []string   `json:"labels,omitempty"`
	Milestone string     `json:"milestone,omitempty"` // milestone number/ID as a string; "" = leave unchanged
}

UpdateIssueOptions contains options for updating an issue.

type UpdateLabelOptions added in v0.38.0

type UpdateLabelOptions struct {
	NewName     *string `json:"new_name,omitempty"`
	Color       *string `json:"color,omitempty"`
	Description *string `json:"description,omitempty"`
}

UpdateLabelOptions contains options for updating a repository label. Nil fields are left unchanged.

type UpdateMilestoneOptions added in v0.40.0

type UpdateMilestoneOptions struct {
	Title       *string        `json:"title,omitempty"`
	Description *string        `json:"description,omitempty"`
	State       MilestoneState `json:"state,omitempty"`
	DueOn       *time.Time     `json:"due_on,omitempty"`
}

UpdateMilestoneOptions contains options for updating a repository milestone. Nil fields are left unchanged.

type UpdateReleaseOptions added in v0.40.0

type UpdateReleaseOptions struct {
	Name       *string `json:"name,omitempty"`
	Body       *string `json:"body,omitempty"`
	Draft      *bool   `json:"draft,omitempty"`
	Prerelease *bool   `json:"prerelease,omitempty"`
}

UpdateReleaseOptions contains options for updating a release addressed by tag. Nil fields are left unchanged.

type UpdateRepoOptions

type UpdateRepoOptions struct {
	Name          string `json:"name,omitempty"`
	Description   string `json:"description,omitempty"`
	DefaultBranch string `json:"default_branch,omitempty"`
	Private       *bool  `json:"private,omitempty"`
}

UpdateRepoOptions contains options for updating a repository.

type ValidatorFunc

type ValidatorFunc struct {
	N  string
	Fn func(r *http.Request, body []byte, secret string) error
}

ValidatorFunc adapts a plain function into a WebhookValidator.

func (ValidatorFunc) Name

func (v ValidatorFunc) Name() string

Name implements WebhookValidator.

func (ValidatorFunc) Validate

func (v ValidatorFunc) Validate(r *http.Request, body []byte, secret string) error

Validate implements WebhookValidator.

type WebhookManager

type WebhookManager interface {
	CreateWebhook(ctx context.Context, opts CreateWebhookOptions) (*PlatformWebhook, error)
	DeleteWebhook(ctx context.Context, owner, repo string, webhookID int64) error
	ListWebhooks(ctx context.Context, owner, repo string) ([]*PlatformWebhook, error)
	ParseWebhookEvent(r *http.Request, secret string) (*NormalizedEvent, error)
	ValidateWebhookSignature(r *http.Request, secret string) error
}

WebhookManager handles webhook CRUD and event parsing.

type WebhookValidator

type WebhookValidator interface {
	Name() string
	Validate(r *http.Request, body []byte, secret string) error
}

WebhookValidator verifies the authenticity of an incoming webhook request. Implementations are stateless and safe for concurrent use.

The signature scheme varies per platform:

  • GitHub: HMAC-SHA256 of the body, sent in X-Hub-Signature-256.
  • GitLab: static token compared in constant time against X-Gitlab-Token.
  • Gitea / Forgejo: HMAC-SHA256 of the body, sent in X-Gitea-Signature.
  • Gitee / GitCode / Tencent: HMAC-SHA256 of the body, sent in X-Gitee-Token / X-Token.

type WebhookValidatorRegistry

type WebhookValidatorRegistry struct {
	// contains filtered or unexported fields
}

WebhookValidatorRegistry indexes WebhookValidator implementations by platform. It is safe for concurrent use; registrations happen during package init and reads happen on the request path.

func DefaultWebhookRegistry

func DefaultWebhookRegistry() *WebhookValidatorRegistry

DefaultWebhookRegistry returns the process-wide registry.

func NewWebhookValidatorRegistry

func NewWebhookValidatorRegistry() *WebhookValidatorRegistry

NewWebhookValidatorRegistry builds an empty registry.

func (*WebhookValidatorRegistry) Get

Get returns the validator for the given platform, or nil if none is registered.

func (*WebhookValidatorRegistry) Register

Register associates a validator with a platform.

func (*WebhookValidatorRegistry) Validate

func (r *WebhookValidatorRegistry) Validate(p Platform, req *http.Request, body []byte, secret string) error

Validate looks up the validator for the given platform and runs it. A nil validator or missing platform produces ErrNotImplemented.

Jump to

Keyboard shortcuts

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