Help us shape the future of Go! Take the 2026 Go Developer Survey

clients

package
v0.24.3-rc1 Latest Latest
Warning

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

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

Documentation

Index

Constants

View Source
const (
	PickReasonOnlyCandidate    = "only_candidate"
	PickReasonHighestRemaining = "highest_remaining"
	PickReasonRandomTiebreak   = "random_tiebreak"
)

Reason values returned by pick to label picker_picks_total. Stable across releases — operators may build dashboards keyed on them.

Variables

View Source
var ErrAllAppsInCooldown = errors.New("all GitHub apps are in rate-limit cooldown")

ErrAllAppsInCooldown is the sentinel "every credential is in cooldown" error. Callers that only need to detect the condition use errors.Is(err, ErrAllAppsInCooldown). Callers that need the soonest retry hint use errors.As to unwrap a *CooldownError.

Functions

func CleanupExpiredServices

func CleanupExpiredServices()

CleanupExpiredServices removes expired clients from cache (optional background cleanup)

func ExtractAppIDs

func ExtractAppIDs(creds string) (appID, installationID string, err error)

ExtractAppIDs returns the GitHub App ID and Installation ID from a credential string. The credential string format is "appID,installationID,privateKeyPEM"; PEM bodies are base64 plus dashes/newlines and never contain commas, so a 3-way split on the first two commas is sufficient. The returned values are kept as raw strings because they are used as Prometheus label values, not for arithmetic.

func GenerateCacheKey

func GenerateCacheKey(creds string) string

GenerateCacheKey creates a consistent cache key from credentials. The same key is used both for the client cache and for the per-app rate-limit quota pool, so that each unique credential blob has a single shared identity.

func Is403

func Is403(err error) bool

Is403 reports a 403 that carries GitHub's error body. Rate-limit 403s arrive as *github.RateLimitError or *github.AbuseRateLimitError and report false.

func Is404

func Is404(err error) bool

func SortInt64

func SortInt64(s []int64)

SortInt64 sorts s in ascending order, in place.

Types

type ActionsClient

type ActionsClient interface {
	ListEnabledReposInOrg(ctx context.Context, owner string, opts *github.ListOptions) (*github.ActionsEnabledOnOrgRepos, *github.Response, error)
	SetEnabledReposInOrg(ctx context.Context, owner string, repositoryIDs []int64) (*github.Response, error)
	GetOrgSecret(ctx context.Context, org, name string) (*github.Secret, *github.Response, error)
	ListSelectedReposForOrgSecret(ctx context.Context, org, name string, opts *github.ListOptions) (*github.SelectedReposList, *github.Response, error)
	SetSelectedReposForOrgSecret(ctx context.Context, org, name string, ids []int64) (*github.Response, error)
	GetOrgVariable(ctx context.Context, org, name string) (*github.ActionsVariable, *github.Response, error)
	CreateOrgVariable(ctx context.Context, org string, variable github.ActionsCreateOrgVariableRequest) (*github.Response, error)
	UpdateOrgVariable(ctx context.Context, org, name string, variable github.ActionsUpdateOrgVariableRequest) (*github.Response, error)
	DeleteOrgVariable(ctx context.Context, org, name string) (*github.Response, error)
	ListSelectedReposForOrgVariable(ctx context.Context, org, name string, opts *github.ListOptions) (*github.SelectedReposList, *github.Response, error)
	ListOrganizationRunnerGroups(ctx context.Context, org string, opts *github.ListOrgRunnerGroupOptions) (*github.RunnerGroups, *github.Response, error)
	CreateOrganizationRunnerGroup(ctx context.Context, org string, createReq github.CreateRunnerGroupRequest) (*github.RunnerGroup, *github.Response, error)
	UpdateOrganizationRunnerGroup(ctx context.Context, org string, groupID int64, updateReq github.UpdateRunnerGroupRequest) (*github.RunnerGroup, *github.Response, error)
	DeleteOrganizationRunnerGroup(ctx context.Context, org string, groupID int64) (*github.Response, error)
	ListRepositoryAccessRunnerGroup(ctx context.Context, org string, groupID int64, opts *github.ListOptions) (*github.ListRepositories, *github.Response, error)
	SetRepositoryAccessRunnerGroup(ctx context.Context, org string, groupID int64, ids github.SetRepoAccessRunnerGroupRequest) (*github.Response, error)
}

