or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

actions.mdadditional-services.mdapps.mdchecks.mdclient.mdenterprise.mdgit.mdindex.mdissues.mdorganizations.mdrepositories.mdteams.mdusers.md
tile.json

client.mddocs/

Client and Core Functionality

Comprehensive documentation for the GitHub API client including creation, configuration, authentication, rate limiting, pagination, and core operations.

Client Creation

NewClient

Creates a new GitHub API client.

func NewClient(httpClient *http.Client) *Client

The httpClient parameter can be nil for unauthenticated requests, or an *http.Client configured with authentication transport.

Usage examples:

// Unauthenticated client (limited to 60 requests/hour)
client := github.NewClient(nil)

// Authenticated client using OAuth2
import "golang.org/x/oauth2"

ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: "your-token"})
tc := oauth2.NewClient(context.Background(), ts)
client := github.NewClient(tc)

Client Type

The Client type provides access to all GitHub API services and core operations.

type Client struct {
    // Service fields for accessing specific API areas
    Actions                *ActionsService
    Activity               *ActivityService
    Admin                  *AdminService
    Apps                   *AppsService
    Authorizations         *AuthorizationsService
    Billing                *BillingService
    Checks                 *ChecksService
    Classroom              *ClassroomService
    CodeScanning           *CodeScanningService
    CodesOfConduct         *CodesOfConductService
    Codespaces             *CodespacesService
    Compute                *ComputeService
    Copilot                *CopilotService
    Dependabot             *DependabotService
    DependencyGraph        *DependencyGraphService
    Emojis                 *EmojisService
    Enterprise             *EnterpriseService
    Gists                  *GistsService
    Git                    *GitService
    Gitignores             *GitignoresService
    Interactions           *InteractionsService
    IssueImport            *IssueImportService
    Issues                 *IssuesService
    Licenses               *LicensesService
    Marketplace            *MarketplaceService
    Meta                   *MetaService
    Migrations             *MigrationService
    Organizations          *OrganizationsService
    Packages               *PackagesService
    Projects               *ProjectsService
    PullRequests           *PullRequestsService
    RateLimit              *RateLimitService
    Reactions              *ReactionsService
    Repositories           *RepositoriesService
    SCIM                   *SCIMService
    Search                 *SearchService
    SecretScanning         *SecretScanningService
    SecurityAdvisories     *SecurityAdvisoriesService
    Teams                  *TeamsService
    Users                  *UsersService
}

Authentication

WithAuthToken

Configure client with a personal access token.

func (c *Client) WithAuthToken(token string) *Client

Returns a copy of the client configured to use the provided authentication token.

client := github.NewClient(nil).WithAuthToken("ghp_your_token_here")

// Now all requests will be authenticated
user, _, err := client.Users.Get(context.Background(), "")

OAuth2 Authentication

For OAuth2 flows, use the golang.org/x/oauth2 package:

import (
    "context"
    "github.com/google/go-github/v79/github"
    "golang.org/x/oauth2"
)

func authenticateWithOAuth2(accessToken string) *github.Client {
    ctx := context.Background()
    ts := oauth2.StaticTokenSource(
        &oauth2.Token{AccessToken: accessToken},
    )
    tc := oauth2.NewClient(ctx, ts)
    return github.NewClient(tc)
}

GitHub App Authentication

For GitHub App installations, use a JWT-based authentication transport:

import (
    "github.com/bradleyfalzon/ghinstallation/v2"
    "github.com/google/go-github/v79/github"
)

func authenticateAsGitHubApp(appID, installationID int64, privateKeyPath string) (*github.Client, error) {
    itr, err := ghinstallation.NewKeyFromFile(
        http.DefaultTransport,
        appID,
        installationID,
        privateKeyPath,
    )
    if err != nil {
        return nil, err
    }

    return github.NewClient(&http.Client{Transport: itr}), nil
}

Basic Authentication

Basic authentication with username and password (deprecated by GitHub, use tokens instead):

import "net/http"

func basicAuth(username, password string) *github.Client {
    tp := &BasicAuthTransport{
        Username: username,
        Password: password,
    }
    return github.NewClient(tp.Client())
}

type BasicAuthTransport struct {
    Username string
    Password string
    Transport http.RoundTripper
}

func (t *BasicAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) {
    req2 := cloneRequest(req)
    req2.SetBasicAuth(t.Username, t.Password)
    return t.transport().RoundTrip(req2)
}

func (t *BasicAuthTransport) Client() *http.Client {
    return &http.Client{Transport: t}
}

func (t *BasicAuthTransport) transport() http.RoundTripper {
    if t.Transport != nil {
        return t.Transport
    }
    return http.DefaultTransport
}

Enterprise Configuration

WithEnterpriseURLs

Configure client for GitHub Enterprise Server.

