Documentation
¶
Overview ¶
Package githubauth provides GitHub authentication as standard golang.org/x/oauth2.TokenSource implementations: GitHub App JWTs, GitHub App installation tokens, and personal access tokens.
Because every credential is exposed through the oauth2.TokenSource interface, the package composes with anything that accepts one — golang.org/x/oauth2.NewClient, the google/go-github SDK, gRPC per-RPC credentials, or code that simply needs the token string. The module depends only on github.com/golang-jwt/jwt and golang.org/x/oauth2; no GitHub SDK is required.
GitHub App authentication ¶
Authenticating as a GitHub App is a two-step chain: a short-lived RS256-signed JWT identifies the App itself, and that JWT is exchanged for an installation access token scoped to one installation of the App.
privateKey := []byte(os.Getenv("GITHUB_APP_PRIVATE_KEY"))
clientID := os.Getenv("GITHUB_APP_CLIENT_ID")
installationID, _ := strconv.ParseInt(os.Getenv("GITHUB_INSTALLATION_ID"), 10, 64)
appSource, err := githubauth.NewApplicationTokenSource(clientID, privateKey)
if err != nil {
// handle error
}
installationSource := githubauth.NewInstallationTokenSource(installationID, appSource)
// httpClient authenticates every request with a fresh installation token.
httpClient := oauth2.NewClient(context.Background(), installationSource)
NewApplicationTokenSource accepts either a string Client ID (recommended by GitHub for new Apps) or an int64 App ID (legacy); the type parameter is inferred from the argument.
Token caching and proactive refresh ¶
Both NewApplicationTokenSource and NewInstallationTokenSource wrap their sources in ReuseTokenSourceWithSkew: tokens are cached and refreshed DefaultExpirySkew (30 seconds) before expiry rather than after it, so a request that starts near the expiry instant never reaches GitHub with an already-expired credential. The window is tunable with WithExpirySkew (application JWTs) and WithInstallationExpirySkew (installation tokens).
Handling rate limits ¶
A throttled request returns a RateLimitError carrying the wait the client computed from GitHub's own headers, so a caller running its own backoff does not have to re-parse a response it never sees:
var rle *githubauth.RateLimitError
if errors.As(err, &rle) {
time.Sleep(rle.RetryAfter)
}
It unwraps to ErrRateLimited, so errors.Is(err, ErrRateLimited) keeps working. A 403 permission failure is not a rate limit and matches neither, even though GitHub attaches rate-limit headers to it.
Signing with external key stores ¶
NewApplicationTokenSourceFromSigner accepts any RSA-backed crypto.Signer — AWS KMS, Google Cloud KMS, Azure Key Vault, HashiCorp Vault Transit, PKCS#11 HSMs, or ssh-agent — so the App private key never enters process memory. GitHub requires RS256; non-RSA signers are rejected at construction time.
GitHub Enterprise ¶
WithEnterpriseURL targets GitHub Enterprise Server, normalizing the URL the way GHES expects (appending /api/v3/ when needed). WithBaseURL uses the supplied URL verbatim, which fits GitHub Enterprise Cloud with data residency (https://api.SUBDOMAIN.ghe.com/) and httptest servers.
Webhook verification ¶
The webhook subpackage verifies GitHub webhook deliveries (X-Hub-Signature-256, HMAC-SHA256 in constant time) and ships an http.Handler middleware that restores the request body for downstream handlers. See github.com/jferrl/go-githubauth/webhook.
Index ¶
- Constants
- Variables
- func NewApplicationTokenSource[T Identifier](id T, privateKey []byte, opts ...ApplicationTokenOpt) (oauth2.TokenSource, error)
- func NewApplicationTokenSourceFromSigner[T Identifier](id T, signer crypto.Signer, opts ...ApplicationTokenOpt) (oauth2.TokenSource, error)
- func NewInstallationTokenSource(id int64, src oauth2.TokenSource, opts ...InstallationTokenSourceOpt) oauth2.TokenSource
- func NewPersonalAccessTokenSource(token string) oauth2.TokenSource
- func Ptr[T any](v T) *T
- func ReuseTokenSourceWithSkew(t *oauth2.Token, src oauth2.TokenSource, skew time.Duration) oauth2.TokenSource
- type ApplicationTokenOpt
- type Identifier
- type InstallationPermissions
- type InstallationToken
- type InstallationTokenOptions
- type InstallationTokenSourceOpt
- func WithBaseURL(baseURL string) InstallationTokenSourceOpt
- func WithContext(ctx context.Context) InstallationTokenSourceOpt
- func WithEnterpriseURL(baseURL string) InstallationTokenSourceOpt
- func WithHTTPClient(client *http.Client) InstallationTokenSourceOpt
- func WithInstallationExpirySkew(d time.Duration) InstallationTokenSourceOpt
- func WithInstallationTokenOptions(opts *InstallationTokenOptions) InstallationTokenSourceOpt
- func WithRetryOnThrottle(enabled bool) InstallationTokenSourceOpt
- type RateLimitError
- type Repository
Examples ¶
Constants ¶
const ( // DefaultApplicationTokenExpiration is the default expiration time for GitHub App tokens. // The maximum allowed expiration is 10 minutes. DefaultApplicationTokenExpiration = 10 * time.Minute // DefaultExpirySkew is the default early-refresh window applied to cached // tokens returned by NewApplicationTokenSource and NewInstallationTokenSource. // At 30s the effective validity of a default 10-minute application JWT becomes // 8m30s, which is acceptable and eliminates the common in-flight 401 caused // by a request starting near exp and arriving at GitHub after exp. DefaultExpirySkew = 30 * time.Second )
Variables ¶
var ErrRateLimited = errors.New("github API rate limited")
ErrRateLimited wraps errors returned when GitHub has throttled a request: any HTTP 429, or a 403 that GitHub identifies as a rate limit rather than a permission failure. A 403 counts when it carries Retry-After, reports an exhausted budget via X-RateLimit-Remaining: 0, or says so in its message.
A 403 such as "Resource not accessible by integration" is a permission failure and is NOT wrapped, even though GitHub attaches rate-limit headers to it. Callers can branch with errors.Is.
Functions ¶
func NewApplicationTokenSource ¶
func NewApplicationTokenSource[T Identifier](id T, privateKey []byte, opts ...ApplicationTokenOpt) (oauth2.TokenSource, error)
NewApplicationTokenSource creates a GitHub App JWT token source from a PEM-encoded RSA private key. Accepts either int64 App ID or string Client ID. GitHub recommends Client IDs for new apps. Generated JWTs are RS256-signed with iat, exp, and iss claims. JWTs expire in max 10 minutes and include clock drift protection (iat set 60s in past).
The returned token source is wrapped in ReuseTokenSourceWithSkew with DefaultExpirySkew (30s), so cached tokens are refreshed before exp rather than after. With the default 10-minute expiration, which is backdated 60s for clock drift, the effective validity is 8m30s. Override with WithExpirySkew.
For KMS, HSM, Vault, or ssh-agent backed signing, use NewApplicationTokenSourceFromSigner instead — the private key never leaves its secure boundary.
Example ¶
Authenticate as a GitHub App with a Client ID (recommended by GitHub for new Apps). The returned source caches the JWT and refreshes it 30s before expiry.
package main
import (
"fmt"
"os"
"github.com/jferrl/go-githubauth"
)
func main() {
privateKey := []byte(os.Getenv("GITHUB_APP_PRIVATE_KEY"))
clientID := os.Getenv("GITHUB_APP_CLIENT_ID") // e.g. "Iv1.1234567890abcdef"
appSource, err := githubauth.NewApplicationTokenSource(clientID, privateKey)
if err != nil {
fmt.Println("creating application token source:", err)
return
}
token, err := appSource.Token()
if err != nil {
fmt.Println("generating JWT:", err)
return
}
fmt.Println("app JWT:", token.AccessToken)
}
Output:
Example (AppID) ¶
Authenticate with a legacy numeric App ID and a custom JWT expiration.
package main
import (
"fmt"
"os"
"strconv"
"time"
"github.com/jferrl/go-githubauth"
)
func main() {
privateKey := []byte(os.Getenv("GITHUB_APP_PRIVATE_KEY"))
appID, _ := strconv.ParseInt(os.Getenv("GITHUB_APP_ID"), 10, 64)
appSource, err := githubauth.NewApplicationTokenSource(
appID,
privateKey,
githubauth.WithApplicationTokenExpiration(5*time.Minute),
)
if err != nil {
fmt.Println("creating application token source:", err)
return
}
token, err := appSource.Token()
if err != nil {
fmt.Println("generating JWT:", err)
return
}
fmt.Println("app JWT:", token.AccessToken)
}
Output:
func NewApplicationTokenSourceFromSigner ¶ added in v1.6.0
func NewApplicationTokenSourceFromSigner[T Identifier](id T, signer crypto.Signer, opts ...ApplicationTokenOpt) (oauth2.TokenSource, error)
NewApplicationTokenSourceFromSigner creates a GitHub App JWT token source backed by an external crypto.Signer. Any RSA-backed signer works: AWS KMS, GCP KMS, Azure Key Vault, HashiCorp Vault Transit, PKCS#11 HSMs, or ssh-agent. The private key never touches process memory.
The signer's public key must be RSA — GitHub requires RS256 (RSASSA-PKCS1-v1_5 with SHA-256, per RFC 7518 §3.3). The signer must return signatures in that form when called with crypto.SHA256; every stdlib-compatible RSA signer does.
Example ¶
Sign App JWTs with an external key store. Any RSA-backed crypto.Signer works: AWS KMS, Google Cloud KMS, Azure Key Vault, HashiCorp Vault Transit, PKCS#11 HSMs, or ssh-agent. A local *rsa.PrivateKey stands in for a KMS-backed signer here; in production the private key never touches process memory.
package main
import (
"crypto"
"crypto/x509"
"encoding/pem"
"fmt"
"os"
"github.com/jferrl/go-githubauth"
)
func main() {
clientID := os.Getenv("GITHUB_APP_CLIENT_ID")
block, _ := pem.Decode([]byte(os.Getenv("GITHUB_APP_PRIVATE_KEY")))
if block == nil {
fmt.Println("no PEM block found")
return
}
key, err := x509.ParsePKCS1PrivateKey(block.Bytes)
if err != nil {
fmt.Println("parsing private key:", err)
return
}
var signer crypto.Signer = key // swap for a KMS/HSM/Vault-backed signer
appSource, err := githubauth.NewApplicationTokenSourceFromSigner(clientID, signer)
if err != nil {
fmt.Println("creating application token source:", err)
return
}
token, err := appSource.Token()
if err != nil {
fmt.Println("generating JWT:", err)
return
}
fmt.Println("app JWT:", token.AccessToken)
}
Output:
func NewInstallationTokenSource ¶
func NewInstallationTokenSource(id int64, src oauth2.TokenSource, opts ...InstallationTokenSourceOpt) oauth2.TokenSource
NewInstallationTokenSource creates a GitHub App installation token source. Requires installation ID and a GitHub App JWT token source for authentication.
A non-positive installation ID is a configuration error, reported by the first call to Token() rather than sent to GitHub as a request that can only 404.
The returned token source is wrapped in ReuseTokenSourceWithSkew so cached tokens are refreshed DefaultExpirySkew before their expiry, eliminating in-flight 401s when a request starts close to exp and reaches GitHub after. Override the window with WithInstallationExpirySkew.
Example ¶
The full GitHub App chain: App JWT -> installation token -> authenticated HTTP client. The client works standalone or can be passed to github.NewClient from google/go-github.
package main
import (
"context"
"fmt"
"os"
"strconv"
"github.com/jferrl/go-githubauth"
"golang.org/x/oauth2"
)
func main() {
privateKey := []byte(os.Getenv("GITHUB_APP_PRIVATE_KEY"))
clientID := os.Getenv("GITHUB_APP_CLIENT_ID")
installationID, _ := strconv.ParseInt(os.Getenv("GITHUB_INSTALLATION_ID"), 10, 64)
appSource, err := githubauth.NewApplicationTokenSource(clientID, privateKey)
if err != nil {
fmt.Println("creating application token source:", err)
return
}
installationSource := githubauth.NewInstallationTokenSource(installationID, appSource)
// Every request carries a valid installation token; refresh is automatic.
httpClient := oauth2.NewClient(context.Background(), installationSource)
resp, err := httpClient.Get("https://api.github.com/installation/repositories")
if err != nil {
fmt.Println("listing installation repositories:", err)
return
}
defer func() { _ = resp.Body.Close() }()
fmt.Println("status:", resp.Status)
}
Output:
Example (Enterprise) ¶
Point the installation token source at GitHub Enterprise Server (GHES) or GitHub Enterprise Cloud (GHEC) with data residency.
package main
import (
"fmt"
"os"
"strconv"
"github.com/jferrl/go-githubauth"
)
func main() {
privateKey := []byte(os.Getenv("GITHUB_APP_PRIVATE_KEY"))
clientID := os.Getenv("GITHUB_APP_CLIENT_ID")
installationID, _ := strconv.ParseInt(os.Getenv("GITHUB_INSTALLATION_ID"), 10, 64)
appSource, err := githubauth.NewApplicationTokenSource(clientID, privateKey)
if err != nil {
fmt.Println("creating application token source:", err)
return
}
// GHES: the URL is normalized the way GHES expects (/api/v3/ appended).
ghes := githubauth.NewInstallationTokenSource(
installationID,
appSource,
githubauth.WithEnterpriseURL("https://github.example.com"),
)
// GHEC with data residency: the URL is used verbatim.
ghec := githubauth.NewInstallationTokenSource(
installationID,
appSource,
githubauth.WithBaseURL("https://api.octocorp.ghe.com"),
)
_, _ = ghes, ghec
}
Output:
func NewPersonalAccessTokenSource ¶ added in v1.4.0
func NewPersonalAccessTokenSource(token string) oauth2.TokenSource
NewPersonalAccessTokenSource creates a token source for GitHub personal access tokens. The provided token should be a valid GitHub personal access token (classic or fine-grained). This token source returns the same token value for all Token() calls without expiration, making it suitable for long-lived authentication scenarios.
Example ¶
Authenticate with a classic or fine-grained personal access token.
package main
import (
"context"
"fmt"
"os"
"github.com/jferrl/go-githubauth"
"golang.org/x/oauth2"
)
func main() {
token := os.Getenv("GITHUB_TOKEN") // "ghp_..." or "github_pat_..."
tokenSource := githubauth.NewPersonalAccessTokenSource(token)
httpClient := oauth2.NewClient(context.Background(), tokenSource)
resp, err := httpClient.Get("https://api.github.com/user")
if err != nil {
fmt.Println("getting user:", err)
return
}
defer func() { _ = resp.Body.Close() }()
fmt.Println("status:", resp.Status)
}
Output:
func Ptr ¶ added in v1.5.0
func Ptr[T any](v T) *T
Ptr is a helper function to create a pointer to a value. This is useful when constructing InstallationTokenOptions with permissions.
func ReuseTokenSourceWithSkew ¶ added in v1.6.0
func ReuseTokenSourceWithSkew(t *oauth2.Token, src oauth2.TokenSource, skew time.Duration) oauth2.TokenSource
ReuseTokenSourceWithSkew wraps src so cached tokens are refreshed proactively, skew before their expiry. oauth2.ReuseTokenSource refreshes only once exp has passed (via oauth2.Token.Valid), so a request that starts at T-100ms with a token expiring at T can arrive at GitHub already expired and yield a 401 the caller must manually retry. This wrapper refreshes when time.Until(t.Expiry) <= skew, cutting out that race.
If skew is zero or negative the wrapper delegates to oauth2.ReuseTokenSource, preserving its exact behavior. An initial non-nil t is used until it needs refresh under the same rule. The returned source is safe for concurrent use; concurrent Token calls that find the cache stale collapse into a single upstream fetch.
Example ¶
Wrap any third-party oauth2.TokenSource so cached tokens refresh before expiry instead of after it.
package main
import (
"time"
"github.com/jferrl/go-githubauth"
"golang.org/x/oauth2"
)
func main() {
var upstream oauth2.TokenSource // any token source, e.g. from another provider
src := githubauth.ReuseTokenSourceWithSkew(nil, upstream, 30*time.Second)
_ = src
}
Output:
Types ¶
type ApplicationTokenOpt ¶
type ApplicationTokenOpt func(*applicationTokenSource)
ApplicationTokenOpt is a functional option for configuring an applicationTokenSource.
func WithApplicationTokenExpiration ¶
func WithApplicationTokenExpiration(exp time.Duration) ApplicationTokenOpt
WithApplicationTokenExpiration sets the JWT expiration duration. Must be greater than 90 seconds and at most 10 minutes. Ten minutes is GitHub's ceiling. The lower bound is the 60 second clock-drift backdate plus DefaultExpirySkew: at or below the backdate the JWT is already expired when minted, and within the skew above it the cache never holds the token, so every call re-signs — a remote round trip for a KMS, HSM or Vault signer. Invalid values default to 10 minutes. See https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-json-web-token-jwt-for-a-github-app#about-json-web-tokens-jwts
func WithExpirySkew ¶ added in v1.6.0
func WithExpirySkew(d time.Duration) ApplicationTokenOpt
WithExpirySkew overrides the default early-refresh window (DefaultExpirySkew, 30s) applied to the token cache returned by NewApplicationTokenSource. The cached token is refreshed when time.Until(exp) <= d. A zero or negative value disables the skew and falls back to oauth2.ReuseTokenSource behavior (refresh only after exp has passed).
Tune this when your application token expiration (see WithApplicationTokenExpiration) is short: the effective validity is expiration - 60s of clock-drift backdating - skew, so with the default 10-minute expiration and 30s skew tokens are refreshed at 8m30s.
type Identifier ¶ added in v1.3.0
Identifier constrains GitHub App identifiers to int64 (App ID) or string (Client ID).
type InstallationPermissions ¶ added in v1.5.0
type InstallationPermissions struct {
Actions *string `json:"actions,omitempty"`
Administration *string `json:"administration,omitempty"`
Checks *string `json:"checks,omitempty"`
Contents *string `json:"contents,omitempty"`
ContentReferences *string `json:"content_references,omitempty"`
Deployments *string `json:"deployments,omitempty"`
Environments *string `json:"environments,omitempty"`
Issues *string `json:"issues,omitempty"`
Metadata *string `json:"metadata,omitempty"`
Packages *string `json:"packages,omitempty"`
Pages *string `json:"pages,omitempty"`
PullRequests *string `json:"pull_requests,omitempty"`
RepositoryAnnouncementBanners *string `json:"repository_announcement_banners,omitempty"`
RepositoryHooks *string `json:"repository_hooks,omitempty"`
RepositoryProjects *string `json:"repository_projects,omitempty"`
SecretScanningAlerts *string `json:"secret_scanning_alerts,omitempty"`
Secrets *string `json:"secrets,omitempty"`
SecurityEvents *string `json:"security_events,omitempty"`
SingleFile *string `json:"single_file,omitempty"`
Statuses *string `json:"statuses,omitempty"`
VulnerabilityAlerts *string `json:"vulnerability_alerts,omitempty"`
Workflows *string `json:"workflows,omitempty"`
Members *string `json:"members,omitempty"`
OrganizationAdministration *string `json:"organization_administration,omitempty"`
OrganizationCustomRoles *string `json:"organization_custom_roles,omitempty"`
OrganizationAnnouncementBanners *string `json:"organization_announcement_banners,omitempty"`
OrganizationHooks *string `json:"organization_hooks,omitempty"`
OrganizationPlan *string `json:"organization_plan,omitempty"`
OrganizationProjects *string `json:"organization_projects,omitempty"`
OrganizationPackages *string `json:"organization_packages,omitempty"`
OrganizationSecrets *string `json:"organization_secrets,omitempty"`
OrganizationSelfHostedRunners *string `json:"organization_self_hosted_runners,omitempty"`
OrganizationUserBlocking *string `json:"organization_user_blocking,omitempty"`
TeamDiscussions *string `json:"team_discussions,omitempty"`
}
InstallationPermissions represents the permissions granted to an installation token.
type InstallationToken ¶ added in v1.5.0
type InstallationToken struct {
Token string `json:"token"`
ExpiresAt time.Time `json:"expires_at"`
Permissions *InstallationPermissions `json:"permissions,omitempty"`
Repositories []Repository `json:"repositories,omitempty"`
}
InstallationToken represents a GitHub App installation token.
type InstallationTokenOptions ¶ added in v1.5.0
type InstallationTokenOptions struct {
// Repositories is a list of repository names that the token should have access to.
Repositories []string `json:"repositories,omitempty"`
// RepositoryIDs is a list of repository IDs that the token should have access to.
RepositoryIDs []int64 `json:"repository_ids,omitempty"`
// Permissions are the permissions granted to the access token.
Permissions *InstallationPermissions `json:"permissions,omitempty"`
}
InstallationTokenOptions specifies options for creating an installation token.
type InstallationTokenSourceOpt ¶
type InstallationTokenSourceOpt func(*installationTokenSource)
InstallationTokenSourceOpt is a functional option for InstallationTokenSource.
func WithBaseURL ¶ added in v1.7.0
func WithBaseURL(baseURL string) InstallationTokenSourceOpt
WithBaseURL sets the API base URL used to create installation tokens, closely mirroring how go-github lets callers point the client at a custom endpoint. Unlike WithEnterpriseURL, the URL is used verbatim — only a trailing slash is appended when missing, and no "/api/v3/" suffix is added.
Use this for:
- GitHub Enterprise Cloud with data residency (https://api.SUBDOMAIN.ghe.com/)
- pointing the client at an httptest server in tests
Option order does not matter; it may be combined with WithHTTPClient, WithEnterpriseURL, and WithRetryOnThrottle in any order. If the URL cannot be parsed, the error is reported by the first call to Token() rather than silently falling back to the public GitHub API.
func WithContext ¶ added in v1.1.0
func WithContext(ctx context.Context) InstallationTokenSourceOpt
WithContext sets the context for the GitHub App installation token source.
func WithEnterpriseURL ¶ added in v1.5.0
func WithEnterpriseURL(baseURL string) InstallationTokenSourceOpt
WithEnterpriseURL sets the base URL for GitHub Enterprise Server (GHES). The URL is normalized the way GHES expects, appending the "/api/v3/" path when the host is not already an "api." subdomain. For GitHub Enterprise Cloud or a verbatim URL (such as an httptest server), use WithBaseURL instead.
Option order does not matter; it may be combined with WithHTTPClient, WithBaseURL, and WithRetryOnThrottle in any order. If the URL cannot be parsed, the error is reported by the first call to Token() rather than silently falling back to the public GitHub API.
func WithHTTPClient ¶
func WithHTTPClient(client *http.Client) InstallationTokenSourceOpt
WithHTTPClient sets the HTTP client used to call the GitHub API. Its transport is wrapped so installation-token requests are authenticated with the GitHub App JWT; any base URL configured via WithBaseURL or WithEnterpriseURL is preserved, so these options may be combined in any order.
A nil client is a configuration error reported by the first call to Token().
func WithInstallationExpirySkew ¶ added in v1.6.0
func WithInstallationExpirySkew(d time.Duration) InstallationTokenSourceOpt
WithInstallationExpirySkew overrides the default early-refresh window (DefaultExpirySkew, 30s) applied to the installation token cache returned by NewInstallationTokenSource. Installation tokens live 1 hour, so the 30s default leaves ~59m30s effective validity — this option exists mostly for parity with WithExpirySkew. A zero or negative value falls back to oauth2.ReuseTokenSource behavior.
func WithInstallationTokenOptions ¶
func WithInstallationTokenOptions(opts *InstallationTokenOptions) InstallationTokenSourceOpt
WithInstallationTokenOptions sets the options for the GitHub App installation token.
func WithRetryOnThrottle ¶ added in v1.6.0
func WithRetryOnThrottle(enabled bool) InstallationTokenSourceOpt
WithRetryOnThrottle enables or disables a single automatic retry when GitHub throttles the installation token POST. Enabled by default.
Any 429 counts as throttled. A 403 counts only when GitHub identifies it as a rate limit — it carries Retry-After, reports an exhausted budget via X-RateLimit-Remaining: 0, or says so in its message. A permission failure such as "Resource not accessible by integration" is terminal and is retried by neither setting, despite carrying rate-limit headers.
On a throttled response the client sleeps the duration hinted by Retry-After or x-ratelimit-reset, falling back to one minute for a hintless rate-limit 403 (capped at 60s, honoring ctx cancellation), and retries once. Subsequent failures bubble up unchanged. On a terminal throttle the returned error wraps ErrRateLimited so callers can branch with errors.Is.
Disable this when the caller implements its own backoff or when deterministic latency matters more than transient rate-limit resilience.
type RateLimitError ¶ added in v1.8.0
type RateLimitError struct {
// StatusCode is the HTTP status GitHub returned, 429 or 403.
StatusCode int
// RetryAfter is how long to wait before retrying, taken from Retry-After or
// X-RateLimit-Reset and capped at maxRetrySleep. It falls back to a
// documented default when GitHub sends no usable hint. It is zero when
// GitHub says to retry immediately, or when the reset instant has already
// passed, so callers must treat zero as "retry now" rather than "no hint".
RetryAfter time.Duration
// Message is the response body, truncated to maxErrorBodyBytes.
Message string
}
RateLimitError is the concrete error returned when GitHub throttles a request. It carries the wait the client computed from GitHub's own hints, so a caller running its own backoff does not have to re-parse the headers the client already read:
var rle *githubauth.RateLimitError
if errors.As(err, &rle) {
time.Sleep(rle.RetryAfter)
}
It unwraps to ErrRateLimited, so errors.Is(err, ErrRateLimited) keeps working.
func (*RateLimitError) Error ¶ added in v1.8.0
func (e *RateLimitError) Error() string
func (*RateLimitError) Unwrap ¶ added in v1.8.0
func (e *RateLimitError) Unwrap() error
Unwrap reports ErrRateLimited so callers can branch with errors.Is without knowing about this type.
type Repository ¶ added in v1.5.0
Repository represents a GitHub repository.
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
githubauth
command
Command githubauth mints GitHub App credentials from the command line.
|
Command githubauth mints GitHub App credentials from the command line. |
|
Package webhook verifies GitHub webhook deliveries.
|
Package webhook verifies GitHub webhook deliveries. |