type AppQuota

type AppQuota struct {
	Remaining     int
	CooldownUntil time.Time
	// ConsecutiveFailures counts (nil-response, non-nil-error) outcomes
	// since the last successful HTTP response. Drives the exponential
	// backoff for unhealthyCooldown. Reset to zero on any non-nil resp.
	ConsecutiveFailures int
}

AppQuota is a snapshot of the last-known rate-limit state for one credential.

type Client

type Client struct {
	*Services
	// contains filtered or unexported fields
}

Client is the GitHub client controllers use. It wraps a *Services with per-credential labels so every API call is recorded into Prometheus telemetry and the per-credential cooldown pool.

func NewClient

func NewClient(services *Services, metrics *telemetry.RateLimitMetrics) *Client

NewClient builds a Client around a *Services (typically returned by NewCachedServices) so every wrapped call carries rate-limit telemetry.

func ResolveAndConnect

func ResolveAndConnect(ctx context.Context, kube client.Client, pc *apisv1alpha1.ProviderConfig, metrics *telemetry.RateLimitMetrics, org string) (*Client, error)

ResolveAndConnect resolves every credential entry on pc (Credentials and AdditionalCredentials), picks the one with the most available rate-limit quota, builds a cached GitHub client for it, and returns a wrapped Client ready for use by a controller.

On a fully-exhausted pool the returned error wraps ErrAllAppsInCooldown so callers can decide whether to requeue or surface the error.

func ResolveAndConnectNamespaced

func ResolveAndConnectNamespaced(ctx context.Context, kube client.Client, ref *xpv2.ProviderConfigReference, namespace string, metrics *telemetry.RateLimitMetrics, org string) (*Client, error)

ResolveAndConnectNamespaced is ResolveAndConnect for a namespaced managed resource. ref is the resource's providerConfigRef, which names either a ProviderConfig in namespace or a ClusterProviderConfig.

func (*Client) WithRateLimitTracking

func (c *Client) WithRateLimitTracking(org, appID, installationID, cacheKey string) *Client

WithRateLimitTracking returns a new Client whose service wrappers tag every API response with the given identifiers:

  • org is the GitHub organization for the Prometheus organization label;
  • appID and installationID are the GitHub App ID and Installation ID, used as the app_id and app_installation_id metric labels;
  • cacheKey is the credential cache key, used internally by the per-app quota pool to track 429s and steer future picks.

appID/installationID and cacheKey are separate so that the metric labels stay human-meaningful while the pool keeps its stable internal identity.

type CooldownError

type CooldownError struct {
	RetryAt time.Time
}

CooldownError is returned when every credential in the pool is currently cooling down. RetryAt carries the soonest expiry time so the caller can issue a sensible RequeueAfter or backoff. Unwraps to ErrAllAppsInCooldown so legacy errors.Is checks keep working.

func (*CooldownError) Error

func (e *CooldownError) Error() string

func (*CooldownError) Unwrap

func (e *CooldownError) Unwrap() error

type DependabotClient

type DependabotClient interface {
	GetOrgSecret(ctx context.Context, org, name string) (*github.Secret, *github.Response, error)
	ListSelectedReposForOrgSecret(ctx context.Context, org, name string, opts *github.ListOptions) (*github.SelectedReposList, *github.Response, error)
	SetSelectedReposForOrgSecret(ctx context.Context, org, name string, ids []int64) (*github.Response, error)
}

type OrganizationsClient

