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