func (c *Client) WithEnterpriseURLs(baseURL, uploadURL string) (*Client, error)
client := github.NewClient(nil)
client, err := client.WithEnterpriseURLs(
    "https://github.company.com/api/v3/",
    "https://github.company.com/api/uploads/",
)
if err != nil {
    // Handle error
}

Rate Limiting

RateLimits

Get current rate limit status for all API categories.

func (c *Client) RateLimits(ctx context.Context) (*RateLimits, *Response, error)
ctx := context.Background()
rateLimits, _, err := client.RateLimits(ctx)
if err != nil {
    // Handle error
}

fmt.Printf("Core API: %d/%d (resets at %v)\n",
    rateLimits.Core.Remaining,
    rateLimits.Core.Limit,
    rateLimits.Core.Reset.Time)

fmt.Printf("Search API: %d/%d\n",
    rateLimits.Search.Remaining,
    rateLimits.Search.Limit)

Rate Limit Types

type Rate struct {
    Limit     int       // Maximum number of requests per hour
    Remaining int       // Remaining requests in current period
    Reset     Timestamp // Time when rate limit resets
}

type RateLimits struct {
    Core                      *Rate // Core API endpoints
    Search                    *Rate // Search API
    GraphQL                   *Rate // GraphQL API
    IntegrationManifest       *Rate // Integration manifest
    SourceImport              *Rate // Source import
    CodeScanningUpload        *Rate // Code scanning upload
    ActionsRunnerRegistration *Rate // Actions runner registration
    SCIM                      *Rate // SCIM API
    DependencySnapshots       *Rate // Dependency snapshots
    CodeSearch                *Rate // Code search
    AuditLog                  *Rate // Audit log
}

Rate Limit in Responses

Every API response includes rate limit information:

repos, resp, err := client.Repositories.List(ctx, "octocat", nil)
if err != nil {
    // Handle error
}

// Check rate limit from response
fmt.Printf("Rate: %d/%d, resets at %v\n",
    resp.Rate.Remaining,
    resp.Rate.Limit,
    resp.Rate.Reset.Time)

// Check for token expiration
if !resp.TokenExpiration.IsZero() {
    fmt.Printf("Token expires: %v\n", resp.TokenExpiration)
}

Rate Limit Error Handling

user, _, err := client.Users.Get(ctx, "octocat")
if err != nil {
    // Check for rate limit errors
    if rateLimitErr, ok := err.(*github.RateLimitError); ok {
        fmt.Printf("Rate limited! Resets at: %v\n", rateLimitErr.Rate.Reset.Time)

        // Wait until reset
        sleepDuration := time.Until(rateLimitErr.Rate.Reset.Time)
        time.Sleep(sleepDuration)

        // Retry request
        user, _, err = client.Users.Get(ctx, "octocat")
    }

    // Check for abuse/secondary rate limit
    if abuseErr, ok := err.(*github.AbuseRateLimitError); ok {
        if abuseErr.RetryAfter != nil {
            fmt.Printf("Secondary rate limit! Retry after: %v\n", *abuseErr.RetryAfter)
            time.Sleep(*abuseErr.RetryAfter)
        }
    }
}

Rate Limit Context Options

Control rate limit behavior with context values:

import "context"

// Bypass rate limit check (use with caution)
ctx := context.WithValue(context.Background(),
    github.BypassRateLimitCheck, true)

// Auto-sleep until rate limit reset when rate limited
ctx = context.WithValue(context.Background(),
    github.SleepUntilPrimaryRateLimitResetWhenRateLimited, true)

repos, _, err := client.Repositories.List(ctx, "user", nil)

Response Type

Response

Every API call returns a Response containing HTTP response details and metadata.

type Response struct {
    *http.Response

    // Rate limit information for this request
    Rate Rate

    // Token expiration time (if applicable)
    TokenExpiration time.Time

    // Pagination links
    NextPage  int
    PrevPage  int
    FirstPage int
    LastPage  int
}

Pagination

ListOptions

Embedded in most list operation option types for pagination control.

type ListOptions struct {
    Page    int // Page number (starting at 1)
    PerPage int // Results per page (max 100)
}

Pagination Pattern

import "context"

func listAllRepositories(client *github.Client, username string) ([]*github.Repository, error) {
    ctx := context.Background()
    var allRepos []*github.Repository

    opts := &github.RepositoryListOptions{
        ListOptions: github.ListOptions{
            Page:    1,
            PerPage: 100, // Maximum
        },
    }

    for {
        repos, resp, err := client.Repositories.List(ctx, username, opts)
        if err != nil {
            return nil, err
        }

        allRepos = append(allRepos, repos...)

        // Check if there are more pages
        if resp.NextPage == 0 {
            break
        }

        opts.Page = resp.NextPage
    }

    return allRepos, nil
}

Core Client Methods

Do

Send an API request and return the parsed response.

