go-github
repository·master·Indexed 11 days ago
https://github.com/google/go-githubA type-safe Go client library for interacting with the GitHub REST API v3. It provides tools for managing repositories, issues, and users, with support for OAuth and GitHub App authentication, rate limit handling, and OpenTelemetry instrumentation. Includes the v90 module and an experimental scrape package for accessing data not available via standard APIs.
What's inside go-github
- go-github is a Go client library designed for accessing the GitHub REST API v3. It follows Go's version support policy, supporting any minor version of the latest two major releases of Go.
Use the scrape package for experimental GitHub data access
masterThe
scrapepackage provides an experimental client for accessing GitHub data via screen scraping. It is intended as a 'client of last resort' for data that is not available through the standard GitHub REST or GraphQL APIs.Usage Guidelines:
- Use only for unavailable data: If the data can be retrieved via the REST or GraphQL APIs, use those instead.
- Prefer read-only access: The package currently focuses on reading data; writing via scraping is considered high-risk.
- Minimalist approach: The package does not aim for exhaustive coverage of GitHub; it only implements what is necessary for specific use cases.
Understand go-github versioning policy
mastergo-github follows semantic versioning (semver) with specific rules regarding GitHub API preview features:
- Major version: Incremented for incompatible changes to non-preview functionality, including changes to the exported Go API surface or changes in the behavior of the underlying GitHub API.
- Minor version: Incremented for backwards-compatible changes and any changes to GitHub API preview functionality. Note that preview functionality is not considered a stable part of the go-github API.
- Patch version: Incremented for backwards-compatible bug fixes.
Preview functionality may appear as entirely new methods or as additional data returned from existing methods.
Create and Update Resources using Pointers
masterAll structs for GitHub resources use pointer values for non-repeated fields. This allows the API to distinguish between a field being unset and a field being set to its zero-value. Use the provided helper functions (e.g.,
github.Ptr) to create these pointers.// create a new private repository named "foo" repo := &github.Repository{ Name: github.Ptr("foo"), Private: github.Ptr(true), } client.Repositories.Create(ctx, "", repo)Handle Rate Limiting
masterGitHub enforces primary and secondary rate limits.
go-githubprovides several ways to manage these:- Detect Primary Rate Limit: Check if the error is of type
*github.RateLimitErrorusingerrors.As. - Detect Secondary Rate Limit: Check if the error is of type
*github.AbuseRateLimitError. - Wait for Reset: Use
context.WithValue(ctx, github.SleepUntilPrimaryRateLimitResetWhenRateLimited, true)to make a request block until the primary rate limit resets. - Bypass Check: Use
context.WithValue(ctx, github.BypassRateLimitCheck, true)to attempt a request even if the client thinks the rate limit has been hit.
For advanced management, the
gofri/go-github-ratelimitmiddleware is recommended.// Detect primary rate limit var rateErr *github.RateLimitError if errors.As(err, &rateErr) { log.Printf("hit primary rate limit, used %v of %v\n", rateErr.Rate.Used, rateErr.Rate.Limit) } // Detect secondary rate limit var abuseErr *github.AbuseRateLimitError if errors.As(err, &abuseErr) { log.Printf("hit secondary rate limit, retry after %v\n", abuseErr.RetryAfter) } // Block until primary rate limit reset ctxWithSleep := context.WithValue(ctx, github.SleepUntilPrimaryRateLimitResetWhenRateLimited, true) repos, _, err := client.Repositories.List(ctxWithSleep, "", nil)- Detect Primary Rate Limit: Check if the error is of type
Understand GitHub API calendar-versioning support
masterGitHub's v3 API uses calendar-versioning. The
go-githublibrary manages this by:- Updating specific methods that have breaking changes by overriding their per-method API version header.
- Once all breaking changes are addressed, the library bumps the default API version and removes per-method overrides (which triggers a major version bump of
go-github).
Always check the Version Compatibility Table in the documentation to ensure your version of
go-githubsupports the required GitHub v3 API version.Paginate through resource collections
masterResource collections (repos, PRs, etc.) support pagination via
github.ListOptions(for page numbers) orgithub.ListCursorOptions(for string cursors).Manual Pagination
Use the
NextPagefield in thegithub.Responsestruct to iterate through pages.Using Iterators (Go 1.23+)
If using Go 1.23 or later, you can use the auto-generated
*Itermethods (e.g.,ListIter) to range over results using the newiterpackage functionality.// Manual pagination opt := &github.RepositoryListByOrgOptions{ ListOptions: github.ListOptions{PerPage: 10}, } for { repos, resp, err := client.Repositories.ListByOrg(ctx, "github", opt) if err != nil { return err } allRepos = append(allRepos, repos...) if resp.NextPage == 0 { break } opt.Page = resp.NextPage } // Go 1.23+ Iterator iter := client.Repositories.ListIter(ctx, "github", nil) for repo, err := range iter { if err != nil { log.Fatal(err) } allRepos = append(allRepos, repo) }Import go-github in your Go project
masterWhen using the library, import the
githubsubpackage from thev90module. After adding the import statement, rungo getto resolve the dependency and its requirements.import "github.com/google/go-github/v90/github"Basic usage of go-github
masterTo use
go-github, import the package and construct a new client usinggithub.NewClient(). You can then access various GitHub API services through the client. Most methods require acontext.Contextto handle cancellation and deadlines; if no context is available, usecontext.Background().import "github.com/google/go-github/v90/github" client, err := github.NewClient() if err != nil { // Handle error. } // list all organizations for user "willnorris" orgs, _, err := client.Organizations.List(context.Background(), "willnorris", nil)How to add methods to the scrape package
masterTo implement new data access methods in the
scrapepackage, follow these steps:- Fetch the page: Use
client.getto retrieve the HTML contents of the target page. - Parse the markup: Use the
goquerylibrary to traverse and extract data from the HTML. - Select stable elements: When using
goqueryselectors, prefer semantic ID or class names, as these are more stable than other HTML attributes and less likely to break during GitHub UI updates.
Refer to
apps.gowithin the package for existing implementation examples.- Fetch the page: Use
Install go-github
masterTo use
go-githubin your project, install thev90module using Go's module mode. You can do this by running thego getcommand or by importing the package in your code and runninggo getwithout parameters.To use the latest development version (top-of-trunk), use the
@mastersuffix.# Install the latest stable v90 release go get github.com/google/go-github/v90 # Install the top-of-trunk (master) version go get github.com/google/go-github/v90@masterAuthenticate as a GitHub App
masterGitHub App authentication can be handled in two primary ways:
- Using
ghinstallation: This package provides aTransport(implementinghttp.RoundTripper) to authenticate as an installation. Usegithub.WithTransport(itr)to inject it into the client. - Using
go-githubauth: This package providesoauth2.TokenSourceimplementations. You can create anoauth2.Clientand inject it into thegithub.Clientusinggithub.WithHTTPClient(httpClient).
Note that some endpoints require access token authentication while others require JWT authentication.
// Example using ghinstallation import ( "net/http" "github.com/bradleyfalzon/ghinstallation/v2" "github.com/google/go-github/v90/github" ) // ... // Wrap the shared transport for use with the integration ID 1 authenticating with installation ID 99. itr, err := ghinstallation.NewKeyFromFile(http.DefaultTransport, 1, 99, "2016-10-19.private-key.pem") if err != nil { // Handle error } client, err := github.NewClient(github.WithTransport(itr))- Using