type OrganizationsClient interface {
	Get(ctx context.Context, org string) (*github.Organization, *github.Response, error)
	Edit(ctx context.Context, name string, org *github.Organization) (*github.Organization, *github.Response, error)
	GetOrgMembership(ctx context.Context, user, org string) (*github.Membership, *github.Response, error)
	CreateOrgInvitation(ctx context.Context, org string, opts *github.CreateOrgInvitationOptions) (*github.Invitation, *github.Response, error)
	EditOrgMembership(ctx context.Context, user, org string, membership *github.Membership) (*github.Membership, *github.Response, error)
	RemoveOrgMembership(ctx context.Context, user, org string) (*github.Response, error)
	ListHooks(ctx context.Context, org string, opts *github.ListOptions) ([]*github.Hook, *github.Response, error)
	GetHook(ctx context.Context, org string, id int64) (*github.Hook, *github.Response, error)
	CreateHook(ctx context.Context, org string, hook *github.Hook) (*github.Hook, *github.Response, error)
	EditHook(ctx context.Context, org string, id int64, hook *github.Hook) (*github.Hook, *github.Response, error)
	DeleteHook(ctx context.Context, org string, id int64) (*github.Response, error)
}

type RepoIDResolver

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

RepoIDResolver resolves repository names to numeric IDs once per reconcile. Avoids hitting Repositories.Get more than once for the same name when both Observe and Update need IDs for the same SelectedRepositories list.

func NewRepoIDResolver

func NewRepoIDResolver(gh *Client, org string) *RepoIDResolver

NewRepoIDResolver returns a RepoIDResolver for repositories in org.

func (*RepoIDResolver) BatchGetIDs

func (c *RepoIDResolver) BatchGetIDs(ctx context.Context, names []string) ([]int64, error)

BatchGetIDs resolves names to repository IDs, preserving order.

type RepositoriesClient

type RepositoriesClient interface {
	Get(ctx context.Context, owner, repo string) (*github.Repository, *github.Response, error)
	Edit(ctx context.Context, owner, repo string, repository *github.Repository) (*github.Repository, *github.Response, error)
	ListTeams(ctx context.Context, owner string, repo string, opts *github.ListOptions) ([]*github.Team, *github.Response, error)
	ListCollaborators(ctx context.Context, owner, repo string, opts *github.ListCollaboratorsOptions) ([]*github.User, *github.Response, error)
	ListInvitations(ctx context.Context, owner, repo string, opts *github.ListOptions) ([]*github.RepositoryInvitation, *github.Response, error)
	Create(ctx context.Context, org string, repo *github.Repository) (*github.Repository, *github.Response, error)
	CreateFromTemplate(ctx context.Context, templateOwner, templateRepo string, templateRepoReq github.TemplateRepoRequest) (*github.Repository, *github.Response, error)
	CreateFork(ctx context.Context, owner, repo string, opts *github.RepositoryCreateForkOptions) (*github.Repository, *github.Response, error)
	AddCollaborator(ctx context.Context, owner, repo, user string, opts *github.RepositoryAddCollaboratorOptions) (*github.CollaboratorInvitation, *github.Response, error)
	RemoveCollaborator(ctx context.Context, owner, repo, user string) (*github.Response, error)
	GetPermissionLevel(ctx context.Context, owner, repo, user string) (*github.RepositoryPermissionLevel, *github.Response, error)
	Delete(ctx context.Context, owner, repo string) (*github.Response, error)
	CreateHook(ctx context.Context, owner, repo string, hook *github.Hook) (*github.Hook, *github.Response, error)
	EditHook(ctx context.Context, owner, repo string, id int64, hook *github.Hook) (*github.Hook, *github.Response, error)
	DeleteHook(ctx context.Context, owner, repo string, id int64) (*github.Response, error)
	ListHooks(ctx context.Context, owner, repo string, opts *github.ListOptions) ([]*github.Hook, *github.Response, error)
	ListBranches(ctx context.Context, owner, repo string, opts *github.BranchListOptions) ([]*github.Branch, *github.Response, error)
	GetBranch(ctx context.Context, owner, repo, branch string, maxRedirects int) (*github.Branch, *github.Response, error)
	GetBranchProtection(ctx context.Context, owner, repo, branch string) (*github.Protection, *github.Response, error)
	UpdateBranchProtection(ctx context.Context, owner, repo, branch string, preq *github.ProtectionRequest) (*github.Protection, *github.Response, error)
	RemoveBranchProtection(ctx context.Context, owner, repo, branch string) (*github.Response, error)
	RequireSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*github.SignaturesProtectedBranch, *github.Response, error)
	OptionalSignaturesOnProtectedBranch(ctx context.Context, owner, repo, branch string) (*github.Response, error)
	ReplaceAllTopics(ctx context.Context, owner, repo string, topics []string) ([]string, *github.Response, error)
}

