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 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. [usage](#1-usage)
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
- * Supports OAuth2 authorization. [oauth](#42-application-oauth-access)
29
- * Flexible argument parsing. You can write expressive and natural queries. [params](#2-arguments--parameters)
30
- * Requests pagination with convenient DSL and automatic options. [pagination](#10-pagination)
31
- * Easy error handling split for client and server type errors. [error](#13-error-handling)
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. [media](#7-media-types)
34
- * Request results caching (Status: TODO)
35
- * Fully tested with test coverage above 90% with over 1,700 specs and 1200 feature tests. [testing](#16-testing)
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
- * [2. Arguments & Parameters](#2-arguments--parameters)
55
- * [3. Advanced Configuration](#3-advanced-configuration)
56
- * [4. Authentication](#4-authentication)
57
- * [5. SSL](#5-ssl)
58
- * [6. API](#6-api)
59
- * [7. Media Types](#7-media-types)
60
- * [8. Hypermeida](#8-hypermedia)
61
- * [9. Configuration](#9-configurations)
62
- * [10. Pagination](#10-pagination)
63
- * [11. Caching](#11-caching)
64
- * [12. Debugging](#12-debugging)
65
- * [13. Error Handling](#13-error-handling)
66
- * [14. Response Message](#14-response-message)
67
- * [15. Examples](#15-examples)
68
- * [16. Testing](#16-testing)
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 direct calls on `Github`
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: 'wycats'
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
- ### 1.1 Options
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 = Github.new oauth_token: 'token'
98
+ github.repos.list user: 'peter-murach'
107
99
  ```
108
100
 
109
- Alternatively, you can configure the GitHub settings by passing a block, for instance, for a custom enterprise endpoint and website like
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 do |config|
113
- config.endpoint = 'https://github.company.com/api/v3'
114
- config.site = 'https://github.company.com'
115
- config.oauth_token = 'token'
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
- You can authenticate either using OAuth authentication convenience methods (see OAuth section) or through basic authentication by passing your login and password credentials
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 = Github.new login:'peter-murach', password:'...'
115
+ github.repos.releases.list 'peter-murach', 'finite_machine'
125
116
  ```
126
117
 
127
- or using a convenience method:
118
+ or to list a user's followers:
128
119
 
129
120
  ```ruby
130
- github = Github.new basic_auth: 'login:password'
121
+ github.users.followers.list 'peter-murach'
131
122
  ```
132
123
 
133
- ### 1.2 API navigation
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
- This gem closely mirrors the GitHub API hierarchy i.e. if you want to create a download resource,
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
- github.repos.commits.all 'user-name', 'repo-name'
142
- github.repos.hooks.create 'user-name', 'repo-name', name: "web", active: true
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.3 Modularity
133
+ ### 1.2 Modularity
147
134
 
148
- The code base is modular and allows for you to work specifically with a given part of GitHub API e.g. blobs
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
- blobs = Github::GitData::Blobs.new
152
- blobs.create 'peter-murach', 'github', content: 'Blob content'
138
+ starring = Github::Client::Activity::Starring.new
139
+ starring.star 'peter-murach', 'github'
153
140
  ```
154
141
 
155
- ### 1.4 Response querying
156
- The response is of type [Github::ResponseWrapper] which allows traversing all the json response attributes like method calls i.e.
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
- repos = Github::Repos.new user: 'peter-murach', repo: 'github'
160
- repos.branches do |branch|
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
- ## 2 Arguments & Parameters
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
- issues = Github::Issues.new user: 'peter-murach', repo: 'github'
171
- issues.milestones.list state: 'open'
158
+ issues = Github::Client::Issues.new
159
+ issues.milestones.list user: 'peter-murach', repo: 'github', state: 'open'
172
160
  ```
173
161
 
174
- Further, arguments can be passed directly inside the method called, but then the order of parameters matters and hence please consult the method documentation or GitHub specification. For instance:
162
+ Furthermore, `required` arguments can be passed during instance creation:
175
163
 
176
164
  ```ruby
177
- issues = Github::Issues.new
178
- issues.milestones.list 'peter-murach', 'github', state: 'open'
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
- issues = Github::Issues.new
185
- issues.milestones(user: 'peter-murach', repo: 'github').list
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
- issues = Github::Issues.new user: 'peter-murach'
192
- issues.milestones(repo: 'github').list
193
- issues.milestones(repo: 'tty').list
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 common among Ruby libraries whereby "username/repository" can be passed as well:
184
+ You can also use a bit of syntactic sugar whereby "username/repository" can be passed as well:
197
185
 
198
186
  ```ruby
199
- issues = Github::Issues.new
200
- issues.milestones('peter-murach/github').list
201
- issues.milestones.list 'peter-murach/github'
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
- issues = Github::Issues.new
208
- issues.milestones.with(user: 'peter-murach', repo: 'github').list
195
+ issues = Github::Client::Issues.new
196
+ issues.milestones.with(user: 'peter-murach', repo: 'github').list
209
197
  ```
210
198
 
211
- Some API methods apart from required parameters such as username, repository name
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
- ```ruby
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
- github.git_data.trees.get 'peter-murach', 'github', 'c18647b75d72f19c1e0cc8af031e5d833b7f12ea',
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
- by passing a block you can iterate over the file tree
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
- github.git_data.trees.get 'peter-murach', 'github', 'c18647b75d72f19c1e0cc8af031e5d833b7f12ea',
227
- recursive: true do |file|
228
- puts file.path
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
- ## 3 Advanced Configuration
214
+ #### 1.4.1 Response Body
233
215
 
234
- The `github_api` gem 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
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
- github = Github.new do |config|
238
- config.stack.insert_after Github::Response::Helpers, CustomMiddleware
239
- end
219
+ response = repos.branches user: 'peter-murach', repo: 'github'
220
+ response.body # => Array of branches
240
221
  ```
241
222
 
242
- Furthermore, you can build your entire custom stack and specify other connection options such as `adapter`
223
+ #### 1.4.2 Response Headers
243
224
 
244
- ```ruby
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
- config.stack do |builder|
249
- builder.use Github::Response::Helpers
250
- builder.use Github::Response::Jsonize
251
- end
252
- end
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
- ## 4 Authentication
237
+ #### 1.4.3 Response Success
256
238
 
257
- ### 4.1 Basic
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.new basic_auth: 'login:password'
242
+ response = Github::Client::Repos.branches 'peter-murach', 'github'
243
+ response.success? # => true
263
244
  ```
264
245
 
265
- Though this method is convenient you should strongly consider using `OAuth` for improved security reasons.
246
+ ### 1.5 Request Headers
266
247
 
267
- ### 4.2 Application OAuth access
248
+ It is possible to specify additional header information which will be added to the final request.
268
249
 
269
- In order to authenticate your app through OAuth2 on GitHub you need to
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
- github = Github.new client_id: '...', client_secret: '...'
280
- github.authorize_url redirect_uri: 'http://localhost', scope: 'repo'
281
- # => "https://github.com/login/oauth/authorize?scope=repo&response_type=code&client_id='...'&redirect_uri=http%3A%2F%2Flocalhost"
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
- After you get your authorization code, call to receive your access_token
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
- token = github.get_token( authorization_code )
267
+ issues = Github::Client::Issues.new
268
+ issues.get 'peter-murach', 'github', 108, accept: 'application/vnd.github.raw'
287
269
  ```
288
270
 
289
- Once you have your access token, configure your github instance following instructions under Configuration.
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
- ### 4.3 Authorizations API
273
+ The **github_api** provides ability to specify global configuration options. These options will be available to all api calls.
294
274
 
295
- #### 4.3.1 For an User
275
+ ### 2.1 Basic
296
276
 
297
- 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.
277
+ The configuration options can be set by using the `configure` helper
298
278
 
299
279
  ```ruby
300
- github = Github.new basic_auth: 'login:password'
301
- github.oauth.create scopes: ['repo']
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
- 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).
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
- github = Github.new basic_auth: 'login:password'
312
- github.oauth.app.create 'client-id', scopes: ['repo']
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
- 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.
297
+ or simply by passing hash of options to an instance like so
316
298
 
317
299
  ```ruby
318
- github = Github.new basic_auth: "client_id:client_secret"
319
- github.oauth.app.delete 'client-id'
300
+ github = Github.new basic_auth: 'login:password',
301
+ adapter: :typheous,
302
+ user: 'peter-murach',
303
+ repo: 'finite_machine'
320
304
  ```
321
305
 
322
- Revoke a specific app token.
306
+ The following is the full list of available configuration options:
323
307
 
324
308
  ```ruby
325
- github.oauth.app.delete 'client-id', 'access-token'
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
- ### 4.4 Scopes
326
+ ### 2.2 Advanced
329
327
 
330
- You can check OAuth scopes you have by:
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
- github = Github.new :oauth_token => 'token'
334
- github.scopes.list # => ['repo']
331
+ Github.configure do |c|
332
+ c.stack.insert_after Github::Response::Helpers, CustomMiddleware
333
+ end
335
334
  ```
336
335
 
337
- To list the scopes that the particular GitHub API action checks for do:
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
- repos = Github::Repos.new
341
- res = repos.list :user => 'peter-murach'
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
- To understand what each scope means refer to [documentation](http://developer.github.com/v3/oauth/#scopes)
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
- ## 5 SSL
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
- Github.new ssl: { verify: false }
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
- ssl: {
359
- client_cert: "/usr/local/www.example.com/client_cert.pem"
360
- client_key: "/user/local/www.example.com/client_key.pem"
361
- ca_file: "example.com.cert"
362
- ca_path: "/etc/ssl/"
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
- ## 6 API
370
+ ### 2.4 Caching
370
371
 
371
- Main API methods are grouped into the following classes that can be instantiated on their own
372
+ Caching is supported through the [`faraday-http-cache` gem](https://github.com/plataformatec/faraday-http-cache).
372
373
 
373
- ```ruby
374
- Github - full API access
374
+ Add the gem to your Gemfile:
375
375
 
376
- Github::Gists Github::GitData Github::Repos Github::Search
377
- Github::Orgs Github::Issues Github::Authorizations
378
- Github::PullRequests Github::Users Github::Activity
376
+ ```ruby
377
+ gem 'faraday-http-cache'
379
378
  ```
380
379
 
381
- Some parts of GitHub API v3 require you to be authenticated, for instance the following are examples of APIs only for the authenticated user
380
+ You can now configure cache parameters as follows
382
381
 
383
382
  ```ruby
384
- Github::Users::Emails
385
- Github::Users::Keys
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
- All method calls form Ruby like sentences and allow for intuitive API navigation, for instance
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
- github = Github.new :oauth_token => '...'
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
- For specifications on all available methods, go to http://developer.github.com/v3/ or
397
- read the rdoc. All methods are documented there with examples of usage.
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
- Alternatively, you can find out which methods are supported by calling `actions` on a class instance in your `irb`:
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
- >> Github::Repos.actions >> github.issues.actions
403
- --- ---
404
- |--> all |--> all
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
- ## 7 Media Types
422
+ ```ruby
423
+ token = github.get_token( authorization_code )
424
+ ```
421
425
 
422
- You can specify custom media types to choose the format of the data you wish to receive. To make things easier you can specify the following shortcuts
423
- `json`, `blob`, `raw`, `text`, `html`, `full`. For instance:
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.issues.get 'peter-murach', 'github', 108, media: 'text'
437
+ github = Github.new basic_auth: 'login:password'
438
+ github.oauth.create scopes: ['repo']
428
439
  ```
429
440
 
430
- This will be expanded into `application/vnd.github.v3.text+json`
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
- If you wish to specify the version, pass `media: 'beta.text'` which will be converted to `application/vnd/github.beta.text+json`.
443
+ #### 3.3.2 For an App
433
444
 
434
- Finally, you can always pass the whole accept header like so
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.issues.get 'peter-murach', 'github', 108, accept: 'application/vnd.github.raw'
448
+ github = Github.new basic_auth: 'login:password'
449
+ github.oauth.app.create 'client-id', scopes: ['repo']
438
450
  ```
439
451
 
440
- ## 8 Hypermedia
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
- ## 9 Configuration
454
+ ```ruby
455
+ github = Github.new basic_auth: "client_id:client_secret"
456
+ github.oauth.app.delete 'client-id'
457
+ ```
445
458
 
446
- Certain methods require authentication. To get your GitHub OAuth v2 credentials,
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
- Github.configure do |config|
452
- config.oauth_token = YOUR_OAUTH_ACCESS_TOKEN
453
- config.basic_auth = 'login:password'
454
- end
462
+ github.oauth.app.delete 'client-id', 'access-token'
463
+ ```
455
464
 
456
- or
465
+ ### 3.4 Scopes
457
466
 
458
- Github.new(:oauth_token => YOUR_OAUTH_TOKEN)
459
- Github.new(:basic_auth => 'login:password')
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
- All parameters can be overwritten each method call by passing a parameters hash.
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
- ## 10 Pagination
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 = Github::Repos.new
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
- res.links.first # Shows the URL of the first page of results.
480
- res.links.next # Shows the URL of the immediate next page of results.
481
- res.links.prev # Shows the URL of the immediate previous page of results.
482
- res.links.last # Shows the URL of the last page of results.
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
- res.each_page do |page|
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 res.has_next_page?
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
- ## 11 Caching
533
+ ### 4.1 Auto pagination
530
534
 
531
- Caching is supported through the [`faraday-http-cache` gem](https://github.com/plataformatec/faraday-http-cache).
535
+ You can retrieve all pages in one invocation by passing the `auto_pagination` option like so:
532
536
 
533
- Add the gem to your Gemfile:
537
+ ```ruby
538
+ github = Github.new auto_pagination: true
539
+ ```
534
540
 
535
- gem 'faraday-http-cache'
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.configure do |config|
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
- 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
547
+ However, to only auto paginate results for a single request do:
548
548
 
549
- ## 12 Debugging
550
-
551
- run with ENV['DEBUG'] flag or include middleware by passing `debug` flag
549
+ ```ruby
550
+ Github::Repos.new.list user: '...', auto_pagination: true
551
+ ```
552
552
 
553
- ## 13 Error Handling
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
- ## 14 Response Message
571
+ ## 6 Examples
572
572
 
573
- 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, call
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
- res = Github::Repos.new.branches 'peter-murach', 'github'
577
- res.headers.ratelimit_limit # "5000"
578
- res.headers.ratelimit_remaining # "4999"
579
- res.headers.status # "200"
580
- res.headers.content_type # "application/json; charset=utf-8"
581
- res.headers.etag # "\"2c5dfc54b3fe498779ef3a9ada9a0af9\""
582
- res.headers.cache_control # "public, max-age=60, s-maxage=60"
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
- ## 15 Examples
597
+ ### 6.2 Manipulating Files
586
598
 
587
- Some API methods require input parameters. These are simply added as a hash of properties, for instance
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
- issues = Github::Issues.new user:'peter-murach', repo: 'github-api'
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
- Other methods may require inputs as an array of strings
605
+ Having instantiaed the contents, to create a file do:
595
606
 
596
607
  ```ruby
597
- users = Github::Users.new oauth_token: 'token'
598
- users.emails.add 'email1', 'email2', ..., 'emailn' # => Adds emails to the authenticated user
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
- If a method returns a collection, you can iterate over it by supplying a block parameter,
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
- events = Github::Activity::Events.new
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
- Query requests return boolean values instead of HTTP responses
622
+ Then update the file just like you do with creating:
611
623
 
612
624
  ```ruby
613
- github = Github.new
614
- github.orgs.members.member? 'github', 'technoweenie', public: true # => true
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
- ### 15.1 Rails Example
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
- class GithubController < ApplicationController
635
+ file = contents.find path: 'full_path_to/file.ext'
636
+ ```
623
637
 
624
- attr_accessor :github
625
- private :github
638
+ Then delete the file like so:
626
639
 
627
- def authorize
628
- github = Github.new client_id: '...', client_secret: '...'
629
- address = github.authorize_url redirect_uri: 'http://...', scope: 'repo'
630
- redirect_to address
631
- end
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
- ## 16 Testing
647
+ ## 7 Testing
642
648
 
643
649
  The test suite is split into two groups, `live` and `mock`.
644
650