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