github_api 0.11.2 → 0.11.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +139 -78
- data/Rakefile +13 -1
- data/features/cassettes/{auths/list.yml → repos/pages/get.yml} +14 -12
- data/features/cassettes/repos/pages/list_builds.yml +63 -0
- data/features/cassettes/repos/pages/list_latest_builds.yml +62 -0
- data/features/repos/pages.feature +24 -0
- data/features/settings.yml +7 -0
- data/lib/github_api.rb +0 -1
- data/lib/github_api/authorizations.rb +55 -41
- data/lib/github_api/authorizations/app.rb +77 -0
- data/lib/github_api/core_ext/array.rb +13 -5
- data/lib/github_api/core_ext/hash.rb +49 -30
- data/lib/github_api/repos.rb +6 -0
- data/lib/github_api/repos/deployments.rb +8 -0
- data/lib/github_api/repos/pages.rb +49 -0
- data/lib/github_api/validations/required.rb +1 -1
- data/lib/github_api/version.rb +1 -1
- data/spec/github/authorizations/app/create_spec.rb +44 -0
- data/spec/github/authorizations/app/delete_spec.rb +59 -0
- data/spec/github/authorizations/create_spec.rb +13 -13
- data/spec/github/authorizations/delete_spec.rb +5 -4
- data/spec/github/core_ext/hash_spec.rb +5 -5
- data/spec/github/normalizer_spec.rb +2 -2
- data/spec/github/parameter_filter_spec.rb +5 -5
- metadata +49 -43
- data/features/authorizations.feature +0 -12
- data/lib/github_api/core_ext/deep_merge.rb +0 -13
- data/lib/github_api/ssl_certs/cacert.pem +0 -41
@@ -0,0 +1,63 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://<BASIC_AUTH>@api.github.com/repos/<USER>/github_api_test/pages/builds?access_token=<TOKEN>
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ""
|
9
|
+
headers:
|
10
|
+
Accept:
|
11
|
+
- application/vnd.github.v3+json,application/vnd.github.beta+json;q=0.5,application/json;q=0.1
|
12
|
+
Accept-Charset:
|
13
|
+
- utf-8
|
14
|
+
User-Agent:
|
15
|
+
- Github Ruby Gem 0.11.2
|
16
|
+
Accept-Encoding:
|
17
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 200
|
21
|
+
message: OK
|
22
|
+
headers:
|
23
|
+
Server:
|
24
|
+
- GitHub.com
|
25
|
+
Date:
|
26
|
+
- Sun, 16 Feb 2014 19:13:30 GMT
|
27
|
+
Content-Type:
|
28
|
+
- application/json; charset=utf-8
|
29
|
+
Status:
|
30
|
+
- 200 OK
|
31
|
+
X-Ratelimit-Limit:
|
32
|
+
- "5000"
|
33
|
+
X-Ratelimit-Remaining:
|
34
|
+
- "4987"
|
35
|
+
X-Ratelimit-Reset:
|
36
|
+
- "1392579836"
|
37
|
+
Cache-Control:
|
38
|
+
- private, max-age=60, s-maxage=60
|
39
|
+
Etag:
|
40
|
+
- "\"be2b47a6aa91c255a63bbfbd08983b13\""
|
41
|
+
Vary:
|
42
|
+
- Accept, Authorization, Cookie, X-GitHub-OTP
|
43
|
+
- Accept-Encoding
|
44
|
+
X-Github-Media-Type:
|
45
|
+
- github.v3; format=json
|
46
|
+
X-Content-Type-Options:
|
47
|
+
- nosniff
|
48
|
+
Content-Length:
|
49
|
+
- "2"
|
50
|
+
Access-Control-Allow-Credentials:
|
51
|
+
- "true"
|
52
|
+
Access-Control-Expose-Headers:
|
53
|
+
- ETag, Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
|
54
|
+
Access-Control-Allow-Origin:
|
55
|
+
- "*"
|
56
|
+
X-Github-Request-Id:
|
57
|
+
- 4D649864:435B:232290A:53010DDA
|
58
|
+
body:
|
59
|
+
encoding: US-ASCII
|
60
|
+
string: "[]"
|
61
|
+
http_version:
|
62
|
+
recorded_at: Sun, 16 Feb 2014 19:13:30 GMT
|
63
|
+
recorded_with: VCR 2.6.0
|
@@ -0,0 +1,62 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://<BASIC_AUTH>@api.github.com/repos/<USER>/github_api_test/pages/builds/latest?access_token=<TOKEN>
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ""
|
9
|
+
headers:
|
10
|
+
Accept:
|
11
|
+
- application/vnd.github.v3+json,application/vnd.github.beta+json;q=0.5,application/json;q=0.1
|
12
|
+
Accept-Charset:
|
13
|
+
- utf-8
|
14
|
+
User-Agent:
|
15
|
+
- Github Ruby Gem 0.11.2
|
16
|
+
Accept-Encoding:
|
17
|
+
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
|
18
|
+
response:
|
19
|
+
status:
|
20
|
+
code: 404
|
21
|
+
message: Not Found
|
22
|
+
headers:
|
23
|
+
Server:
|
24
|
+
- GitHub.com
|
25
|
+
Date:
|
26
|
+
- Sun, 16 Feb 2014 19:21:04 GMT
|
27
|
+
Content-Type:
|
28
|
+
- application/json; charset=utf-8
|
29
|
+
Transfer-Encoding:
|
30
|
+
- chunked
|
31
|
+
Status:
|
32
|
+
- 404 Not Found
|
33
|
+
X-Ratelimit-Limit:
|
34
|
+
- "5000"
|
35
|
+
X-Ratelimit-Remaining:
|
36
|
+
- "4983"
|
37
|
+
X-Ratelimit-Reset:
|
38
|
+
- "1392579836"
|
39
|
+
X-Github-Media-Type:
|
40
|
+
- github.v3; format=json
|
41
|
+
X-Content-Type-Options:
|
42
|
+
- nosniff
|
43
|
+
Access-Control-Allow-Credentials:
|
44
|
+
- "true"
|
45
|
+
Access-Control-Expose-Headers:
|
46
|
+
- ETag, Link, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
|
47
|
+
Access-Control-Allow-Origin:
|
48
|
+
- "*"
|
49
|
+
X-Github-Request-Id:
|
50
|
+
- 4D649864:435B:233DE61:53010FA0
|
51
|
+
Content-Encoding:
|
52
|
+
- gzip
|
53
|
+
body:
|
54
|
+
encoding: ASCII-8BIT
|
55
|
+
string: !binary |
|
56
|
+
H4sIAAAAAAAAA6tWyk0tLk5MT1WyUvLLL1Fwyy/NS1HSUUrJTy7NTc0rSSzJ
|
57
|
+
zM+LLy3KAcpnlJQUWOnrp6SWpebkF6QW6aVnlmSUJukl5+fqlxkr1QIARorx
|
58
|
+
tEwAAAA=
|
59
|
+
|
60
|
+
http_version:
|
61
|
+
recorded_at: Sun, 16 Feb 2014 19:21:04 GMT
|
62
|
+
recorded_with: VCR 2.6.0
|
@@ -0,0 +1,24 @@
|
|
1
|
+
Feature: Pages API
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given I have "Github::Repos::Pages" instance
|
5
|
+
|
6
|
+
Scenario: List builds
|
7
|
+
|
8
|
+
Given I want to list resources with the following params:
|
9
|
+
| owner | repo |
|
10
|
+
| murek | github_api_test |
|
11
|
+
When I make request within a cassette named "repos/pages/list_builds"
|
12
|
+
Then the response status should be 200
|
13
|
+
And the response type should be JSON
|
14
|
+
And the response should be empty
|
15
|
+
|
16
|
+
Scenario: Get
|
17
|
+
|
18
|
+
Given I want to get resource with the following params:
|
19
|
+
| owner | repo |
|
20
|
+
| murek | github_api_test |
|
21
|
+
When I make request within a cassette named "repos/pages/get"
|
22
|
+
Then the response status should be 200
|
23
|
+
And the response type should be JSON
|
24
|
+
And the response should not be empty
|
data/lib/github_api.rb
CHANGED
@@ -5,6 +5,8 @@ module Github
|
|
5
5
|
# OAuth Authorizations API
|
6
6
|
class Authorizations < API
|
7
7
|
|
8
|
+
Github::require_all 'github_api/authorizations', 'app'
|
9
|
+
|
8
10
|
VALID_AUTH_PARAM_NAMES = %w[
|
9
11
|
scopes
|
10
12
|
add_scopes
|
@@ -15,15 +17,21 @@ module Github
|
|
15
17
|
client_secret
|
16
18
|
].freeze
|
17
19
|
|
20
|
+
# Access to Authorizations::App API
|
21
|
+
def app(options={}, &block)
|
22
|
+
@app ||= ApiFactory.new('Authorizations::App', current_options.merge(options), &block)
|
23
|
+
end
|
24
|
+
|
18
25
|
# List authorizations
|
19
26
|
#
|
20
|
-
#
|
21
|
-
# github = Github.new :
|
27
|
+
# @example
|
28
|
+
# github = Github.new basic_auth: 'login:password'
|
22
29
|
# github.oauth.list
|
23
30
|
# github.oauth.list { |auth| ... }
|
24
31
|
#
|
32
|
+
# @api public
|
25
33
|
def list(*args)
|
26
|
-
|
34
|
+
raise_authentication_error unless authenticated?
|
27
35
|
arguments(args)
|
28
36
|
|
29
37
|
response = get_request('/authorizations', arguments.params)
|
@@ -34,12 +42,15 @@ module Github
|
|
34
42
|
|
35
43
|
# Get a single authorization
|
36
44
|
#
|
37
|
-
#
|
38
|
-
# github = Github.new :
|
45
|
+
# @example
|
46
|
+
# github = Github.new basic_auth: 'login:password'
|
39
47
|
# github.oauth.get 'authorization-id'
|
40
48
|
#
|
49
|
+
# @return [ResponseWrapper]
|
50
|
+
#
|
51
|
+
# @api public
|
41
52
|
def get(*args)
|
42
|
-
|
53
|
+
raise_authentication_error unless authenticated?
|
43
54
|
arguments(args, required: [:authorization_id])
|
44
55
|
|
45
56
|
get_request("/authorizations/#{authorization_id}", arguments.params)
|
@@ -48,18 +59,26 @@ module Github
|
|
48
59
|
|
49
60
|
# Create a new authorization
|
50
61
|
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
62
|
+
# @param [Hash] params
|
63
|
+
# @option params [Array[String]] :scopes
|
64
|
+
# A list of scopes that this authorization is in.
|
65
|
+
# @option params [String] :note
|
66
|
+
# A note to remind you what the OAuth token is for.
|
67
|
+
# @option params [String] :note_url
|
68
|
+
# A URL to remind you what the OAuth token is for.
|
69
|
+
# @option params [String] :client_id
|
70
|
+
# The 20 character OAuth app client key for which to create the token.
|
71
|
+
# @option params [String] :client_secret
|
72
|
+
# The 40 character OAuth app client secret for which to create the token.
|
55
73
|
#
|
56
|
-
#
|
57
|
-
# github = Github.new :
|
74
|
+
# @example
|
75
|
+
# github = Github.new basic_auth: 'login:password'
|
58
76
|
# github.oauth.create
|
59
77
|
# "scopes" => ["public_repo"]
|
60
78
|
#
|
79
|
+
# @api public
|
61
80
|
def create(*args)
|
62
|
-
|
81
|
+
raise_authentication_error unless authenticated?
|
63
82
|
arguments(args) do
|
64
83
|
sift VALID_AUTH_PARAM_NAMES
|
65
84
|
end
|
@@ -69,19 +88,25 @@ module Github
|
|
69
88
|
|
70
89
|
# Update an existing authorization
|
71
90
|
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
91
|
+
# @param [Hash] inputs
|
92
|
+
# @option inputs [Array] :scopes
|
93
|
+
# Optional array - A list of scopes that this authorization is in.
|
94
|
+
# @option inputs [Array] :add_scopes
|
95
|
+
# Optional array - A list of scopes to add to this authorization.
|
96
|
+
# @option inputs [Array] :remove_scopes
|
97
|
+
# Optional array - A list of scopes to remove from this authorization.
|
98
|
+
# @option inputs [String] :note
|
99
|
+
# Optional string - A note to remind you what the OAuth token is for.
|
100
|
+
# @optoin inputs [String] :note_url
|
101
|
+
# Optional string - A URL to remind you what the OAuth token is for.
|
78
102
|
#
|
79
|
-
#
|
80
|
-
# github = Github.new :
|
81
|
-
# github.oauth.update "authorization-id",
|
103
|
+
# @example
|
104
|
+
# github = Github.new basic_auth: 'login:password'
|
105
|
+
# github.oauth.update "authorization-id", add_scopes: ["repo"]
|
82
106
|
#
|
107
|
+
# @api public
|
83
108
|
def update(*args)
|
84
|
-
|
109
|
+
raise_authentication_error unless authenticated?
|
85
110
|
arguments(args, required: [:authorization_id]) do
|
86
111
|
sift VALID_AUTH_PARAM_NAMES
|
87
112
|
end
|
@@ -92,34 +117,23 @@ module Github
|
|
92
117
|
|
93
118
|
# Delete an authorization
|
94
119
|
#
|
95
|
-
#
|
120
|
+
# @example
|
96
121
|
# github.oauth.delete 'authorization-id'
|
97
122
|
#
|
123
|
+
# @api public
|
98
124
|
def delete(*args)
|
99
|
-
|
125
|
+
raise_authentication_error unless authenticated?
|
100
126
|
arguments(args, required: [:authorization_id])
|
101
127
|
|
102
128
|
delete_request("/authorizations/#{authorization_id}", arguments.params)
|
103
129
|
end
|
104
130
|
alias :remove :delete
|
105
131
|
|
106
|
-
|
107
|
-
#
|
108
|
-
# = Examples
|
109
|
-
# github = Github.new basic_auth: "client_id:client_secret"
|
110
|
-
# github.oauth.revoke 'client-id'
|
111
|
-
#
|
112
|
-
#
|
113
|
-
def revoke(*args)
|
114
|
-
|
115
|
-
end
|
116
|
-
|
117
|
-
private
|
132
|
+
protected
|
118
133
|
|
119
|
-
def
|
120
|
-
|
121
|
-
|
122
|
-
end
|
134
|
+
def raise_authentication_error
|
135
|
+
raise ArgumentError, 'You can only access your own tokens' +
|
136
|
+
' via Basic Authentication'
|
123
137
|
end
|
124
138
|
|
125
139
|
end # Authorizations
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Github
|
4
|
+
|
5
|
+
class Authorizations::App < Authorizations
|
6
|
+
|
7
|
+
# Get-or-create an authorization for a specific app
|
8
|
+
#
|
9
|
+
# @param [Hash] params
|
10
|
+
# @option params [String] client_secret
|
11
|
+
# The 40 character OAuth app client secret associated with the client
|
12
|
+
# ID specified in the URL.
|
13
|
+
# @option params [Array] :scopes
|
14
|
+
# Optional array - A list of scopes that this authorization is in.
|
15
|
+
# @option params [String] :note
|
16
|
+
# Optional string - A note to remind you what the OAuth token is for.
|
17
|
+
# @option params [String] :note_url
|
18
|
+
# Optional string - A URL to remind you what the OAuth token is for.
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# github = Github.new
|
22
|
+
# github.oauth.app.create 'client-id', client_secret: '...'
|
23
|
+
#
|
24
|
+
# @api public
|
25
|
+
def create(*args)
|
26
|
+
raise_authentication_error unless authenticated?
|
27
|
+
arguments(args, required: [:client_id]) do
|
28
|
+
sift Authorizations::VALID_AUTH_PARAM_NAMES
|
29
|
+
end
|
30
|
+
|
31
|
+
if client_id
|
32
|
+
put_request("/authorizations/clients/#{client_id}", arguments.params)
|
33
|
+
else
|
34
|
+
raise raise_app_authentication_error
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Revoke all authorizations for an application
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
# github = Github.new basic_auth: "client_id:client_secret"
|
42
|
+
# github.oauth.app.delete 'client-id'
|
43
|
+
#
|
44
|
+
# Revoke an authorization for an application
|
45
|
+
#
|
46
|
+
# @example
|
47
|
+
#
|
48
|
+
# github = Github.new basic_auth: "client_id:client_secret"
|
49
|
+
# github.oauth.app.delete 'client-id', 'access-token'
|
50
|
+
#
|
51
|
+
# @api public
|
52
|
+
def delete(*args)
|
53
|
+
raise_authentication_error unless authenticated?
|
54
|
+
params = arguments(args, required: [:client_id]).params
|
55
|
+
|
56
|
+
if client_id
|
57
|
+
if access_token = (params.delete('access_token') || args[1])
|
58
|
+
delete_request("/applications/#{client_id}/tokens/#{access_token}", params)
|
59
|
+
else
|
60
|
+
# Revokes all tokens
|
61
|
+
delete_request("/applications/#{client_id}/tokens", params)
|
62
|
+
end
|
63
|
+
else
|
64
|
+
raise raise_app_authentication_error
|
65
|
+
end
|
66
|
+
end
|
67
|
+
alias :remove :delete
|
68
|
+
alias :revoke :delete
|
69
|
+
|
70
|
+
protected
|
71
|
+
|
72
|
+
def raise_app_authentication_error
|
73
|
+
raise ArgumentError, 'To create authorization for the app, ' +
|
74
|
+
'you need to provide client_id argument and client_secret parameter'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -1,17 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
class Array # :nodoc:
|
2
4
|
|
3
|
-
|
5
|
+
# Returns a new arrray with keys removed
|
6
|
+
#
|
7
|
+
def except(*keys)
|
4
8
|
self.dup.except!(*keys)
|
5
|
-
end unless method_defined?
|
9
|
+
end unless method_defined? :except
|
6
10
|
|
7
|
-
|
11
|
+
# Similar to except but modifies self
|
12
|
+
#
|
13
|
+
def except!(*items)
|
8
14
|
copy = self.dup
|
9
15
|
copy.reject! { |item| items.include? item }
|
10
16
|
copy
|
11
|
-
end unless method_defined?
|
17
|
+
end unless method_defined? :except!
|
12
18
|
|
19
|
+
# Selects a hash from the arguments list
|
20
|
+
#
|
13
21
|
def extract_options!
|
14
22
|
last.is_a?(::Hash) ? pop : {}
|
15
|
-
end
|
23
|
+
end unless method_defined? :extract_options!
|
16
24
|
|
17
25
|
end # Array
|
@@ -1,23 +1,33 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
class Hash # :nodoc:
|
2
4
|
|
3
|
-
|
5
|
+
# Returns a new hash with keys removed
|
6
|
+
#
|
7
|
+
def except(*items)
|
4
8
|
self.dup.except!(*items)
|
5
|
-
end unless method_defined?
|
9
|
+
end unless method_defined? :except
|
6
10
|
|
7
|
-
|
11
|
+
# Similar to except but modifies self
|
12
|
+
#
|
13
|
+
def except!(*keys)
|
8
14
|
copy = self.dup
|
9
15
|
keys.each { |key| copy.delete!(key) }
|
10
16
|
copy
|
11
|
-
end unless method_defined?
|
17
|
+
end unless method_defined? :except!
|
12
18
|
|
13
|
-
|
19
|
+
# Returns a new hash with all the keys converted to symbols
|
20
|
+
#
|
21
|
+
def symbolize_keys
|
14
22
|
inject({}) do |hash, (key, value)|
|
15
23
|
hash[(key.to_sym rescue key) || key] = value
|
16
24
|
hash
|
17
25
|
end
|
18
|
-
end unless method_defined?
|
26
|
+
end unless method_defined? :symbolize_keys
|
19
27
|
|
20
|
-
|
28
|
+
# Similar to symbolize_keys but modifies self
|
29
|
+
#
|
30
|
+
def symbolize_keys!
|
21
31
|
hash = symbolize_keys
|
22
32
|
hash.each do |key, val|
|
23
33
|
hash[key] = case val
|
@@ -32,42 +42,51 @@ class Hash # :nodoc:
|
|
32
42
|
end
|
33
43
|
end
|
34
44
|
return hash
|
35
|
-
end unless method_defined?
|
45
|
+
end unless method_defined? :symbolize_keys!
|
36
46
|
|
37
|
-
|
47
|
+
# Returns hash collapsed into a query string
|
48
|
+
#
|
49
|
+
def serialize
|
38
50
|
self.map { |key, val| [key, val].join("=") }.join("&")
|
39
|
-
end unless method_defined?
|
51
|
+
end unless method_defined? :serialize
|
40
52
|
|
41
|
-
|
53
|
+
# Searches for all deeply nested keys
|
54
|
+
#
|
55
|
+
def deep_keys
|
42
56
|
keys = self.keys
|
43
57
|
keys.each do |key|
|
44
58
|
if self[key].is_a?(Hash)
|
45
|
-
keys << self[key].
|
59
|
+
keys << self[key].deep_keys.compact.flatten
|
46
60
|
next
|
47
61
|
end
|
48
62
|
end
|
49
63
|
keys.flatten
|
50
|
-
end unless method_defined?
|
64
|
+
end unless method_defined? :deep_keys
|
51
65
|
|
52
|
-
|
53
|
-
|
54
|
-
|
66
|
+
# Returns true if the given key is present inside deeply nested hash
|
67
|
+
#
|
68
|
+
def deep_key?(key)
|
69
|
+
self.deep_keys.include? key
|
70
|
+
end unless method_defined? :deep_key?
|
55
71
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
72
|
+
# Recursively merges self with other hash and returns new hash.
|
73
|
+
#
|
74
|
+
def deep_merge(other, &block)
|
75
|
+
dup.deep_merge!(other, &block)
|
76
|
+
end unless method_defined? :deep_merge
|
77
|
+
|
78
|
+
# Similar as deep_merge but modifies self
|
79
|
+
#
|
80
|
+
def deep_merge!(other, &block)
|
81
|
+
other.each_pair do |key, val|
|
82
|
+
tval = self[key]
|
83
|
+
if tval.is_a?(Hash) && val.is_a?(Hash)
|
84
|
+
self[key] = tval.deep_merge(val)
|
85
|
+
else
|
86
|
+
self[key] = block && tval ? block.call(k, tval, val) : val
|
68
87
|
end
|
69
88
|
end
|
70
|
-
|
71
|
-
end
|
89
|
+
self
|
90
|
+
end unless method_defined? :deep_merge!
|
72
91
|
|
73
92
|
end # Hash
|