gitprovider

package
v0.9.2 Latest Latest
Warning

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

Go to latest
Published: Nov 6, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package gitprovider holds the small slice of REST-client plumbing that is genuinely identical across internal/githubapp, internal/gitlabapp, and internal/bitbucketapp: sending a built request and turning its response into either a decoded value or a uniform API error. Request construction (auth scheme, headers, pagination shape) stays in each provider's own package, since that is exactly where the three providers' real, non-coincidental differences live.

Index

Constants

View Source
const AllowPrivateEnv = "APP_GIT_ALLOW_PRIVATE_NETWORKS"

AllowPrivateEnv lets git provider clients reach internal addresses, for example GitHub Enterprise or Bitbucket Server on a private network.

View Source
const CommentPageSize = 100

CommentPageSize is the page size every provider's comment listing asks for.

View Source
const MaxCommentPages = 10

MaxCommentPages bounds how many pages a comment lookup walks, so a PR with a huge thread cannot turn one status update into unbounded requests.

View Source
const MaxErrorBodySnippet = 512

MaxErrorBodySnippet caps how much of a non-2xx response body an APIError retains, so a misbehaving upstream can't inflate a log line unboundedly.

Variables

This section is empty.

Functions

func Execute

func Execute(client *http.Client, req *http.Request, prefix, api, label string, out any) error

Execute sends req and, on a 2xx response, decodes its body into out (skipped when out is nil). prefix and api identify the caller for both wrapped errors and a returned *APIError's own message; label is the method/URL text those wrapped errors describe, since GitHub's own caller wraps a relative path while GitLab's and Bitbucket's wrap a full URL.

func ExecuteETag

func ExecuteETag(client *http.Client, req *http.Request, prefix, api, label, etag string, out any) (newETag string, notModified bool, err error)

ExecuteETag is Execute with conditional-request support: a non-empty etag is sent as If-None-Match, a 304 reply returns notModified true with out untouched, and the response's own ETag is returned for the next call.

func IsNotFound

func IsNotFound(err error) bool

IsNotFound reports whether err is a provider 404, meaning the resource (typically a comment an operator deleted) no longer exists.

func IsRateLimited

func IsRateLimited(err error) (retryAfter string, ok bool)

IsRateLimited reports whether err is a provider API error caused by rate limiting, and the Retry-After value it carried, if any.

func NewGuardedClient

func NewGuardedClient() *http.Client

NewGuardedClient returns an SSRF-guarded HTTP client with the shared git provider timeout.

func ParseRetryAfter

func ParseRetryAfter(v string, now time.Time) (time.Duration, bool)

ParseRetryAfter reads a Retry-After header: delta seconds or an HTTP date.

func WithRetry

func WithRetry(ctx context.Context, p RetryPolicy, provider string, fn func() error) error

WithRetry runs fn, retrying a rate-limited failure up to p.Retries times when the provider's Retry-After fits within p.MaxWait. Otherwise it returns a *RateLimitError with the next-check time. Other errors pass through unchanged.

Types

type APIError

type APIError struct {
	Prefix     string
	API        string
	StatusCode int
	Body       string
	// RetryAfter is the response's Retry-After header, empty when absent.
	RetryAfter string
	// RateLimited is true for a 429, or a 403 the provider marks as rate
	// limited (an exhausted X-RateLimit-Remaining or a "rate limit" body).
	RateLimited bool
}

APIError is returned for any non-2xx response from a git provider's REST API. Prefix and API identify the caller (e.g. "gitlabapp", "gitlab") so Error() reproduces that client's own message shape.

func (*APIError) Error

func (e *APIError) Error() string

type Comment

type Comment struct {
	ID   int64
	Body string
}

Comment is one pull request comment as the preview upsert sees it.

type ListOptions

type ListOptions struct {
	// MaxItems stops paging once this many items are collected (0 = no cap).
	MaxItems int
	Retry    RetryPolicy
}

ListOptions bounds a paginated repository listing.

func (ListOptions) Reached

func (o ListOptions) Reached(n int) bool

Reached reports whether n collected items meets the cap.

type ListResult

type ListResult struct {
	// Truncated is true when the MaxItems cap stopped paging while the
	// provider still had more.
	Truncated bool
}

ListResult reports how a paginated listing ended.

type RateLimitError

type RateLimitError struct {
	Provider   string
	RetryAfter time.Duration
	NextCheck  time.Time
	Err        error
}

RateLimitError is returned once a bounded retry gave up on a rate limit. NextCheck is when the provider said (or the default backoff implies) a call may succeed again.

func AsRateLimit

func AsRateLimit(err error) (*RateLimitError, bool)

AsRateLimit reports whether err is (or wraps) a RateLimitError.

func (*RateLimitError) Error

func (e *RateLimitError) Error() string

func (*RateLimitError) Unwrap

func (e *RateLimitError) Unwrap() error

type RetryPolicy

type RetryPolicy struct {
	Retries        int
	MaxWait        time.Duration
	DefaultBackoff time.Duration
	Sleep          func(ctx context.Context, d time.Duration) error
	Now            func() time.Time
}

RetryPolicy bounds how a rate-limited provider call is retried inside one request. A Retry-After longer than MaxWait is not slept on: the caller gets a RateLimitError carrying the next-check time instead.

func RetryPolicyFromEnv

func RetryPolicyFromEnv() RetryPolicy

RetryPolicyFromEnv reads the retry bounds from APP_GIT_RATE_LIMIT_*.

Jump to

Keyboard shortcuts

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