type RulesetsClient

type RulesetsClient interface {
	GetAllRulesets(ctx context.Context, owner, repo string, opts *github.RepositoryListRulesetsOptions) ([]*rulesets.Ruleset, *github.Response, error)
	GetRuleset(ctx context.Context, owner, repo string, rulesetID int64, includesParents bool) (*rulesets.Ruleset, *github.Response, error)
	CreateRuleset(ctx context.Context, owner, repo string, ruleset rulesets.Ruleset) (*rulesets.Ruleset, *github.Response, error)
	UpdateRuleset(ctx context.Context, owner, repo string, rulesetID int64, ruleset rulesets.Ruleset) (*rulesets.Ruleset, *github.Response, error)
	DeleteRuleset(ctx context.Context, owner, repo string, rulesetID int64) (*github.Response, error)
}

RulesetsClient reads and writes repository rulesets with the types of package rulesets.

type Services

type Services struct {
	Actions       ActionsClient
	Dependabot    DependabotClient
	Organizations OrganizationsClient
	Users         UsersClient
	Teams         TeamsClient
	Repositories  RepositoriesClient
	Rulesets      RulesetsClient
}

func NewCachedServices

func NewCachedServices(creds string) (*Services, error)

NewCachedServices creates a new cached GitHub client that reuses tokens

type ServicesCache

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

ServicesCache caches *Services keyed by credential hash so that installation tokens are reused across calls within a TTL.

type TeamsClient

type TeamsClient interface {
	GetTeamBySlug(ctx context.Context, org, slug string) (*github.Team, *github.Response, error)
	ListTeamMembersBySlug(ctx context.Context, org, slug string, opts *github.TeamListTeamMembersOptions) ([]*github.User, *github.Response, error)
	CreateTeam(ctx context.Context, org string, team github.NewTeam) (*github.Team, *github.Response, error)
	AddTeamMembershipBySlug(ctx context.Context, org, slug, user string, opts *github.TeamAddTeamMembershipOptions) (*github.Membership, *github.Response, error)
	RemoveTeamMembershipBySlug(ctx context.Context, org, slug, user string) (*github.Response, error)
	ListPendingTeamInvitationsBySlug(ctx context.Context, org, slug string, opts *github.ListOptions) ([]*github.Invitation, *github.Response, error)
	ListChildTeamsByParentSlug(ctx context.Context, org, slug string, opts *github.ListOptions) ([]*github.Team, *github.Response, error)
	EditTeamBySlug(ctx context.Context, org, slug string, team github.NewTeam, removeParent bool) (*github.Team, *github.Response, error)
	DeleteTeamBySlug(ctx context.Context, org, slug string) (*github.Response, error)
	AddTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string, opts *github.TeamAddTeamRepoOptions) (*github.Response, error)
	RemoveTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string) (*github.Response, error)
	IsTeamRepoBySlug(ctx context.Context, org, slug, owner, repo string) (*github.Repository, *github.Response, error)
}

type UsersClient

type UsersClient interface {
	Get(ctx context.Context, user string) (*github.User, *github.Response, error)
}

Directories

Path Synopsis
Package rulesets reads and writes repository rulesets with the provider's own types over go-github's transport.
Package rulesets reads and writes repository rulesets with the provider's own types over go-github's transport.

Jump to

Keyboard shortcuts

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