github_api 0.12.0 → 0.12.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +333 -327
- data/lib/github_api.rb +39 -4
- data/lib/github_api/api/actions.rb +35 -25
- data/lib/github_api/api/config/property_set.rb +1 -0
- data/lib/github_api/client/repos/deployments.rb +1 -0
- data/lib/github_api/configuration.rb +14 -6
- data/lib/github_api/connection.rb +5 -41
- data/lib/github_api/middleware.rb +30 -0
- data/lib/github_api/request/basic_auth.rb +3 -1
- data/lib/github_api/request/jsonize.rb +3 -1
- data/lib/github_api/version.rb +1 -1
- data/spec/github/api/actions_spec.rb +19 -0
- data/spec/github/api/set_spec.rb +2 -2
- data/spec/github/api/with_spec.rb +2 -3
- data/spec/github/api_spec.rb +1 -5
- data/spec/github/client/repos/deployments/create_spec.rb +2 -2
- data/spec/github/client/repos/deployments/create_status_spec.rb +2 -2
- data/spec/github/configuration_spec.rb +1 -1
- data/spec/github/configure_spec.rb +15 -0
- data/spec/github/request/jsonize_spec.rb +2 -2
- data/spec/github/stack_spec.rb +26 -0
- metadata +22 -24
data/README.md
CHANGED
@@ -21,18 +21,18 @@ Supports all the API methods. It's built in a modular way. You can either instan
|
|
21
21
|
|
22
22
|
## Features
|
23
23
|
|
24
|
-
* Intuitive GitHub API interface navigation.
|
25
|
-
* Modular design allows for working with parts of API. [api](#12-api-navigation)
|
26
|
-
* Fully customizable including advanced middleware stack construction. [config](#3-advanced-configuration)
|
24
|
+
* Intuitive GitHub API interface navigation.
|
27
25
|
* It's comprehensive. You can request all GitHub API resources.
|
28
|
-
*
|
29
|
-
*
|
30
|
-
*
|
31
|
-
*
|
26
|
+
* Modular design allows for working with parts of API.
|
27
|
+
* Fully customizable including advanced middleware stack construction.
|
28
|
+
* Supports OAuth2 authorization.
|
29
|
+
* Flexible argument parsing. You can write expressive and natural queries.
|
30
|
+
* Requests pagination with convenient DSL and automatic options.
|
31
|
+
* Easy error handling split for client and server type errors.
|
32
32
|
* Supports multithreaded environment.
|
33
|
-
* Custom media type specification through the 'media' parameter.
|
34
|
-
* Request results caching
|
35
|
-
* Fully tested with
|
33
|
+
* Custom media type specification through the 'media' parameter.
|
34
|
+
* Request results caching
|
35
|
+
* Fully tested with unit and feature tests hitting the live api.
|
36
36
|
|
37
37
|
## Installation
|
38
38
|
|
@@ -51,470 +51,474 @@ gem "github_api"
|
|
51
51
|
## Contents
|
52
52
|
|
53
53
|
* [1. Usage](#1-usage)
|
54
|
-
* [
|
55
|
-
* [
|
56
|
-
* [
|
57
|
-
* [
|
58
|
-
* [
|
59
|
-
* [
|
60
|
-
* [
|
61
|
-
* [
|
62
|
-
* [
|
63
|
-
* [
|
64
|
-
* [
|
65
|
-
* [
|
66
|
-
* [
|
67
|
-
* [
|
68
|
-
* [
|
54
|
+
* [1.1 API Navigation](#11-api-navigation)
|
55
|
+
* [1.2 Modularity](#12-modularity)
|
56
|
+
* [1.3 Arguments](#13-arguments)
|
57
|
+
* [1.4 Response Querying](#14-response-querying)
|
58
|
+
* [1.4.1 Response Body](#141-response-body)
|
59
|
+
* [1.4.2 Response Headers](#142-response-headers)
|
60
|
+
* [1.4.3 Response Success](#143-response-success)
|
61
|
+
* [1.5 Request Headers](#15-request-headers)
|
62
|
+
* [1.5.1 Media Types](#151-media-types)
|
63
|
+
* [2. Configuration](#2-configuration)
|
64
|
+
* [2.1 Basic](#21-basic)
|
65
|
+
* [2.2 Advanced](#22-advanced)
|
66
|
+
* [2.3 SSL](#23-ssl)
|
67
|
+
* [2.4 Caching](#24-caching)
|
68
|
+
* [3. Authentication](#3-authentication)
|
69
|
+
* [3.1 Basic](#31-basic)
|
70
|
+
* [3.2 Application OAuth](#32-application-oauth)
|
71
|
+
* [3.3 Authorizations API](#33-authorizations-api)
|
72
|
+
* [3.4 Scopes](#34-scopes)
|
73
|
+
* [4. Pagination](#4-pagination)
|
74
|
+
* [4.1 Auto pagination](#41-auto-pagination)
|
75
|
+
* [5. Error Handling](#5-error-handling)
|
76
|
+
* [6. Examples](#6-examples)
|
77
|
+
* [6.1 Rails](#61-rails)
|
78
|
+
* [6.2 Manipulating Files](#62-manipulating-files)
|
79
|
+
* [7. Testing](#7-testing)
|
69
80
|
|
70
81
|
## 1 Usage
|
71
82
|
|
72
|
-
To start using the gem, you can either perform
|
83
|
+
To start using the gem, you can either perform requests directly on `Github` namespace:
|
73
84
|
|
74
85
|
```ruby
|
75
|
-
Github.repos.list user: '
|
86
|
+
Github.repos.list user: 'peter-murach'
|
76
87
|
```
|
77
88
|
|
78
|
-
or create a new client instance
|
89
|
+
or create a new client instance like so
|
79
90
|
|
80
91
|
```ruby
|
81
92
|
github = Github.new
|
82
93
|
```
|
83
94
|
|
84
|
-
|
85
|
-
|
86
|
-
At this stage, you can also supply various configuration parameters, such as
|
87
|
-
```
|
88
|
-
adapter # http client used for performing requests
|
89
|
-
auto_pagination # false by default, set to true to traverse requests page links
|
90
|
-
oauth_token # oauth authorization token
|
91
|
-
basic_auth # login:password string
|
92
|
-
client_id # oauth client id
|
93
|
-
client_secret # oauth client secret
|
94
|
-
user # global user used in requests if none provided
|
95
|
-
repo # global repository used in requests in none provided
|
96
|
-
org # global organization used in requests if none provided
|
97
|
-
endpoint # enterprise API endpoint
|
98
|
-
site # enterprise API web endpoint
|
99
|
-
ssl # SSL settings
|
100
|
-
per_page # number of items per page- max of 100
|
101
|
-
user_agent # custom user agent name, 'Github API' by default
|
102
|
-
```
|
103
|
-
which are used throughout the API. These can be passed directly as hash options:
|
95
|
+
and then call api methods, for instance, to list a given user repositories do
|
104
96
|
|
105
97
|
```ruby
|
106
|
-
github
|
98
|
+
github.repos.list user: 'peter-murach'
|
107
99
|
```
|
108
100
|
|
109
|
-
|
101
|
+
### 1.1 API Navigation
|
102
|
+
|
103
|
+
The **github_api** closely mirrors the [GitHub API](https://developer.github.com/v3/) hierarchy. For example, if you want to create a new file in a repository, look up the GitHub API spec. In there you will find contents sub category underneath the repository category. This would translate to the request:
|
110
104
|
|
111
105
|
```ruby
|
112
|
-
github = Github.new
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
config.adapter = :net_http
|
117
|
-
config.ssl = {:verify => false}
|
118
|
-
end
|
106
|
+
github = Github.new
|
107
|
+
github.repos.contents.create 'peter-murach', 'finite_machine', 'hello.rb',
|
108
|
+
path: 'hello.rb',
|
109
|
+
content: "puts 'hello ruby'"
|
119
110
|
```
|
120
111
|
|
121
|
-
|
112
|
+
The whole library reflects the same api navigation. Therefore, if you need to list releases for a repository do:
|
122
113
|
|
123
114
|
```ruby
|
124
|
-
github
|
115
|
+
github.repos.releases.list 'peter-murach', 'finite_machine'
|
125
116
|
```
|
126
117
|
|
127
|
-
or
|
118
|
+
or to list a user's followers:
|
128
119
|
|
129
120
|
```ruby
|
130
|
-
github
|
121
|
+
github.users.followers.list 'peter-murach'
|
131
122
|
```
|
132
123
|
|
133
|
-
|
124
|
+
The code base has been extensively documented with examples of how to use each method. Please refer to the [documentation](http://rubydoc.info/github/peter-murach/github/master/frames) under the `Github::Client` class name.
|
134
125
|
|
135
|
-
|
136
|
-
look up the GitHub API spec and issue the request as in `github.repos.downloads.create`
|
137
|
-
|
138
|
-
For example to interact with GitHub Repositories API, issue the following calls that correspond directly to the GitHub API hierarchy
|
126
|
+
Alternatively, you can find out which methods are supported by an api by calling `actions` on a class or instance. For example, in order to find out available endpoints for `Github::Client::Repos::Contents` api call `actions` method:
|
139
127
|
|
140
128
|
```ruby
|
141
|
-
|
142
|
-
|
143
|
-
github.repos.keys.get 'user-name', 'repo-name'
|
129
|
+
Github::Client::Repos::Contents.actions
|
130
|
+
=> [:archive, :create, :delete, :find, :get, :readme, :update]
|
144
131
|
```
|
145
132
|
|
146
|
-
### 1.
|
133
|
+
### 1.2 Modularity
|
147
134
|
|
148
|
-
The code base is modular
|
135
|
+
The code base is modular. This means that you can work specifically with a given part of GitHub API. If you want to only work with activity starring API do the following:
|
149
136
|
|
150
137
|
```ruby
|
151
|
-
|
152
|
-
|
138
|
+
starring = Github::Client::Activity::Starring.new
|
139
|
+
starring.star 'peter-murach', 'github'
|
153
140
|
```
|
154
141
|
|
155
|
-
|
156
|
-
|
142
|
+
Please refer to the [documentation](http://rubydoc.info/github/peter-murach/github/master/frames) and look under `Github::Client` to see all available classes.
|
143
|
+
|
144
|
+
### 1.3 Arguments
|
145
|
+
|
146
|
+
The **github_api** library allows for flexible argument parsing.
|
147
|
+
|
148
|
+
Arguments can be passed directly inside the method called. The `required` arguments are passed in first, followed by optional parameters supplied as hash options:
|
157
149
|
|
158
150
|
```ruby
|
159
|
-
|
160
|
-
|
161
|
-
puts branch.name
|
162
|
-
end
|
151
|
+
issues = Github::Client::Issues.new
|
152
|
+
issues.milestones.list 'peter-murach', 'github', state: 'open'
|
163
153
|
```
|
164
154
|
|
165
|
-
|
166
|
-
|
167
|
-
The **GithubAPI** library allows for flexible argument parsing. Therefore, arguments can be passed during instance creation:
|
155
|
+
In the previous example, the order of arguments is important. However, each method also allows you to specify `required` arguments using hash symbols and thus remove the need for ordering. Therefore, the same example could be rewritten like so:
|
168
156
|
|
169
157
|
```ruby
|
170
|
-
|
171
|
-
|
158
|
+
issues = Github::Client::Issues.new
|
159
|
+
issues.milestones.list user: 'peter-murach', repo: 'github', state: 'open'
|
172
160
|
```
|
173
161
|
|
174
|
-
|
162
|
+
Furthermore, `required` arguments can be passed during instance creation:
|
175
163
|
|
176
164
|
```ruby
|
177
|
-
|
178
|
-
|
165
|
+
issues = Github::Client::Issues.new user: 'peter-murach', repo: 'github'
|
166
|
+
issues.milestones.list state: 'open'
|
179
167
|
```
|
180
168
|
|
181
|
-
Similarly, the arguments for the request can be passed inside the current scope such as:
|
169
|
+
Similarly, the `required` arguments for the request can be passed inside the current scope such as:
|
182
170
|
|
183
171
|
```ruby
|
184
|
-
|
185
|
-
|
172
|
+
issues = Github::Client::Issues.new
|
173
|
+
issues.milestones(user: 'peter-murach', repo: 'github').list state: 'open'
|
186
174
|
```
|
187
175
|
|
188
176
|
But why limit ourselves? You can mix and match arguments, for example:
|
189
177
|
|
190
178
|
```ruby
|
191
|
-
|
192
|
-
|
193
|
-
|
179
|
+
issues = Github::Client::Issues.new user: 'peter-murach'
|
180
|
+
issues.milestones(repo: 'github').list
|
181
|
+
issues.milestones(repo: 'tty').list
|
194
182
|
```
|
195
183
|
|
196
|
-
You can also use a bit of syntactic sugar
|
184
|
+
You can also use a bit of syntactic sugar whereby "username/repository" can be passed as well:
|
197
185
|
|
198
186
|
```ruby
|
199
|
-
|
200
|
-
|
201
|
-
|
187
|
+
issues = Github::Client::Issues.new
|
188
|
+
issues.milestones('peter-murach/github').list
|
189
|
+
issues.milestones.list 'peter-murach/github'
|
202
190
|
```
|
203
191
|
|
204
192
|
Finally, use the `with` scope to clearly denote your requests
|
205
193
|
|
206
194
|
```ruby
|
207
|
-
|
208
|
-
|
195
|
+
issues = Github::Client::Issues.new
|
196
|
+
issues.milestones.with(user: 'peter-murach', repo: 'github').list
|
209
197
|
```
|
210
198
|
|
211
|
-
|
212
|
-
or organisation name, allow you to switch the way the data is returned to you, for instance
|
199
|
+
Please consult the method [documentation](http://rubydoc.info/github/peter-murach/github/master/frames) or [GitHub specification](https://developer.github.com/v3/) to see which arguments are required and what are the option parameters.
|
213
200
|
|
214
|
-
|
215
|
-
github = Github.new
|
216
|
-
github.git_data.trees.get 'peter-murach', 'github', 'c18647b75d72f19c1e0cc8af031e5d833b7f12ea'
|
217
|
-
# => gets a tree
|
201
|
+
### 1.4 Response Querying
|
218
202
|
|
219
|
-
|
220
|
-
recursive: true # => gets a whole tree recursively
|
221
|
-
```
|
203
|
+
The response is of type `Github::ResponseWrapper` and allows traversing all the json response attributes like method calls. In addition, if the response returns more than one resource, these will be automatically yielded to the provided block one by one.
|
222
204
|
|
223
|
-
|
205
|
+
For example, when request is issued to list all the branches on a given repository, each branch will be yielded one by one:
|
224
206
|
|
225
207
|
```ruby
|
226
|
-
|
227
|
-
|
228
|
-
|
208
|
+
repos = Github::Client::Repos.new
|
209
|
+
repos.branches user: 'peter-murach', repo: 'github' do |branch|
|
210
|
+
puts branch.name
|
229
211
|
end
|
230
212
|
```
|
231
213
|
|
232
|
-
|
214
|
+
#### 1.4.1 Response Body
|
233
215
|
|
234
|
-
The `
|
216
|
+
The `ResponseWrapper` allows you to call json attributes directly as method calls. there is no magic here, all calls are delegated to the response body. Therefore, you can directly inspect request body by calling `body` method on the `ResponseWrapper` like so:
|
235
217
|
|
236
218
|
```ruby
|
237
|
-
|
238
|
-
|
239
|
-
end
|
219
|
+
response = repos.branches user: 'peter-murach', repo: 'github'
|
220
|
+
response.body # => Array of branches
|
240
221
|
```
|
241
222
|
|
242
|
-
|
223
|
+
#### 1.4.2 Response Headers
|
243
224
|
|
244
|
-
|
245
|
-
github = Github.new do |config|
|
246
|
-
config.adapter :excon
|
225
|
+
Each response comes packaged with methods allowing for inspection of HTTP start line and headers. For example, to check for rate limits and status codes do:
|
247
226
|
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
227
|
+
```ruby
|
228
|
+
response = Github::Client::Repos.branches 'peter-murach', 'github'
|
229
|
+
response.headers.ratelimit_limit # "5000"
|
230
|
+
response.headers.ratelimit_remaining # "4999"
|
231
|
+
response.headers.status # "200"
|
232
|
+
response.headers.content_type # "application/json; charset=utf-8"
|
233
|
+
response.headers.etag # "\"2c5dfc54b3fe498779ef3a9ada9a0af9\""
|
234
|
+
response.headers.cache_control # "public, max-age=60, s-maxage=60"
|
253
235
|
```
|
254
236
|
|
255
|
-
|
237
|
+
#### 1.4.3 Response Success
|
256
238
|
|
257
|
-
|
258
|
-
|
259
|
-
To start making requests as authenticated user you can use your GitHub username and password like so
|
239
|
+
If you want to verify if the response was success, namely, that the `200` code was returned call the `success?` like so:
|
260
240
|
|
261
241
|
```ruby
|
262
|
-
Github.
|
242
|
+
response = Github::Client::Repos.branches 'peter-murach', 'github'
|
243
|
+
response.success? # => true
|
263
244
|
```
|
264
245
|
|
265
|
-
|
246
|
+
### 1.5 Request Headers
|
266
247
|
|
267
|
-
|
248
|
+
It is possible to specify additional header information which will be added to the final request.
|
268
249
|
|
269
|
-
|
270
|
-
|
271
|
-
* Visit https://github.com/settings/applications/new and register your app.
|
272
|
-
You will need to be logged in to initially register the application.
|
273
|
-
|
274
|
-
* Authorize your credentials https://github.com/login/oauth/authorize
|
275
|
-
|
276
|
-
You can use convenience methods to help you achieve this using **GithubAPI** gem:
|
250
|
+
For example, to set `etag` and `X-Poll_Interval` headers, use the `:headers` hash key inside the `:options` hash like in the following:
|
277
251
|
|
278
252
|
```ruby
|
279
|
-
|
280
|
-
|
281
|
-
|
253
|
+
events = Github::Client::Activity::Events.new
|
254
|
+
events.public options: {
|
255
|
+
headers: {
|
256
|
+
'X-Poll-Interval': 60,
|
257
|
+
'ETag': "a18c3bded88eb5dbb5c849a489412bf3"
|
258
|
+
}
|
259
|
+
}
|
282
260
|
```
|
283
|
-
|
261
|
+
|
262
|
+
#### 1.5.1 Media Types
|
263
|
+
|
264
|
+
In order to set custom media types for a request use the accept header. By using the `:accept` key you can determine media type like in the example:
|
284
265
|
|
285
266
|
```ruby
|
286
|
-
|
267
|
+
issues = Github::Client::Issues.new
|
268
|
+
issues.get 'peter-murach', 'github', 108, accept: 'application/vnd.github.raw'
|
287
269
|
```
|
288
270
|
|
289
|
-
|
290
|
-
|
291
|
-
**Note**: If you are working locally (i.e. your app URL and callback URL are localhost), do not specify a ```:redirect_uri``` otherwise you will get a ```redirect_uri_mismatch``` error.
|
271
|
+
## 2 Configuration
|
292
272
|
|
293
|
-
|
273
|
+
The **github_api** provides ability to specify global configuration options. These options will be available to all api calls.
|
294
274
|
|
295
|
-
|
275
|
+
### 2.1 Basic
|
296
276
|
|
297
|
-
|
277
|
+
The configuration options can be set by using the `configure` helper
|
298
278
|
|
299
279
|
```ruby
|
300
|
-
|
301
|
-
|
280
|
+
Github.configure do |c|
|
281
|
+
c.basic_auth = "login:password"
|
282
|
+
c.adapter = :typheous
|
283
|
+
c.user = 'peter-murach'
|
284
|
+
c.repo = 'finite_machine'
|
285
|
+
end
|
302
286
|
```
|
303
287
|
|
304
|
-
|
305
|
-
|
306
|
-
#### 4.3.2 For an App
|
307
|
-
|
308
|
-
Furthermore, to create auth token for an application you need to pass `:app` argument together with `:client_id` and `:client_secret` parameters.
|
288
|
+
Alternatively, you can configure the settings by passing a block to an instance like:
|
309
289
|
|
310
290
|
```ruby
|
311
|
-
|
312
|
-
github.
|
291
|
+
Github.new do |c|
|
292
|
+
c.endpoint = 'https://github.company.com/api/v3'
|
293
|
+
c.site = 'https://github.company.com'
|
294
|
+
end
|
313
295
|
```
|
314
296
|
|
315
|
-
|
297
|
+
or simply by passing hash of options to an instance like so
|
316
298
|
|
317
299
|
```ruby
|
318
|
-
github = Github.new basic_auth:
|
319
|
-
|
300
|
+
github = Github.new basic_auth: 'login:password',
|
301
|
+
adapter: :typheous,
|
302
|
+
user: 'peter-murach',
|
303
|
+
repo: 'finite_machine'
|
320
304
|
```
|
321
305
|
|
322
|
-
|
306
|
+
The following is the full list of available configuration options:
|
323
307
|
|
324
308
|
```ruby
|
325
|
-
|
309
|
+
adapter # Http client used for performing requests. Default :net_http
|
310
|
+
auto_pagination # Automatically traverse requests page links. Default false
|
311
|
+
basic_auth # Basic authentication in form login:password.
|
312
|
+
client_id # Oauth client id.
|
313
|
+
client_secret # Oauth client secret.
|
314
|
+
connection_options # Hash of connection options.
|
315
|
+
endpoint # Enterprise API endpoint. Default: 'https://api.github.com'
|
316
|
+
oauth_token # Oauth authorization token.
|
317
|
+
org # Global organization used in requests if none provided
|
318
|
+
per_page # Number of items per page. Max of 100. Default 30.
|
319
|
+
repo # Global repository used in requests in none provided
|
320
|
+
site # enterprise API web endpoint
|
321
|
+
ssl # SSL settings in hash form.
|
322
|
+
user # Global user used for requests if none provided
|
323
|
+
user_agent # Custom user agent name. Default 'Github API Ruby Gem'
|
326
324
|
```
|
327
325
|
|
328
|
-
###
|
326
|
+
### 2.2 Advanced
|
329
327
|
|
330
|
-
|
328
|
+
The **github_api** will use the default middleware stack which is exposed by calling `stack` on a client instance. However, this stack can be freely modified with methods such as `insert`, `insert_after`, `delete` and `swap`. For instance, to add your `CustomMiddleware` do:
|
331
329
|
|
332
330
|
```ruby
|
333
|
-
|
334
|
-
|
331
|
+
Github.configure do |c|
|
332
|
+
c.stack.insert_after Github::Response::Helpers, CustomMiddleware
|
333
|
+
end
|
335
334
|
```
|
336
335
|
|
337
|
-
|
336
|
+
Furthermore, you can build your entire custom stack and specify other connection options such as `adapter` by doing:
|
338
337
|
|
339
338
|
```ruby
|
340
|
-
|
341
|
-
|
342
|
-
res.headers.accepted_oauth_scopes # => ['delete_repo', 'repo', 'public_repo', 'repo:status']
|
343
|
-
```
|
339
|
+
Github.new do |c|
|
340
|
+
c.adapter :excon
|
344
341
|
|
345
|
-
|
342
|
+
c.stack do |builder|
|
343
|
+
builder.use Github::Response::Helpers
|
344
|
+
builder.use Github::Response::Jsonize
|
345
|
+
end
|
346
|
+
end
|
347
|
+
```
|
346
348
|
|
347
|
-
|
349
|
+
### 2.3 SSL
|
348
350
|
|
349
351
|
By default requests over SSL are set to OpenSSL::SSL::VERIFY_PEER. However, you can turn off peer verification by
|
350
352
|
|
351
353
|
```ruby
|
352
|
-
|
354
|
+
github = Github.new ssl: { verify: false }
|
353
355
|
```
|
354
356
|
|
355
357
|
If your client fails to find CA certs, you can pass other SSL options to specify exactly how the information is sourced
|
356
358
|
|
357
359
|
```ruby
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
360
|
+
ssl: {
|
361
|
+
client_cert: "/usr/local/www.example.com/client_cert.pem"
|
362
|
+
client_key: "/user/local/www.example.com/client_key.pem"
|
363
|
+
ca_file: "example.com.cert"
|
364
|
+
ca_path: "/etc/ssl/"
|
365
|
+
}
|
364
366
|
```
|
365
367
|
|
366
|
-
For instance, download CA root certificates from Mozilla [cacert](http://curl.haxx.se/ca/cacert.pem) and point ca_file at your certificate bundle location.
|
367
|
-
This will allow the client to verify the github.com ssl certificate as authentic.
|
368
|
+
For instance, download CA root certificates from Mozilla [cacert](http://curl.haxx.se/ca/cacert.pem) and point ca_file at your certificate bundle location. This will allow the client to verify the github.com ssl certificate as authentic.
|
368
369
|
|
369
|
-
|
370
|
+
### 2.4 Caching
|
370
371
|
|
371
|
-
|
372
|
+
Caching is supported through the [`faraday-http-cache` gem](https://github.com/plataformatec/faraday-http-cache).
|
372
373
|
|
373
|
-
|
374
|
-
Github - full API access
|
374
|
+
Add the gem to your Gemfile:
|
375
375
|
|
376
|
-
|
377
|
-
|
378
|
-
Github::PullRequests Github::Users Github::Activity
|
376
|
+
```ruby
|
377
|
+
gem 'faraday-http-cache'
|
379
378
|
```
|
380
379
|
|
381
|
-
|
380
|
+
You can now configure cache parameters as follows
|
382
381
|
|
383
382
|
```ruby
|
384
|
-
Github
|
385
|
-
|
383
|
+
Github.configure do |config|
|
384
|
+
config.stack do |builder|
|
385
|
+
builder.use Faraday::HttpCache, store: Rails.cache
|
386
|
+
end
|
387
|
+
end
|
386
388
|
```
|
387
389
|
|
388
|
-
|
390
|
+
More details on the available options can be found in the gem's own documentation: https://github.com/plataformatec/faraday-http-cache#faraday-http-cache
|
391
|
+
|
392
|
+
## 3 Authentication
|
393
|
+
|
394
|
+
### 3.1 Basic
|
395
|
+
|
396
|
+
To start making requests as authenticated user you can use your GitHub username and password like so
|
389
397
|
|
390
398
|
```ruby
|
391
|
-
|
392
|
-
github.users.followers.following 'wycats' # => returns users that 'wycats' is following
|
393
|
-
github.users.followers.following? 'wycats' # => returns true if following, otherwise false
|
399
|
+
Github.new basic_auth: 'login:password'
|
394
400
|
```
|
395
401
|
|
396
|
-
|
397
|
-
|
402
|
+
Though this method is convenient you should strongly consider using `OAuth` for improved security reasons.
|
403
|
+
|
404
|
+
### 3.2 Application OAuth
|
398
405
|
|
399
|
-
|
406
|
+
In order to authenticate your app through OAuth2 on GitHub you need to
|
407
|
+
|
408
|
+
* Visit https://github.com/settings/applications/new and register your app.
|
409
|
+
You will need to be logged in to initially register the application.
|
410
|
+
|
411
|
+
* Authorize your credentials https://github.com/login/oauth/authorize
|
412
|
+
|
413
|
+
You can use convenience methods to help you achieve this using **GithubAPI** gem:
|
400
414
|
|
401
415
|
```ruby
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|--> branches |--> comments
|
406
|
-
|--> collaborators |--> create
|
407
|
-
|--> commits |--> edit
|
408
|
-
|--> contribs |--> events
|
409
|
-
|--> contributors |--> find
|
410
|
-
|--> create |--> get
|
411
|
-
|--> downloads |--> labels
|
412
|
-
|--> edit |--> list
|
413
|
-
|--> find |--> list_repo
|
414
|
-
|--> forks |--> list_repository
|
415
|
-
|--> get |--> milestones
|
416
|
-
|--> hooks ...
|
417
|
-
...
|
416
|
+
github = Github.new client_id: '...', client_secret: '...'
|
417
|
+
github.authorize_url redirect_uri: 'http://localhost', scope: 'repo'
|
418
|
+
# => "https://github.com/login/oauth/authorize?scope=repo&response_type=code&client_id='...'&redirect_uri=http%3A%2F%2Flocalhost"
|
418
419
|
```
|
420
|
+
After you get your authorization code, call to receive your access_token
|
419
421
|
|
420
|
-
|
422
|
+
```ruby
|
423
|
+
token = github.get_token( authorization_code )
|
424
|
+
```
|
421
425
|
|
422
|
-
|
423
|
-
|
426
|
+
Once you have your access token, configure your github instance following instructions under Configuration.
|
427
|
+
|
428
|
+
**Note**: If you are working locally (i.e. your app URL and callback URL are localhost), do not specify a ```:redirect_uri``` otherwise you will get a ```redirect_uri_mismatch``` error.
|
429
|
+
|
430
|
+
### 3.3 Authorizations API
|
431
|
+
|
432
|
+
#### 3.3.1 For an User
|
433
|
+
|
434
|
+
To create an access token through the GitHub Authrizations API, you are required to pass your basic credentials and scopes you wish to have for the authentication token.
|
424
435
|
|
425
436
|
```ruby
|
426
|
-
github = Github.new
|
427
|
-
github.
|
437
|
+
github = Github.new basic_auth: 'login:password'
|
438
|
+
github.oauth.create scopes: ['repo']
|
428
439
|
```
|
429
440
|
|
430
|
-
|
441
|
+
You can add more than one scope from the `user`, `public_repo`, `repo`, `gist` or leave the scopes parameter out, in which case, the default read-only access will be assumed (includes public user profile info, public repo info, and gists).
|
431
442
|
|
432
|
-
|
443
|
+
#### 3.3.2 For an App
|
433
444
|
|
434
|
-
|
445
|
+
Furthermore, to create auth token for an application you need to pass `:app` argument together with `:client_id` and `:client_secret` parameters.
|
435
446
|
|
436
447
|
```ruby
|
437
|
-
github
|
448
|
+
github = Github.new basic_auth: 'login:password'
|
449
|
+
github.oauth.app.create 'client-id', scopes: ['repo']
|
438
450
|
```
|
439
451
|
|
440
|
-
|
441
|
-
|
442
|
-
TODO
|
452
|
+
In order to revoke auth token(s) for an application you must use basic authentication with `client_id` as login and `client_secret` as password.
|
443
453
|
|
444
|
-
|
454
|
+
```ruby
|
455
|
+
github = Github.new basic_auth: "client_id:client_secret"
|
456
|
+
github.oauth.app.delete 'client-id'
|
457
|
+
```
|
445
458
|
|
446
|
-
|
447
|
-
register an app at https://github.com/settings/applications/
|
448
|
-
You will need to be logged in to register the application.
|
459
|
+
Revoke a specific app token.
|
449
460
|
|
450
461
|
```ruby
|
451
|
-
|
452
|
-
|
453
|
-
config.basic_auth = 'login:password'
|
454
|
-
end
|
462
|
+
github.oauth.app.delete 'client-id', 'access-token'
|
463
|
+
```
|
455
464
|
|
456
|
-
|
465
|
+
### 3.4 Scopes
|
457
466
|
|
458
|
-
|
459
|
-
|
467
|
+
You can check OAuth scopes you have by:
|
468
|
+
|
469
|
+
```ruby
|
470
|
+
github = Github.new :oauth_token => 'token'
|
471
|
+
github.scopes.list # => ['repo']
|
460
472
|
```
|
461
473
|
|
462
|
-
|
474
|
+
To list the scopes that the particular GitHub API action checks for do:
|
475
|
+
|
476
|
+
```ruby
|
477
|
+
repos = Github::Client::Repos.new
|
478
|
+
response = repos.list user: 'peter-murach'
|
479
|
+
response.headers.accepted_oauth_scopes # => ['delete_repo', 'repo', 'public_repo']
|
480
|
+
```
|
463
481
|
|
482
|
+
To understand what each scope means refer to [documentation](http://developer.github.com/v3/oauth/#scopes)
|
464
483
|
|
465
|
-
By default, no caching will be performed. In order to set the cache do... If no cache type is provided, a default memoization is done.
|
466
484
|
|
467
|
-
##
|
485
|
+
## 4 Pagination
|
468
486
|
|
469
487
|
Any request that returns multiple items will be paginated to 30 items by default. You can specify custom `page` and `per_page` query parameters to alter default behavior. For instance:
|
470
488
|
|
471
489
|
```ruby
|
472
|
-
repos
|
473
|
-
repos.list user: 'wycats', per_page: 10, page: 5
|
490
|
+
repos = Github::Client::Repos.new
|
491
|
+
response = repos.list user: 'wycats', per_page: 10, page: 5
|
474
492
|
```
|
475
493
|
|
476
494
|
Then you can query the pagination information included in the link header by:
|
477
495
|
|
478
496
|
```ruby
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
497
|
+
response.links.first # Shows the URL of the first page of results.
|
498
|
+
response.links.next # Shows the URL of the immediate next page of results.
|
499
|
+
response.links.prev # Shows the URL of the immediate previous page of results.
|
500
|
+
response.links.last # Shows the URL of the last page of results.
|
483
501
|
```
|
484
502
|
|
485
503
|
In order to iterate through the entire result set page by page, you can use convenience methods:
|
486
504
|
|
487
505
|
```ruby
|
488
|
-
|
506
|
+
response.each_page do |page|
|
489
507
|
page.each do |repo|
|
490
508
|
puts repo.name
|
491
509
|
end
|
492
510
|
end
|
493
511
|
```
|
494
512
|
|
495
|
-
or use `has_next_page?` and `next_page` like in the following:
|
513
|
+
or use `has_next_page?` and `next_page` helper methods like in the following:
|
496
514
|
|
497
515
|
```ruby
|
498
|
-
while
|
516
|
+
while response.has_next_page?
|
499
517
|
... process response ...
|
500
518
|
res.next_page
|
501
519
|
end
|
502
520
|
```
|
503
521
|
|
504
|
-
Alternatively, you can retrieve all pages in one invocation by passing the `auto_pagination` option like so:
|
505
|
-
|
506
|
-
```ruby
|
507
|
-
github = Github.new auto_pagination: true
|
508
|
-
```
|
509
|
-
|
510
|
-
Depending at what stage you pass the `auto_pagination` it will affect all or only a single request:
|
511
|
-
|
512
|
-
```ruby
|
513
|
-
Github::Repos.new auto_pagination: true # affects Repos part of API
|
514
|
-
|
515
|
-
Github::Repos.new.list user: '...', auto_pagination: true # affects a single request
|
516
|
-
```
|
517
|
-
|
518
522
|
One can also navigate straight to the specific page by:
|
519
523
|
|
520
524
|
```ruby
|
@@ -526,31 +530,27 @@ res.prev_page # Get previous page
|
|
526
530
|
res.last_page # Get last page
|
527
531
|
```
|
528
532
|
|
529
|
-
|
533
|
+
### 4.1 Auto pagination
|
530
534
|
|
531
|
-
|
535
|
+
You can retrieve all pages in one invocation by passing the `auto_pagination` option like so:
|
532
536
|
|
533
|
-
|
537
|
+
```ruby
|
538
|
+
github = Github.new auto_pagination: true
|
539
|
+
```
|
534
540
|
|
535
|
-
|
536
|
-
|
537
|
-
You can now configure cache parameters as follows
|
541
|
+
Depending at what stage you pass the `auto_pagination` it will affect all or only a single request. For example, in order to auto paginate all Repository API methods do:
|
538
542
|
|
539
543
|
```ruby
|
540
|
-
Github.
|
541
|
-
config.stack do |builder|
|
542
|
-
builder.use Faraday::HttpCache, store: Rails.cache
|
543
|
-
end
|
544
|
-
end
|
544
|
+
Github::Repos.new auto_pagination: true
|
545
545
|
```
|
546
546
|
|
547
|
-
|
547
|
+
However, to only auto paginate results for a single request do:
|
548
548
|
|
549
|
-
|
550
|
-
|
551
|
-
|
549
|
+
```ruby
|
550
|
+
Github::Repos.new.list user: '...', auto_pagination: true
|
551
|
+
```
|
552
552
|
|
553
|
-
##
|
553
|
+
## 5 Error Handling
|
554
554
|
|
555
555
|
The generic error class `Github::Error::GithubError` will handle both the client (`Github::Error::ClientError`) and service (`Github::Error::ServiceError`) side errors. For instance in your code you can catch errors like
|
556
556
|
|
@@ -568,77 +568,83 @@ rescue Github::Error::GithubError => e
|
|
568
568
|
end
|
569
569
|
```
|
570
570
|
|
571
|
-
##
|
571
|
+
## 6 Examples
|
572
572
|
|
573
|
-
|
573
|
+
### 6.1 Rails
|
574
|
+
|
575
|
+
A Rails controller that allows a user to authorize their GitHub account and then performs a request.
|
574
576
|
|
575
577
|
```ruby
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
578
|
+
class GithubController < ApplicationController
|
579
|
+
|
580
|
+
attr_accessor :github
|
581
|
+
private :github
|
582
|
+
|
583
|
+
def authorize
|
584
|
+
github = Github.new client_id: '...', client_secret: '...'
|
585
|
+
address = github.authorize_url redirect_uri: 'http://...', scope: 'repo'
|
586
|
+
redirect_to address
|
587
|
+
end
|
588
|
+
|
589
|
+
def callback
|
590
|
+
authorization_code = params[:code]
|
591
|
+
access_token = github.get_token authorization_code
|
592
|
+
access_token.token # => returns token value
|
593
|
+
end
|
594
|
+
end
|
583
595
|
```
|
584
596
|
|
585
|
-
|
597
|
+
### 6.2 Manipulating Files
|
586
598
|
|
587
|
-
|
599
|
+
In order to be able to create/update/remove files you need to use Contents API like so:
|
588
600
|
|
589
601
|
```ruby
|
590
|
-
|
591
|
-
issues.milestones.list state: 'open', sort: 'due_date', direction: 'asc'
|
602
|
+
contents = Github::Client::Repos::Contents.new oauth_token: '...'
|
592
603
|
```
|
593
604
|
|
594
|
-
|
605
|
+
Having instantiaed the contents, to create a file do:
|
595
606
|
|
596
607
|
```ruby
|
597
|
-
|
598
|
-
|
608
|
+
contents.create 'username', 'repo_name', 'full_path_to/file.ext',
|
609
|
+
path: 'full_path_to/file.ext',
|
610
|
+
message: 'Your commit message',
|
611
|
+
content: 'The contents of your file'
|
599
612
|
```
|
600
613
|
|
601
|
-
|
614
|
+
Content is all Base64 encoded to/from the API, and when you create a file it encodes it automatically for you.
|
615
|
+
|
616
|
+
To update a file, first you need to find the file so you can get the SHA you're updating off of:
|
602
617
|
|
603
618
|
```ruby
|
604
|
-
|
605
|
-
events.public do |event|
|
606
|
-
puts event.actor.login
|
607
|
-
end
|
619
|
+
file = contents.find path: 'full_path_to/file.ext'
|
608
620
|
```
|
609
621
|
|
610
|
-
|
622
|
+
Then update the file just like you do with creating:
|
611
623
|
|
612
624
|
```ruby
|
613
|
-
|
614
|
-
|
625
|
+
contents.update 'username', 'repo_name', 'full_path_to/file.ext',
|
626
|
+
path: 'full_path_to/file.ext'
|
627
|
+
message: 'Your commit message',
|
628
|
+
content: 'The contens to be updated',
|
629
|
+
sha: file.sha
|
615
630
|
```
|
616
631
|
|
617
|
-
|
618
|
-
|
619
|
-
A Rails controller that allows a user to authorize their GitHub account and then performs a request.
|
632
|
+
Finally to remove a file, find the file so you can get the SHA you're removing:
|
620
633
|
|
621
634
|
```ruby
|
622
|
-
|
635
|
+
file = contents.find path: 'full_path_to/file.ext'
|
636
|
+
```
|
623
637
|
|
624
|
-
|
625
|
-
private :github
|
638
|
+
Then delete the file like so:
|
626
639
|
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
def callback
|
634
|
-
authorization_code = params[:code]
|
635
|
-
access_token = github.get_token authorization_code
|
636
|
-
access_token.token # => returns token value
|
637
|
-
end
|
638
|
-
end
|
640
|
+
```ruby
|
641
|
+
github.delete 'username', 'tome-of-knowledge', 'full_path_to/file.ext',
|
642
|
+
path: 'full_path_to/file.ext',
|
643
|
+
message: 'Your Commit Message',
|
644
|
+
sha: file.sha
|
639
645
|
```
|
640
646
|
|
641
|
-
##
|
647
|
+
## 7 Testing
|
642
648
|
|
643
649
|
The test suite is split into two groups, `live` and `mock`.
|
644
650
|
|