func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*Response, error)
req, err := client.NewRequest("GET", "users/octocat", nil)
if err != nil {
    // Handle error
}

var user github.User
resp, err := client.Do(context.Background(), req, &user)
if err != nil {
    // Handle error
}

BareDo

Send an API request without automatic response parsing.

func (c *Client) BareDo(ctx context.Context, req *http.Request) (*Response, error)
req, _ := client.NewRequest("GET", "zen", nil)
resp, err := client.BareDo(context.Background(), req)
if err != nil {
    // Handle error
}
defer resp.Body.Close()

body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))

NewRequest

Create a new API request.

func (c *Client) NewRequest(method, urlStr string, body interface{}) (*http.Request, error)
// GET request
req, err := client.NewRequest("GET", "repos/owner/repo", nil)

// POST request with body
createRepo := &github.Repository{
    Name:    github.Ptr("new-repo"),
    Private: github.Ptr(false),
}
req, err := client.NewRequest("POST", "user/repos", createRepo)

NewFormRequest

Create a form-encoded POST request.

func (c *Client) NewFormRequest(urlStr string, body io.Reader, opts ...RequestOption) (*http.Request, error)
// Create a form-encoded request
formData := url.Values{}
formData.Set("key", "value")
req, err := client.NewFormRequest("path/to/endpoint", strings.NewReader(formData.Encode()))

NewUploadRequest

Create a request for uploading assets.

func (c *Client) NewUploadRequest(urlStr string, reader io.Reader, size int64, mediaType string) (*http.Request, error)
file, _ := os.Open("asset.zip")
defer file.Close()

stat, _ := file.Stat()
req, err := client.NewUploadRequest(
    "repos/owner/repo/releases/123/assets?name=asset.zip",
    file,
    stat.Size(),
    "application/zip",
)

Client

Get the underlying http.Client.

func (c *Client) Client() *http.Client
httpClient := client.Client()
// Modify timeouts, transports, etc.

Utility Methods

APIMeta

Get information about GitHub.com API.

func (c *Client) APIMeta(ctx context.Context) (*APIMeta, *Response, error)

type APIMeta struct {
    Hooks                     []string
    Git                       []string
    Pages                     []string
    Importer                  []string
    Actions                   []string
    Dependabot                []string
    VerifiablePasswordAuthentication bool
    SSHKeyFingerprints        struct {
        SHA256_RSA   string
        SHA256_DSA   string
        SHA256_ECDSA string
        SHA256_ED25519 string
    }
}
meta, _, err := client.APIMeta(context.Background())
if err != nil {
    // Handle error
}

fmt.Printf("GitHub hooks IPs: %v\n", meta.Hooks)
fmt.Printf("SSH fingerprints: %+v\n", meta.SSHKeyFingerprints)

Octocat

Get ASCII art Octocat with optional message.

func (c *Client) Octocat(ctx context.Context, message string) (string, *Response, error)
octocat, _, err := client.Octocat(context.Background(), "Hello!")
if err != nil {
    // Handle error
}
fmt.Println(octocat)

Zen

Get a random line from The Zen of GitHub.

func (c *Client) Zen(ctx context.Context) (string, *Response, error)
zen, _, err := client.Zen(context.Background())
if err != nil {
    // Handle error
}
fmt.Println(zen) // e.g., "Design for failure."

ListEmojis

Get available GitHub emojis.

func (c *Client) ListEmojis(ctx context.Context) (map[string]string, *Response, error)
emojis, _, err := client.ListEmojis(context.Background())
if err != nil {
    // Handle error
}

// Map of emoji name to URL
fmt.Println(emojis["+1"])  // URL to thumbs up emoji image
fmt.Println(emojis["smile"]) // URL to smile emoji image

GetCodeOfConduct

Get a specific code of conduct.

func (c *Client) GetCodeOfConduct(ctx context.Context, key string) (*CodeOfConduct, *Response, error)

type CodeOfConduct struct {
    Name *string
    Key  *string
    URL  *string
    Body *string
}
coc, _, err := client.GetCodeOfConduct(context.Background(), "contributor_covenant")
if err != nil {
    // Handle error
}

fmt.Printf("Code of Conduct: %s\n", *coc.Name)
fmt.Printf("Content: %s\n", *coc.Body)

ListCodesOfConduct

Get all available codes of conduct.

func (c *Client) ListCodesOfConduct(ctx context.Context) ([]*CodeOfConduct, *Response, error)
cocs, _, err := client.ListCodesOfConduct(context.Background())
if err != nil {
    // Handle error
}

for _, coc := range cocs {
    fmt.Printf("%s: %s\n", *coc.Key, *coc.Name)
}

Error Handling

Error Types

// Standard API error response
type ErrorResponse struct {
    Response *http.Response
    Message  string
    Errors   []Error
    Block    *ErrorBlock
    DocumentationURL string
}

