githubobserver

package
v0.182.3 Latest Latest
Warning

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

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

Documentation

Index

Constants

View Source
const DefaultMaxPages = 100

DefaultMaxPages bounds a paginated read. GitHub's own maximum page size is 100, so this is 10 000 items — far past anything WB reads — and exists only so a malformed or looping `link` header cannot make a verb run forever.

Variables

View Source
var ErrTransientMutationOutcomeUnknown = errors.New("github transient mutation outcome unknown")

ErrTransientMutationOutcomeUnknown marks a GitHub write whose command failed for a transient transport/provider reason. WB must not blindly retry the mutation: GitHub may have accepted it before the response was lost. Callers first re-read authoritative state, then leave the operation resumable when that read cannot prove the write landed.

View Source
var ErrTransientRetriesExhausted = errors.New("github transient read retries exhausted")

ErrTransientRetriesExhausted marks an error returned after every in-process retry attempt for a transient GitHub read failure was exhausted (attempt cap or elapsed budget). Callers that can name a resumable command (for example `wb pr land` or `wb ci wait`) should check for it with errors.Is and append that guidance; the observer package has no such context.

Functions

func IsTransientCommandFailure added in v0.150.2

func IsTransientCommandFailure(ctx context.Context, response CommandResponse) bool

IsTransientCommandFailure applies the observer's existing transient transport/provider classification to a single non-read command result. It classifies only; it never retries a mutation whose outcome may be unknown.

func NextPageEndpoint added in v0.89.0

func NextPageEndpoint(headers map[string]string) string

NextPageEndpoint extracts the rel="next" URL from a GitHub link header. It returns "" when there is no next page, which is the ordinary end of a walk.

func Read

func Read(ctx context.Context, dir string, args ...string) ([]byte, error)

func WithProgress added in v0.96.6

func WithProgress(ctx context.Context, reporter progress.Reporter) context.Context

WithProgress attaches one transport-neutral progress sink to GitHub reads made below ctx. An explicit GetRequest.Progress takes precedence.

func WithReader added in v0.175.0

func WithReader(ctx context.Context, reader Reader) context.Context

WithReader makes every Get, GetPages and Execute below ctx go to reader.

func WithRetryTelemetry added in v0.120.0

func WithRetryTelemetry(ctx context.Context, telemetry *RetryTelemetry) context.Context

WithRetryTelemetry attaches a RetryTelemetry accumulator to ctx. Every retried GitHub read (Get/apiGet and Read) made below the returned context increments it, so a caller can report `github_read_retries` on its own receipt after the call returns, whether the call ultimately succeeded or failed.

Types

type CommandResponse

type CommandResponse struct {
	Stdout   []byte
	Stderr   []byte
	ExitCode int
	Err      error
}

func Execute

func Execute(ctx context.Context, dir string, args ...string) CommandResponse

type GetRequest

type GetRequest struct {
	Dir         string
	Repository  string
	Target      string
	Head        string
	Endpoint    string
	Query       map[string]string
	Accept      string
	FreshWindow time.Duration
	Progress    progress.Reporter
}

type Observer

type Observer struct {
	StateDir    string
	Now         func() time.Time
	Sleep       func(context.Context, time.Duration) error
	RandomIntn  func(int64) int64
	Run         func(context.Context, string, ...string) commandResult
	MaxAttempts int
	BaseBackoff time.Duration
	MaxBackoff  time.Duration
	// MinAPIAttemptTimeout floors the per-attempt exec timeout for `gh api`
	// and `gh pr view` commands. Defaults to defaultMinAPIAttemptTimeout (30s)
	// when unset; never applied when the caller's own context already carries
	// an explicit deadline, which remains authoritative.
	MinAPIAttemptTimeout time.Duration
	// MaxRetryElapsed caps the total wall-clock time spent retrying a single
	// GitHub read across all attempts. Defaults to defaultMaxRetryElapsed
	// (45s) when unset.
	MaxRetryElapsed time.Duration
}

func Default

func Default() *Observer

func (*Observer) Execute

func (o *Observer) Execute(ctx context.Context, dir string, args ...string) CommandResponse

func (*Observer) Get

func (o *Observer) Get(ctx context.Context, request GetRequest) (response Response, err error)

func (*Observer) GetPages added in v0.89.0

func (o *Observer) GetPages(ctx context.Context, request GetRequest, maxPages int) ([]Response, error)

func (*Observer) Read

func (o *Observer) Read(ctx context.Context, dir string, args ...string) ([]byte, error)

type Reader added in v0.175.0

type Reader struct {
	Get     func(ctx context.Context, request GetRequest) (Response, error)
	Read    func(ctx context.Context, dir string, args ...string) ([]byte, error)
	Execute func(ctx context.Context, dir string, args ...string) CommandResponse
}

Reader replaces the GitHub reads made below one context: Get answers Get and GetPages, Read answers Read, Execute answers Execute; a nil function leaves that call to the real observer. It is the seam a unit test uses to count and answer every read of a caller without a `gh` binary, a process or the network.

type Response

type Response struct {
	Body        []byte
	StatusCode  int
	Headers     map[string]string
	Cached      bool
	ObservedAt  time.Time
	CacheKey    string
	RequestHash string
}

func Get

func Get(ctx context.Context, request GetRequest) (Response, error)

func GetPages added in v0.89.0

func GetPages(ctx context.Context, request GetRequest, maxPages int) ([]Response, error)

GetPages performs a paginated GET and returns one response per page, in order.

It follows GitHub's own `link: <…>; rel="next"` header rather than asking the CLI to paginate. That matters because `gh api --paginate --slurp` — the obvious way to get one JSON document per page — needs a `gh` newer than the 2.45 installed on this fleet, and a land verb that breaks on the installed client sends operators back to raw `gh pr merge`, which is precisely how the cleanup that should have run at landing stopped running.

Every page goes through the ordinary observer, so each is conditionally requested, cached, and throttle-aware exactly like a single-page read.

type RetryTelemetry added in v0.120.0

type RetryTelemetry struct {
	Count      int
	LastReason string
}

RetryTelemetry accumulates the in-process GitHub read retries performed while it is attached to a context via WithRetryTelemetry. Count is the number of retries attempted (not the number of calls), and LastReason records the most recent retry's classified cause.

Jump to

Keyboard shortcuts

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