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