octokit 2.0.0.rc4 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/CONTRIBUTING.md CHANGED
@@ -1,4 +1,7 @@
1
1
  ## Submitting a Pull Request
2
+
3
+ 0. Check out Hacking on Octokit in the README guide for
4
+ bootstrapping the project for local development.
2
5
  1. [Fork the repository.][fork]
3
6
  2. [Create a topic branch.][branch]
4
7
  3. Add specs for your unimplemented feature or bug fix.
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011-2013 Wynn Netherland, Adam Stacoviak, Erik Michaels-Ober
1
+ Copyright (c) 2009-2013 Wynn Netherland, Adam Stacoviak, Erik Michaels-Ober
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,100 +1,426 @@
1
1
  # Octokit
2
2
 
3
- Simple Ruby wrapper for the GitHub API.
3
+ Ruby toolkit for the GitHub API.
4
4
 
5
- ## Installation
5
+ ![Logo][logo]
6
+ [logo]: http://cl.ly/image/3Y013H0A2z3z/gundam-ruby.png
7
+
8
+ Octokit 2.0 is out, check the [Upgrade Guide](#upgrading-guide) before
9
+ upgrading from 1.x.
10
+
11
+ ## Philosophy
12
+
13
+ API wrappers [should reflect the idioms of the language in which they were
14
+ written][wrappers]. Octokit.rb wraps the [GitHub API][github-api] in a flat API
15
+ client that follows Ruby conventions and requires little knowledge of REST.
16
+ Most methods have positional arguments for required input and an options hash
17
+ for optional parameters, headers, or other options:
18
+
19
+ ```ruby
20
+ # Fetch a README with Accept header for HTML format
21
+ Octokit.readme 'al3x/sovereign', :accept => 'application/vnd.github.html'
22
+ ```
23
+
24
+
25
+ [wrappers]: http://wynnnetherland.com/journal/what-makes-a-good-api-wrapper
26
+ [github-api]: http://developer.github.com
27
+
28
+ ## Quick start
29
+
30
+ Install via Rubygems
6
31
 
7
32
  gem install octokit
8
33
 
9
- ## Documentation
34
+ ... or add to your Gemfile
10
35
 
11
- [http://rdoc.info/gems/octokit][documentation]
36
+ gem "octokit", "~> 2.0"
12
37
 
13
- [documentation]: http://rdoc.info/gems/octokit
38
+ ### Making requests
14
39
 
15
- ### Examples
40
+ API methods are available as module methods (consuming module-level
41
+ configuration) or as client instance methods.
42
+
43
+ ```ruby
44
+ # Provide authentication credentials
45
+ Octokit.configure do |c|
46
+ c.login 'defunkt'
47
+ c.password 'c0d3b4ssssss!'
48
+ end
16
49
 
17
- #### Show a user
50
+ # Fetch the current user
51
+ Octokit.user
52
+ ```
53
+ or
18
54
 
19
55
  ```ruby
20
- Octokit.user "sferik"
21
- => #<Hashie::Mash avatar_url="https://secure.gravatar.com/avatar/1f74b13f1e5c6c69cb5d7fbaabb1e2cb?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png" bio="" blog="http://twitter.com/sferik" company="" created_at="2008-05-14T20:36:12Z" email="sferik@gmail.com" events_url="https://api.github.com/users/sferik/events{/privacy}" followers=662 followers_url="https://api.github.com/users/sferik/followers" following=102 following_url="https://api.github.com/users/sferik/following{/other_user}" gists_url="https://api.github.com/users/sferik/gists{/gist_id}" gravatar_id="1f74b13f1e5c6c69cb5d7fbaabb1e2cb" hireable=false html_url="https://github.com/sferik" id=10308 location="San Francisco, CA" login="sferik" name="Erik Michaels-Ober" organizations_url="https://api.github.com/users/sferik/orgs" public_gists=59 public_repos=83 received_events_url="https://api.github.com/users/sferik/received_events" repos_url="https://api.github.com/users/sferik/repos" starred_url="https://api.github.com/users/sferik/starred{/owner}{/repo}" subscriptions_url="https://api.github.com/users/sferik/subscriptions" type="User" updated_at="2013-05-31T16:01:08Z" url="https://api.github.com/users/sferik">
56
+ # Provide authentication credentials
57
+ client = Octokit::Client.new :login => 'defunkt', :password => 'c0d3b4ssssss!'
58
+ # Fetch the current user
59
+ client.user
22
60
  ```
23
61
 
24
- #### Repositories
62
+ ### Consuming resources
25
63
 
26
- For convenience, methods that require a repository argument may be passed in
27
- any of the following forms:
64
+ Most methods return a `Resource` object which provides dot notation and `[]`
65
+ access for fields returned in the API response.
28
66
 
29
67
  ```ruby
30
- Octokit.repo "octokit/octokit.rb"
68
+ # Fetch a user
69
+ user = Octokit.user 'jbarnette'
70
+ puts user.name
71
+ # => "John Barnette"
72
+ puts user.fields
73
+ # => <Set: {:login, :id, :gravatar_id, :type, :name, :company, :blog, :location, :email, :hireable, :bio, :public_repos, :followers, :following, :created_at, :updated_at, :public_gists}>
74
+ puts user[:company]
75
+ # => "GitHub"
76
+ user.rels[:gists].href
77
+ # => "https://api.github.com/users/jbarnette/gists"
78
+ ```
31
79
 
32
- Octokit.repo {:username => "octokit", :name => "octokit.rb"}
80
+ **Note:** URL fields are culled into a separate `.rels` collection for easier
81
+ [Hypermedia](#hypermedia-agent) support.
33
82
 
34
- Octokit.repo {:username => "octokit", :repo => "octokit.rb"}
83
+ ### Accessing HTTP responses
35
84
 
36
- Octokit.repo Repository.new('octokit/octokit.rb')
85
+ While most methods return a `Resource` object or a Boolean, sometimes you may
86
+ need access to the raw HTTP response headers. You can access the last HTTP
87
+ response with `Client#last_response`:
88
+
89
+ ```ruby
90
+ user = Octokit.user 'andrewpthorp'
91
+ response = Octokit.last_response
92
+ etag = response.headers[:etag]
37
93
  ```
38
94
 
39
- #### List the commits for a repository
95
+ ## Authentication
40
96
 
41
- ```ruby
42
- Octokit.commits("octokit/octokit.rb")
97
+ Octokit supports the various [authentication methods supported by the GitHub
98
+ API][auth]:
99
+
100
+ ### Basic Authentication
43
101
 
44
- Octokit.list_commits("octokit/octokit.rb")
102
+ Using your GitHub username and password is the easiest way to get started
103
+ making authenticated requests:
45
104
 
46
- => [#<Hashie::Mash author=#<Hashie::Mash avatar_url="https://secure.gravatar.com/avatar/7e19cd5486b5d6dc1ef90e671ba52ae0?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png" gravatar_id="7e19cd5486b5d6dc1ef90e671ba52ae0" id=865 login="pengwynn" url="https://api.github.com/users/pengwynn"> commit=#<Hashie::Mash author=#<Hashie::Mash date="2012-10-31T15:17:51Z" email="wynn@github.com" name="Wynn Netherland"> comment_count=0 committer=#<Hashie::Mash date="2012-10-31T15:17:51Z" email="wynn@github.com" name="Wynn Netherland"> message="Fix bug with archive_link for private repo" tree=#<Hashie::Mash sha="49bf2a476aa819f29b0fc1a8805f7567f010006d" url="https://api.github.com/repos/octokit/octokit.rb/git/trees/49bf2a476aa819f29b0fc1a8805f7567f010006d"> url="https://api.github.com/repos/octokit/octokit.rb/git/commits/8db3df37fad3a021eb8036b007c718149836cb32"> committer=#<Hashie::Mash avatar_url="https://secure.gravatar.com/avatar/7e19cd5486b5d6dc1ef90e671ba52ae0?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png" gravatar_id="7e19cd5486b5d6dc1ef90e671ba52ae0" id=865 login="pengwynn" url="https://api.github.com/users/pengwynn"> parents=[#<Hashie::Mash sha="7a67f4b47791cb77de33e491df87cef06012c79f" url="https://api.github.com/repos/octokit/octokit.rb/commits/7a67f4b47791cb77de33e491df87cef06012c79f">] sha="8db3df37fad3a021eb8036b007c718149836cb32" url="https://api.github.com/repos/octokit/octokit.rb/commits/8db3df37fad3a021eb8036b007c718149836cb32">, ... , ...]
105
+ ```ruby
106
+ client = Octokit::Client.new \
107
+ :login => 'defunkt',
108
+ :password => 'c0d3b4ssssss!'
109
+
110
+ user = client.user
111
+ user.login
112
+ # => "defunkt"
47
113
  ```
114
+ While Basic Authentication makes it easy to get started quickly, OAuth access
115
+ tokens are the preferred way to authenticate on behalf of users.
116
+
117
+ ### OAuth access tokens
118
+
119
+ [OAuth access tokens][oauth] provide two main benefits over using your username
120
+ and password:
48
121
 
49
- #### Authenticated Requests
50
- For methods that require authentication, you'll need to setup a client with
51
- your login and password.
122
+ * **Revokable access**. Access tokens can be revoked, removing access for just
123
+ that token without having to change your password everywhere.
124
+ * **Limited access**. Access tokens have [access scopes][] which allow for more
125
+ granular access to API resources. For instance, you can grant a third party
126
+ access to your gists but not your private repositories.
127
+
128
+ To use an access token with the Octokit client, just pass it in lieu of your
129
+ username and password:
52
130
 
53
131
  ```ruby
54
- client = Octokit::Client.new(:login => "me", :password => "sekret")
55
- client.follow("sferik")
132
+ client = Octokit::Client.new :access_token => "<your 40 char token>"
133
+
134
+ user = client.user
135
+ user.login
136
+ # => "defunkt"
56
137
  ```
57
138
 
58
- Alternately, you can authenticate with a [GitHub OAuth2 token][oauth].
139
+ You can use `.create_authorization` to create a token using Basic Authorization
140
+ that you can use for subsequent calls.
59
141
 
60
- [oauth]: http://developer.github.com/v3/oauth
142
+ ### Using a .netrc file
143
+
144
+ Octokit supports reading credentials from a netrc file (defaulting to
145
+ `~/.netrc`). Given these lines in your netrc:
146
+
147
+ ```
148
+ machine api.github.com
149
+ login defunkt
150
+ password c0d3b4ssssss!
151
+ ```
152
+ You can now create a client with those credentials:
61
153
 
62
154
  ```ruby
63
- client = Octokit::Client.new(:login => "me", :oauth_token => "oauth2token")
64
- client.follow("sferik")
155
+ client = Octokit::Client.new :netrc => true
156
+ client.login
157
+ # => "defunkt"
158
+ ```
159
+ But _I want to use OAuth_ you say. Since the GitHub API supports using an OAuth
160
+ token as a Basic password, you totally can:
161
+
162
+ ```
163
+ machine api.github.com
164
+ login defunkt
165
+ password <your 40 char token>
65
166
  ```
66
167
 
67
- #### Requesting a specific media type
168
+ **Note:** Support for netrc requires adding the [netrc gem][] to your Gemfile
169
+ or `.gemspec`.
68
170
 
69
- You can pass an `:accept` option value to request a particular [media
70
- type][media-types].
171
+ ### Application authentication
71
172
 
72
- [media-types]: http://developer.github.com/v3/media/
173
+ Octokit also supports application-only authentication [using OAuth application client
174
+ credentials][app-creds]. Using application credentials will result in making
175
+ anonymous API calls on behalf of an application in order to take advantage of
176
+ the higher rate limit.
73
177
 
74
178
  ```ruby
75
- Octokit.contents 'octokit/octokit.rb', :path => 'README.md', :accept => 'application/vnd.github.html'
179
+ client = Octokit::Client.new \
180
+ :client_id => "<your 20 char id>",
181
+ :client_secret => "<your 40 char secret>"
182
+
183
+ user = client.users 'defunkt'
76
184
  ```
77
185
 
78
- ### Using with GitHub Enterprise
79
186
 
80
- To use with [GitHub Enterprise](https://enterprise.github.com/), you'll need to
81
- set the API and web endpoints before instantiating a client.
187
+
188
+ [auth]: http://developer.github.com/v3/#authentication
189
+ [oauth]: http://developer.github.com/v3/oauth/
190
+ [access scopes]: http://developer.github.com/v3/oauth/#scopes
191
+ [app-creds]: http://developer.github.com/v3/#unauthenticated-rate-limited-requests
192
+
193
+
194
+ ## Configuration and defaults
195
+
196
+ While `Octokit::Client` accepts a range of options when creating a new client
197
+ instance, Octokit's configuration API allows you to set your configuration
198
+ options at the module level. This is particularly handy if you're creating a
199
+ number of client instances based on some shared defaults.
200
+
201
+ ### Configuring module defaults
202
+
203
+ Every writable attribute in {Octokit::Configurable} can be set one at a time:
204
+
205
+ ```ruby
206
+ Octokit.api_endpoint = 'http://api.github.dev'
207
+ Octokit.web_endpoint = 'http://github.dev'
208
+ ```
209
+
210
+ or in batch:
82
211
 
83
212
  ```ruby
84
213
  Octokit.configure do |c|
85
- c.api_endpoint = 'https://github.company.com/api/v3'
86
- c.web_endpoint = 'https://github.company.com/'
214
+ c.api_endpoint = 'http://api.github.dev'
215
+ c.web_endpoint = 'http://github.dev'
87
216
  end
217
+ ```
218
+
219
+ ### Using ENV variables
220
+
221
+ Default configuration values are specified in {Octokit::Default}. Many
222
+ attributes will look for a default value from the ENV before returning
223
+ Octokit's default.
88
224
 
89
- @client = Octokit::Client.new(:login => 'USERNAME', :password => 'PASSWORD')
225
+ ```ruby
226
+ # Given $OCTOKIT_API_ENDPOINT is "http://api.github.dev"
227
+ Octokit.api_endpoint
228
+
229
+ # => "http://api.github.dev"
90
230
  ```
91
231
 
232
+ ## Hypermedia agent
233
+
234
+ Starting in version 2.0, Octokit is [hypermedia][]-enabled. Under the hood,
235
+ {Octokit::Client} uses [Sawyer][], a hypermedia client built on [Faraday][].
236
+
237
+ ### Hypermedia in Octokit
238
+
239
+ Resources returned by Octokit methods contain not only data but hypermedia
240
+ link relations:
241
+
242
+ ```ruby
243
+ user = Octokit.user 'technoweenie'
244
+
245
+ # Get the repos rel, returned from the API
246
+ # as repos_url in the resource
247
+ user.rels[:repos].href
248
+ # => "https://api.github.com/users/technoweenie/repos"
249
+
250
+ repos = user.rels[:repos].get.data
251
+ repos.last.name
252
+ # => "faraday-zeromq"
253
+ ```
254
+
255
+ When processing API responses, all `*_url` attributes are culled in to the link
256
+ relations collection. Any `url` attribute becomes `.rels[:self]`.
257
+
258
+ ### URI templates
259
+
260
+ You might notice many link relations have variable placeholders. Octokit
261
+ supports [URI Templates][uri-templates] for parameterized URI expansion:
262
+
263
+ ```ruby
264
+ repo = Octokit.repo 'pengwynn/pingwynn'
265
+ rel = repo.rels[:issues]
266
+ # => #<Sawyer::Relation: issues: get https://api.github.com/repos/pengwynn/pingwynn/issues{/number}>
267
+
268
+ # Get a page of issues
269
+ repo.rels[:issues].get.data
270
+
271
+ # Get issue #2
272
+ repo.rels[:issues].get(:uri => {:number => 2}).data
273
+ ```
274
+
275
+ ### The Full Hypermedia Experience™
276
+
277
+ If you want to use Octokit as a pure hypermedia API client, you can start at
278
+ the API root and and follow link relations from there:
279
+
280
+ ```ruby
281
+ root = Octokit.root
282
+ root.rels[:repository].get :uri => {:owner => "octokit", :repo => "octokit.rb" }
283
+ ```
284
+
285
+ Octokit 3.0 aims to be hypermedia-driven, removing the internal URL
286
+ construction currently used throughout the client.
287
+
288
+ [hypermedia]: http://en.wikipedia.org/wiki/Hypermedia
289
+ [Sawyer]: https://github.com/lostisland/sawyer
290
+ [Faraday]: https://github.com/lostisland/faraday
291
+ [uri-templates]: http://tools.ietf.org/html/rfc6570
292
+
293
+ ## Upgrading guide
294
+
295
+ Version 2.0 includes a completely rewritten `Client` factory that now memoizes
296
+ client instances based on unique configuration options. Breaking changes also
297
+ include:
298
+
299
+ * `:oauth_token` is now `:access_token`
300
+ * `Hashie::Mash` has been removed. Responses now return a `Sawyer::Resource`
301
+ object. This new type behaves mostly like a Ruby `Hash`, but does not fully
302
+ support the `Hashie::Mash` API.
303
+ * Two new client error types are raised where appropriate:
304
+ `Octokit::TooManyRequests` and `Octokit::TooManyLoginAttempts`
305
+ * The `search_*` methods from v1.x are now found at `legacy_search_*`
306
+ * Support for netrc requires including the [netrc gem][] in your Gemfile or
307
+ gemspec.
308
+
309
+ [netrc gem]: https://rubygems.org/gems/netrc
310
+
311
+
312
+ ## Advanced usage
313
+
314
+ Since Octokit employs [Faraday][faraday] under the hood, some behavior can be
315
+ extended via middleware.
316
+
317
+ ### Debugging
318
+
319
+ Often, it helps to know what Octokit is doing under the hood. Faraday makes it
320
+ easy to peek into the underlying HTTP traffic:
321
+
322
+ ```ruby
323
+ stack = Faraday::Builder.new do |builder|
324
+ builder.response :logger
325
+ builder.use Octokit::Response::RaiseError
326
+ builder.adapter Faraday.default_adapter
327
+ end
328
+ Octokit.middleware = stack
329
+ Octokit.user 'pengwynn'
330
+ ```
331
+ ```
332
+ I, [2013-08-22T15:54:38.583300 #88227] INFO -- : get https://api.github.com/users/pengwynn
333
+ D, [2013-08-22T15:54:38.583401 #88227] DEBUG -- request: Accept: "application/vnd.github.beta+json"
334
+ User-Agent: "Octokit Ruby Gem 2.0.0.rc4"
335
+ I, [2013-08-22T15:54:38.843313 #88227] INFO -- Status: 200
336
+ D, [2013-08-22T15:54:38.843459 #88227] DEBUG -- response: server: "GitHub.com"
337
+ date: "Thu, 22 Aug 2013 20:54:40 GMT"
338
+ content-type: "application/json; charset=utf-8"
339
+ transfer-encoding: "chunked"
340
+ connection: "close"
341
+ status: "200 OK"
342
+ x-ratelimit-limit: "60"
343
+ x-ratelimit-remaining: "39"
344
+ x-ratelimit-reset: "1377205443"
345
+ ...
346
+ ```
347
+
348
+ See the [Faraday README][faraday] for more middleware magic.
349
+
350
+ ### Caching
351
+
352
+ If you want to boost performance, stretch your API rate limit, or avoid paying
353
+ the hypermedia tax, you can use [Faraday Http Cache][cache].
354
+
355
+ Add the gem to your Gemfile
356
+
357
+ gem 'faraday-http-cache'
358
+
359
+ Next, construct your own Faraday middleware:
360
+
361
+ ```ruby
362
+ stack = Faraday::Builder.new do |builder|
363
+ builder.use Faraday::HttpCache
364
+ builder.use Octokit::Response::RaiseError
365
+ builder.adapter Faraday.default_adapter
366
+ end
367
+ Octokit.middleware = stack
368
+ ```
369
+
370
+ Once configured, the middleware will store responses in cache based on ETag
371
+ fingerprint and serve those back up for future `304` responses for the same
372
+ resource. See the [project README][cache] for advanced usage.
373
+
374
+
375
+ [cache]: https://github.com/plataformatec/faraday-http-cache
376
+ [faraday]: https://github.com/lostisland/faraday
377
+
378
+ ## Hacking on Octokit.rb
379
+
380
+ If you want to hack on Octokit locally, we try to make [bootstrapping the
381
+ project][bootstrapping] as painless as possible. Just clone and run:
382
+
383
+ script/bootstrap
384
+
385
+ This will install project dependencies and get you up and running. If you want
386
+ to run a Ruby console to poke on Octokit, you can crank one up with:
387
+
388
+ script/console
389
+
390
+ Using the scripts in `./scripts` instead of `bundle exec rspec`, `bundle
391
+ console`, etc. ensures your dependencies are up-to-date.
392
+
393
+ ### Running and writing new tests
394
+
395
+ Octokit uses [VCR][] for recording and playing back API fixtures during test
396
+ runs. These fixtures are part of the Git project in the `spec/cassettes`
397
+ folder. For the most part, tests use an authenticated client, using a token
398
+ stored in `ENV['OCTOKIT_TEST_GITHUB_TOKEN']`. If you're not recording new
399
+ cassettes, you don't need to have this set. If you do need to record new
400
+ cassettes, this token can be any GitHub API token because the test suite strips
401
+ the actual token from the cassette output before storing to disk.
402
+
403
+ Since we periodically refresh our cassettes, please keep some points in mind
404
+ when writing new specs.
405
+
406
+ * **Specs should be idempotent**. The HTTP calls made during a spec should be
407
+ able to be run over and over. This means deleting a known resource prior to
408
+ creating it if the name has to be unique.
409
+ * **Specs should be able to be run in random order.** If a spec depends on
410
+ another resource as a fixture, make sure that's created in the scope of the
411
+ spec and not depend on a previous spec to create the data needed.
412
+ * **Do not depend on authenticated user info.** Instead of asserting
413
+ actual values in resources, try to assert the existence of a key or that a
414
+ response is an Array. We're testing the client, not the API.
415
+
416
+ [bootstrapping]: http://wynnnetherland.com/linked/2013012801/bootstrapping-consistency
417
+ [VCR]: https://github.com/vcr/vcr
418
+
92
419
  ## Supported Ruby Versions
93
420
 
94
421
  This library aims to support and is [tested against][travis] the following Ruby
95
422
  implementations:
96
423
 
97
- * Ruby 1.8.7
98
424
  * Ruby 1.9.2
99
425
  * Ruby 1.9.3
100
426
  * Ruby 2.0.0
@@ -125,40 +451,11 @@ introduced with new major versions. As a result of this policy, you can (and
125
451
  should) specify a dependency on this gem using the [Pessimistic Version
126
452
  Constraint][pvc] with two digits of precision. For example:
127
453
 
128
- spec.add_dependency 'octokit', '~> 1.0'
454
+ spec.add_dependency 'octokit', '~> 2.0'
129
455
 
130
456
  [semver]: http://semver.org/
131
457
  [pvc]: http://docs.rubygems.org/read/chapter/16#page74
132
458
 
133
- ### JSON dependency
134
-
135
- Since JSON is included in 1.9 now, we no longer include it as a hard
136
- dependency. Please require it explicitly if you're running Ruby 1.8
137
-
138
- gem 'json', '~> 1.7'
139
-
140
- ## Contributors
141
-
142
- Octokit was initially created by Wynn Netherland and [Adam
143
- Stacoviak](http://twitter.com/adamstac) but has
144
- turned into a true community effort. Special thanks to the following
145
- contributors:
146
-
147
- * [Erik Michaels-Ober](http://github.com/sferik)
148
- * [Clint Shryock](http://github.com/ctshryock)
149
- * [Joey Wendt](http://github.com/joeyw)
150
-
151
-
152
- ## Inspiration
153
-
154
- Octokit was inspired by [Octopi][] and aims to be a lightweight,
155
- less-ActiveResourcey alternative.
156
-
157
- [octopi]: https://github.com/fcoury/octopi
158
-
159
- ## Copyright
160
-
161
- Copyright (c) 2011-2013 Wynn Netherland, Adam Stacoviak, Erik Michaels-Ober.
162
- See [LICENSE][] for details.
459
+ ## License
163
460
 
164
- [license]: LICENSE.md
461
+ {include:file:LICENSE.md}