type Error struct {
    Resource string
    Field    string
    Code     string
    Message  string
}

type ErrorBlock struct {
    Reason    string
    CreatedAt *Timestamp
}

// Rate limit exceeded
type RateLimitError struct {
    Rate     Rate
    Response *http.Response
    Message  string
}

// Secondary/abuse rate limit
type AbuseRateLimitError struct {
    Response   *http.Response
    Message    string
    RetryAfter *time.Duration
}

// Two-factor authentication required
type TwoFactorAuthError ErrorResponse

// Request accepted but processing asynchronously (HTTP 202)
type AcceptedError struct{}

Error Handling Pattern

import "errors"

user, resp, err := client.Users.Get(ctx, "username")
if err != nil {
    // Check for rate limit error
    var rateLimitErr *github.RateLimitError
    if errors.As(err, &rateLimitErr) {
        fmt.Printf("Rate limited until: %v\n", rateLimitErr.Rate.Reset.Time)
        return
    }

    // Check for abuse rate limit
    var abuseErr *github.AbuseRateLimitError
    if errors.As(err, &abuseErr) {
        if abuseErr.RetryAfter != nil {
            fmt.Printf("Retry after: %v\n", *abuseErr.RetryAfter)
        }
        return
    }

    // Check for 2FA required
    var twoFactorErr *github.TwoFactorAuthError
    if errors.As(err, &twoFactorErr) {
        fmt.Println("Two-factor authentication required")
        return
    }

    // Check for standard API error
    var errResp *github.ErrorResponse
    if errors.As(err, &errResp) {
        fmt.Printf("API error: %s\n", errResp.Message)
        for _, err := range errResp.Errors {
            fmt.Printf("  - %s: %s\n", err.Field, err.Message)
        }
        return
    }

    // Other error
    fmt.Printf("Error: %v\n", err)
    return
}

Helper Functions

Pointer Helpers

Create pointers to literal values for API requests.

// Generic pointer helper (preferred)
func Ptr[T any](v T) *T

// Legacy type-specific helpers (deprecated)
func Bool(v bool) *bool
func Int(v int) *int
func Int64(v int64) *int64
func String(v string) *string
// Using the generic Ptr function (preferred)
repo := &github.Repository{
    Name:        github.Ptr("my-repo"),
    Description: github.Ptr("A test repository"),
    Private:     github.Ptr(false),
    AutoInit:    github.Ptr(true),
}

// Legacy approach (still works but deprecated)
repo := &github.Repository{
    Name:        github.String("my-repo"),
    Description: github.String("A test repository"),
    Private:     github.Bool(false),
    AutoInit:    github.Bool(true),
}

Stringify

Create a string representation of any library type.

func Stringify(message interface{}) string
user, _, _ := client.Users.Get(ctx, "octocat")
fmt.Println(github.Stringify(user))
// Output: &{Login:"octocat" ID:123 ... }

Common Types

Timestamp

Wrapper around time.Time for proper JSON marshaling with GitHub API.

type Timestamp struct {
    time.Time
}

func (t Timestamp) Equal(u Timestamp) bool
// Timestamps are used throughout the API
repo, _, _ := client.Repositories.Get(ctx, "owner", "repo")
fmt.Printf("Created: %v\n", repo.CreatedAt.Time)
fmt.Printf("Updated: %v\n", repo.UpdatedAt.Time)
fmt.Printf("Pushed: %v\n", repo.PushedAt.Time)

Context Usage

All API methods require a context.Context as the first parameter for cancellation, timeouts, and request metadata.

import (
    "context"
    "time"
)

// With timeout
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
repos, _, err := client.Repositories.List(ctx, "user", nil)

// With cancellation
ctx, cancel := context.WithCancel(context.Background())
go func() {
    // Cancel after some condition
    time.Sleep(5 * time.Second)
    cancel()
}()
repos, _, err := client.Repositories.List(ctx, "user", nil)

// With deadline
deadline := time.Now().Add(1 * time.Minute)
ctx, cancel := context.WithDeadline(context.Background(), deadline)
defer cancel()
repos, _, err := client.Repositories.List(ctx, "user", nil)

Request Context Keys

Special context keys for controlling request behavior.

const (
    // Bypass rate limit checking for this request
    BypassRateLimitCheck requestContext = iota

    // Automatically sleep until rate limit resets when rate limited
    SleepUntilPrimaryRateLimitResetWhenRateLimited
)
// Bypass rate limit check (use with caution)
ctx := context.WithValue(context.Background(),
    github.BypassRateLimitCheck, true)

// Auto-sleep on rate limit
ctx = context.WithValue(context.Background(),
    github.SleepUntilPrimaryRateLimitResetWhenRateLimited, true)

Library Version

const Version = "v79.0.0"
fmt.Printf("go-github version: %s\n", github.Version)