github.com/google/go-github/v70@v70.0.0/README.md (about)

     1  # go-github #
     2  
     3  [![go-github release (latest SemVer)](https://img.shields.io/github/v/release/google/go-github?sort=semver)](https://github.com/google/go-github/releases)
     4  [![Go Reference](https://img.shields.io/static/v1?label=godoc&message=reference&color=blue)](https://pkg.go.dev/github.com/google/go-github/v70/github)
     5  [![Test Status](https://github.com/google/go-github/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/google/go-github/actions/workflows/tests.yml)
     6  [![Test Coverage](https://codecov.io/gh/google/go-github/branch/master/graph/badge.svg)](https://codecov.io/gh/google/go-github)
     7  [![Discuss at go-github@googlegroups.com](https://img.shields.io/badge/discuss-go--github%40googlegroups.com-blue.svg)](https://groups.google.com/group/go-github)
     8  [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/796/badge)](https://bestpractices.coreinfrastructure.org/projects/796)
     9  
    10  go-github is a Go client library for accessing the [GitHub API v3][].
    11  
    12  go-github tracks [Go's version support policy][support-policy] supporting any
    13  minor version of the latest two major releases of Go and the go directive in
    14  go.mod reflects that.
    15  We do our best not to break older versions of Go if we don't have to, but we
    16  don't explicitly test older versions and as of Go 1.21 the go directive in
    17  go.mod declares a hard required _minimum_ version of Go to use with this module
    18  and this _must_ be greater than or equal to the go line of all dependencies so
    19  go-github will require the N-1 major release of Go by default.
    20  
    21  [support-policy]: https://golang.org/doc/devel/release.html#policy
    22  
    23  ## Development
    24  
    25  If you're interested in using the [GraphQL API v4][], the recommended library is
    26  [shurcooL/githubv4][].
    27  
    28  ## Installation ##
    29  
    30  go-github is compatible with modern Go releases in module mode, with Go installed:
    31  
    32  ```bash
    33  go get github.com/google/go-github/v70
    34  ```
    35  
    36  will resolve and add the package to the current development module, along with its dependencies.
    37  
    38  Alternatively the same can be achieved if you use import in a package:
    39  
    40  ```go
    41  import "github.com/google/go-github/v70/github"
    42  ```
    43  
    44  and run `go get` without parameters.
    45  
    46  Finally, to use the top-of-trunk version of this repo, use the following command:
    47  
    48  ```bash
    49  go get github.com/google/go-github/v70@master
    50  ```
    51  
    52  ## Usage ##
    53  
    54  ```go
    55  import "github.com/google/go-github/v70/github"	// with go modules enabled (GO111MODULE=on or outside GOPATH)
    56  import "github.com/google/go-github/github" // with go modules disabled
    57  ```
    58  
    59  Construct a new GitHub client, then use the various services on the client to
    60  access different parts of the GitHub API. For example:
    61  
    62  ```go
    63  client := github.NewClient(nil)
    64  
    65  // list all organizations for user "willnorris"
    66  orgs, _, err := client.Organizations.List(context.Background(), "willnorris", nil)
    67  ```
    68  
    69  Some API methods have optional parameters that can be passed. For example:
    70  
    71  ```go
    72  client := github.NewClient(nil)
    73  
    74  // list public repositories for org "github"
    75  opt := &github.RepositoryListByOrgOptions{Type: "public"}
    76  repos, _, err := client.Repositories.ListByOrg(context.Background(), "github", opt)
    77  ```
    78  
    79  The services of a client divide the API into logical chunks and correspond to
    80  the structure of the [GitHub API documentation](https://docs.github.com/en/rest).
    81  
    82  NOTE: Using the [context](https://pkg.go.dev/context) package, one can easily
    83  pass cancelation signals and deadlines to various services of the client for
    84  handling a request. In case there is no context available, then `context.Background()`
    85  can be used as a starting point.
    86  
    87  For more sample code snippets, head over to the
    88  [example](https://github.com/google/go-github/tree/master/example) directory.
    89  
    90  ### Authentication ###
    91  
    92  Use the `WithAuthToken` method to configure your client to authenticate using an
    93  OAuth token (for example, a [personal access token][]). This is what is needed
    94  for a majority of use cases aside from GitHub Apps.
    95  
    96  ```go
    97  client := github.NewClient(nil).WithAuthToken("... your access token ...")
    98  ```
    99  
   100  Note that when using an authenticated Client, all calls made by the client will
   101  include the specified OAuth token. Therefore, authenticated clients should
   102  almost never be shared between different users.
   103  
   104  For API methods that require HTTP Basic Authentication, use the
   105  [`BasicAuthTransport`](https://pkg.go.dev/github.com/google/go-github/github#BasicAuthTransport).
   106  
   107  #### As a GitHub App ####
   108  
   109  GitHub Apps authentication can be provided by different pkgs like [bradleyfalzon/ghinstallation](https://github.com/bradleyfalzon/ghinstallation)
   110  or [jferrl/go-githubauth](https://github.com/jferrl/go-githubauth).
   111  
   112  > **Note**: Most endpoints (ex. [`GET /rate_limit`]) require access token authentication
   113  > while a few others (ex. [`GET /app/hook/deliveries`]) require [JWT] authentication.
   114  
   115  [`GET /rate_limit`]: https://docs.github.com/en/rest/rate-limit#get-rate-limit-status-for-the-authenticated-user
   116  [`GET /app/hook/deliveries`]: https://docs.github.com/en/rest/apps/webhooks#list-deliveries-for-an-app-webhook
   117  [JWT]: https://docs.github.com/en/developers/apps/building-github-apps/authenticating-with-github-apps#authenticating-as-a-github-app
   118  
   119  `ghinstallation` provides `Transport`, which implements `http.RoundTripper` to provide authentication as an installation for GitHub Apps.
   120  
   121  Here is an example of how to authenticate as a GitHub App using the `ghinstallation` package:
   122  
   123  ```go
   124  import (
   125  	"net/http"
   126  
   127  	"github.com/bradleyfalzon/ghinstallation/v2"
   128  	"github.com/google/go-github/v70/github"
   129  )
   130  
   131  func main() {
   132  	// Wrap the shared transport for use with the integration ID 1 authenticating with installation ID 99.
   133  	itr, err := ghinstallation.NewKeyFromFile(http.DefaultTransport, 1, 99, "2016-10-19.private-key.pem")
   134  
   135  	// Or for endpoints that require JWT authentication
   136  	// itr, err := ghinstallation.NewAppsTransportKeyFromFile(http.DefaultTransport, 1, "2016-10-19.private-key.pem")
   137  
   138  	if err != nil {
   139  		// Handle error.
   140  	}
   141  
   142  	// Use installation transport with client.
   143  	client := github.NewClient(&http.Client{Transport: itr})
   144  
   145  	// Use client...
   146  }
   147  ```
   148  
   149  `go-githubauth` implements a set of `oauth2.TokenSource` to be used with `oauth2.Client`. An `oauth2.Client` can be injected into the `github.Client` to authenticate requests.
   150  
   151  Other example using `go-githubauth`:
   152  
   153  ```go
   154  package main
   155  
   156  import (
   157  	"context"
   158  	"fmt"
   159  	"os"
   160  	"strconv"
   161  
   162  	"github.com/google/go-github/v70/github"
   163  	"github.com/jferrl/go-githubauth"
   164  	"golang.org/x/oauth2"
   165  )
   166  
   167  func main() {
   168  	privateKey := []byte(os.Getenv("GITHUB_APP_PRIVATE_KEY"))
   169  
   170  	appTokenSource, err := githubauth.NewApplicationTokenSource(1112, privateKey)
   171  	if err != nil {
   172  		fmt.Println("Error creating application token source:", err)
   173  		return
   174  	 }
   175  
   176  	installationTokenSource := githubauth.NewInstallationTokenSource(1113, appTokenSource)
   177  
   178  	// oauth2.NewClient uses oauth2.ReuseTokenSource to reuse the token until it expires.
   179  	// The token will be automatically refreshed when it expires.
   180  	// InstallationTokenSource has the mechanism to refresh the token when it expires.
   181  	httpClient := oauth2.NewClient(context.Background(), installationTokenSource)
   182  
   183  	client := github.NewClient(httpClient)
   184  }
   185  ```
   186  
   187  *Note*: In order to interact with certain APIs, for example writing a file to a repo, one must generate an installation token
   188  using the installation ID of the GitHub app and authenticate with the OAuth method mentioned above. See the examples.
   189  
   190  ### Rate Limiting ###
   191  
   192  GitHub imposes a rate limit on all API clients. Unauthenticated clients are
   193  limited to 60 requests per hour, while authenticated clients can make up to
   194  5,000 requests per hour. The Search API has a custom rate limit. Unauthenticated
   195  clients are limited to 10 requests per minute, while authenticated clients
   196  can make up to 30 requests per minute. To receive the higher rate limit when
   197  making calls that are not issued on behalf of a user,
   198  use `UnauthenticatedRateLimitedTransport`.
   199  
   200  The returned `Response.Rate` value contains the rate limit information
   201  from the most recent API call. If a recent enough response isn't
   202  available, you can use `RateLimits` to fetch the most up-to-date rate
   203  limit data for the client.
   204  
   205  To detect an API rate limit error, you can check if its type is `*github.RateLimitError`:
   206  
   207  ```go
   208  repos, _, err := client.Repositories.List(ctx, "", nil)
   209  if _, ok := err.(*github.RateLimitError); ok {
   210  	log.Println("hit rate limit")
   211  }
   212  ```
   213  
   214  Learn more about GitHub rate limiting in
   215  ["REST API endpoints for rate limits"](https://docs.github.com/en/rest/rate-limit).
   216  
   217  In addition to these rate limits, GitHub imposes a secondary rate limit on all API clients.
   218  This rate limit prevents clients from making too many concurrent requests.
   219  
   220  To detect an API secondary rate limit error, you can check if its type is `*github.AbuseRateLimitError`:
   221  
   222  ```go
   223  repos, _, err := client.Repositories.List(ctx, "", nil)
   224  if _, ok := err.(*github.AbuseRateLimitError); ok {
   225  	log.Println("hit secondary rate limit")
   226  }
   227  ```
   228  
   229  Alternatively, you can block until the rate limit is reset by using the `context.WithValue` method:
   230  
   231  ```go
   232  repos, _, err := client.Repositories.List(context.WithValue(ctx, github.SleepUntilPrimaryRateLimitResetWhenRateLimited, true), "", nil)
   233  ```
   234  
   235  You can use [gofri/go-github-ratelimit](https://github.com/gofri/go-github-ratelimit) to handle
   236  secondary rate limit sleep-and-retry for you, as well as primary rate limit abuse-prevention and callback triggering.
   237  
   238  Learn more about GitHub secondary rate limiting in
   239  ["About secondary rate limits"](https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2022-11-28#about-secondary-rate-limits).
   240  
   241  ### Accepted Status ###
   242  
   243  Some endpoints may return a 202 Accepted status code, meaning that the
   244  information required is not yet ready and was scheduled to be gathered on
   245  the GitHub side. Methods known to behave like this are documented specifying
   246  this behavior.
   247  
   248  To detect this condition of error, you can check if its type is
   249  `*github.AcceptedError`:
   250  
   251  ```go
   252  stats, _, err := client.Repositories.ListContributorsStats(ctx, org, repo)
   253  if _, ok := err.(*github.AcceptedError); ok {
   254  	log.Println("scheduled on GitHub side")
   255  }
   256  ```
   257  
   258  ### Conditional Requests ###
   259  
   260  The GitHub REST API has good support for [conditional HTTP requests](https://docs.github.com/en/rest/using-the-rest-api/best-practices-for-using-the-rest-api?apiVersion=2022-11-28#use-conditional-requests-if-appropriate)
   261  via the `ETag` header which will help prevent you from burning through your
   262  rate limit, as well as help speed up your application. `go-github` does not
   263  handle conditional requests directly, but is instead designed to work with a
   264  caching `http.Transport`.
   265  
   266  Typically, an [RFC 7234](https://datatracker.ietf.org/doc/html/rfc7234)
   267  compliant HTTP cache such as [gregjones/httpcache](https://github.com/gregjones/httpcache)
   268  is recommended, ex:
   269  
   270  ```go
   271  import "github.com/gregjones/httpcache"
   272  
   273  client := github.NewClient(
   274  	httpcache.NewMemoryCacheTransport().Client()
   275  ).WithAuthToken(os.Getenv("GITHUB_TOKEN"))
   276  ```
   277  
   278  Alternatively, the [bored-engineer/github-conditional-http-transport](https://github.com/bored-engineer/github-conditional-http-transport)
   279  package relies on (undocumented) GitHub specific cache logic and is
   280  recommended when making requests using short-lived credentials such as a 
   281  [GitHub App installation token](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/authenticating-as-a-github-app-installation).
   282  
   283  ### Creating and Updating Resources ###
   284  
   285  All structs for GitHub resources use pointer values for all non-repeated fields.
   286  This allows distinguishing between unset fields and those set to a zero-value.
   287  Helper functions have been provided to easily create these pointers for string,
   288  bool, and int values. For example:
   289  
   290  ```go
   291  // create a new private repository named "foo"
   292  repo := &github.Repository{
   293  	Name:    github.Ptr("foo"),
   294  	Private: github.Ptr(true),
   295  }
   296  client.Repositories.Create(ctx, "", repo)
   297  ```
   298  
   299  Users who have worked with protocol buffers should find this pattern familiar.
   300  
   301  ### Pagination ###
   302  
   303  All requests for resource collections (repos, pull requests, issues, etc.)
   304  support pagination. Pagination options are described in the
   305  `github.ListOptions` struct and passed to the list methods directly or as an
   306  embedded type of a more specific list options struct (for example
   307  `github.PullRequestListOptions`). Pages information is available via the
   308  `github.Response` struct.
   309  
   310  ```go
   311  client := github.NewClient(nil)
   312  
   313  opt := &github.RepositoryListByOrgOptions{
   314  	ListOptions: github.ListOptions{PerPage: 10},
   315  }
   316  // get all pages of results
   317  var allRepos []*github.Repository
   318  for {
   319  	repos, resp, err := client.Repositories.ListByOrg(ctx, "github", opt)
   320  	if err != nil {
   321  		return err
   322  	}
   323  	allRepos = append(allRepos, repos...)
   324  	if resp.NextPage == 0 {
   325  		break
   326  	}
   327  	opt.Page = resp.NextPage
   328  }
   329  ```
   330  
   331  #### Iterators (**experimental**) ####
   332  
   333  Go v1.23 introduces the new `iter` package.  
   334  
   335  With the `enrichman/gh-iter` package, it is possible to create iterators for `go-github`. The iterator will handle pagination for you, looping through all the available results.
   336  
   337  ```go
   338  client := github.NewClient(nil)
   339  var allRepos []*github.Repository
   340  
   341  // create an iterator and start looping through all the results
   342  repos := ghiter.NewFromFn1(client.Repositories.ListByOrg, "github")
   343  for repo := range repos.All() {
   344  	allRepos = append(allRepos, repo)
   345  }
   346  ```
   347  
   348  For complete usage of `enrichman/gh-iter`, see the full [package docs](https://github.com/enrichman/gh-iter).
   349  
   350  #### Middleware ####
   351  
   352  You can use [gofri/go-github-pagination](https://github.com/gofri/go-github-pagination) to handle
   353  pagination for you. It supports both sync and async modes, as well as customizations.  
   354  By default, the middleware automatically paginates through all pages, aggregates results, and returns them as an array.  
   355  See `example/ratelimit/main.go` for usage.
   356  
   357  ### Webhooks ###
   358  
   359  `go-github` provides structs for almost all [GitHub webhook events][] as well as functions to validate them and unmarshal JSON payloads from `http.Request` structs.
   360  
   361  ```go
   362  func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) {
   363  	payload, err := github.ValidatePayload(r, s.webhookSecretKey)
   364  	if err != nil { ... }
   365  	event, err := github.ParseWebHook(github.WebHookType(r), payload)
   366  	if err != nil { ... }
   367  	switch event := event.(type) {
   368  	case *github.CommitCommentEvent:
   369  		processCommitCommentEvent(event)
   370  	case *github.CreateEvent:
   371  		processCreateEvent(event)
   372  	...
   373  	}
   374  }
   375  ```
   376  
   377  Furthermore, there are libraries like [cbrgm/githubevents][] that build upon the example above and provide functions to subscribe callbacks to specific events.
   378  
   379  For complete usage of go-github, see the full [package docs][].
   380  
   381  [GitHub API v3]: https://docs.github.com/en/rest
   382  [personal access token]: https://github.com/blog/1509-personal-api-tokens
   383  [package docs]: https://pkg.go.dev/github.com/google/go-github/v70/github
   384  [GraphQL API v4]: https://developer.github.com/v4/
   385  [shurcooL/githubv4]: https://github.com/shurcooL/githubv4
   386  [GitHub webhook events]: https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads
   387  [cbrgm/githubevents]: https://github.com/cbrgm/githubevents
   388  
   389  ### Testing code that uses `go-github` ###
   390  
   391  The repo [migueleliasweb/go-github-mock](https://github.com/migueleliasweb/go-github-mock) provides a way to mock responses. Check the repo for more details.
   392  
   393  ### Integration Tests ###
   394  
   395  You can run integration tests from the `test` directory. See the integration tests [README](test/README.md).
   396  
   397  ## Contributing ##
   398  
   399  I would like to cover the entire GitHub API and contributions are of course always welcome. The
   400  calling pattern is pretty well established, so adding new methods is relatively
   401  straightforward. See [`CONTRIBUTING.md`](CONTRIBUTING.md) for details.
   402  
   403  ## Versioning ##
   404  
   405  In general, go-github follows [semver](https://semver.org/) as closely as we
   406  can for tagging releases of the package. For self-contained libraries, the
   407  application of semantic versioning is relatively straightforward and generally
   408  understood. But because go-github is a client library for the GitHub API, which
   409  itself changes behavior, and because we are typically pretty aggressive about
   410  implementing preview features of the GitHub API, we've adopted the following
   411  versioning policy:
   412  
   413  * We increment the **major version** with any incompatible change to
   414  	non-preview functionality, including changes to the exported Go API surface
   415  	or behavior of the API.
   416  * We increment the **minor version** with any backwards-compatible changes to
   417  	functionality, as well as any changes to preview functionality in the GitHub
   418  	API. GitHub makes no guarantee about the stability of preview functionality,
   419  	so neither do we consider it a stable part of the go-github API.
   420  * We increment the **patch version** with any backwards-compatible bug fixes.
   421  
   422  Preview functionality may take the form of entire methods or simply additional
   423  data returned from an otherwise non-preview method. Refer to the GitHub API
   424  documentation for details on preview functionality.
   425  
   426  ### Calendar Versioning ###
   427  
   428  As of 2022-11-28, GitHub [has announced](https://github.blog/2022-11-28-to-infinity-and-beyond-enabling-the-future-of-githubs-rest-api-with-api-versioning/)
   429  that they are starting to version their v3 API based on "calendar-versioning".
   430  
   431  In practice, our goal is to make per-method version overrides (at
   432  least in the core library) rare and temporary.
   433  
   434  Our understanding of the GitHub docs is that they will be revving the
   435  entire API to each new date-based version, even if only a few methods
   436  have breaking changes. Other methods will accept the new version with
   437  their existing functionality. So when a new date-based version of the
   438  GitHub API is released, we (the repo maintainers) plan to:
   439  
   440  * update each method that had breaking changes, overriding their
   441    per-method API version header. This may happen in one or multiple
   442    commits and PRs, and is all done in the main branch.
   443  
   444  * once all of the methods with breaking changes have been updated,
   445    have a final commit that bumps the default API version, and remove
   446    all of the per-method overrides. That would now get a major version
   447    bump when the next go-github release is made.
   448  
   449  ### Version Compatibility Table ###
   450  
   451  The following table identifies which version of the GitHub API is
   452  supported by this (and past) versions of this repo (go-github).
   453  Versions prior to 48.2.0 are not listed.
   454  
   455  | go-github Version | GitHub v3 API Version |
   456  | ----------------- | --------------------- |
   457  | 70.0.0            | 2022-11-28            |
   458  | ...               | 2022-11-28            |
   459  | 48.2.0            | 2022-11-28            |
   460  
   461  ## License ##
   462  
   463  This library is distributed under the BSD-style license found in the [LICENSE](./LICENSE)
   464  file.