octokit 4.22.0 → 9.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +117 -95
- data/Rakefile +20 -14
- data/lib/ext/sawyer/relation.rb +4 -2
- data/lib/octokit/arguments.rb +3 -3
- data/lib/octokit/authentication.rb +10 -3
- data/lib/octokit/client/actions_artifacts.rb +71 -0
- data/lib/octokit/client/actions_secrets.rb +111 -8
- data/lib/octokit/client/actions_workflow_jobs.rb +65 -0
- data/lib/octokit/client/actions_workflow_runs.rb +23 -3
- data/lib/octokit/client/actions_workflows.rb +27 -2
- data/lib/octokit/client/apps.rb +63 -26
- data/lib/octokit/client/checks.rb +18 -9
- data/lib/octokit/client/code_scanning.rb +190 -0
- data/lib/octokit/client/codespaces_secrets.rb +108 -0
- data/lib/octokit/client/commit_branches.rb +2 -2
- data/lib/octokit/client/commit_comments.rb +8 -8
- data/lib/octokit/client/commit_pulls.rb +2 -2
- data/lib/octokit/client/commits.rb +25 -33
- data/lib/octokit/client/community_profile.rb +2 -3
- data/lib/octokit/client/contents.rb +19 -22
- data/lib/octokit/client/dependabot_secrets.rb +108 -0
- data/lib/octokit/client/deployments.rb +8 -8
- data/lib/octokit/client/downloads.rb +5 -6
- data/lib/octokit/client/emojis.rb +3 -3
- data/lib/octokit/client/environments.rb +58 -0
- data/lib/octokit/client/events.rb +4 -5
- data/lib/octokit/client/feeds.rb +4 -5
- data/lib/octokit/client/gists.rb +6 -6
- data/lib/octokit/client/gitignore.rb +3 -3
- data/lib/octokit/client/hooks.rb +9 -19
- data/lib/octokit/client/issues.rb +14 -15
- data/lib/octokit/client/labels.rb +10 -10
- data/lib/octokit/client/legacy_search.rb +3 -3
- data/lib/octokit/client/licenses.rb +3 -6
- data/lib/octokit/client/markdown.rb +3 -3
- data/lib/octokit/client/marketplace.rb +4 -4
- data/lib/octokit/client/meta.rb +4 -5
- data/lib/octokit/client/milestones.rb +5 -5
- data/lib/octokit/client/notifications.rb +6 -6
- data/lib/octokit/client/oauth_applications.rb +1 -7
- data/lib/octokit/client/objects.rb +14 -14
- data/lib/octokit/client/organizations.rb +100 -56
- data/lib/octokit/client/pages.rb +5 -7
- data/lib/octokit/client/projects.rb +44 -64
- data/lib/octokit/client/pull_requests.rb +66 -45
- data/lib/octokit/client/rate_limit.rb +9 -11
- data/lib/octokit/client/reactions.rb +62 -16
- data/lib/octokit/client/refs.rb +14 -17
- data/lib/octokit/client/releases.rb +13 -13
- data/lib/octokit/client/repositories.rb +92 -69
- data/lib/octokit/client/repository_invitations.rb +3 -3
- data/lib/octokit/client/reviews.rb +8 -8
- data/lib/octokit/client/say.rb +4 -5
- data/lib/octokit/client/search.rb +24 -10
- data/lib/octokit/client/service_status.rb +19 -9
- data/lib/octokit/client/source_import.rb +7 -12
- data/lib/octokit/client/stats.rb +10 -9
- data/lib/octokit/client/statuses.rb +5 -5
- data/lib/octokit/client/tokens.rb +31 -0
- data/lib/octokit/client/traffic.rb +6 -11
- data/lib/octokit/client/users.rb +54 -33
- data/lib/octokit/client.rb +42 -18
- data/lib/octokit/configurable.rb +51 -31
- data/lib/octokit/connection.rb +30 -21
- data/lib/octokit/default.rb +66 -35
- data/lib/octokit/enterprise_admin_client/admin_stats.rb +13 -14
- data/lib/octokit/enterprise_admin_client/license.rb +3 -4
- data/lib/octokit/enterprise_admin_client/orgs.rb +3 -4
- data/lib/octokit/enterprise_admin_client/search_indexing.rb +7 -8
- data/lib/octokit/enterprise_admin_client/users.rb +5 -4
- data/lib/octokit/enterprise_admin_client.rb +9 -3
- data/lib/octokit/enterprise_management_console_client/management_console.rb +51 -33
- data/lib/octokit/enterprise_management_console_client.rb +8 -2
- data/lib/octokit/error.rb +51 -34
- data/lib/octokit/gist.rb +3 -4
- data/lib/octokit/manage_ghes_client/manage_ghes.rb +178 -0
- data/lib/octokit/manage_ghes_client.rb +64 -0
- data/lib/octokit/middleware/follow_redirects.rb +13 -12
- data/lib/octokit/organization.rb +3 -1
- data/lib/octokit/rate_limit.rb +8 -6
- data/lib/octokit/repo_arguments.rb +3 -4
- data/lib/octokit/repository.rb +32 -25
- data/lib/octokit/response/base_middleware.rb +10 -0
- data/lib/octokit/response/feed_parser.rb +5 -7
- data/lib/octokit/response/raise_error.rb +4 -4
- data/lib/octokit/user.rb +4 -2
- data/lib/octokit/version.rb +4 -2
- data/lib/octokit/warnable.rb +4 -5
- data/lib/octokit.rb +30 -8
- data/octokit.gemspec +12 -11
- metadata +19 -31
- data/lib/octokit/client/authorizations.rb +0 -182
- data/lib/octokit/client/pub_sub_hubbub.rb +0 -111
- data/lib/octokit/preview.rb +0 -46
data/lib/octokit/error.rb
CHANGED
@@ -1,12 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Octokit
|
2
4
|
# Custom error class for rescuing from all GitHub errors
|
3
5
|
class Error < StandardError
|
4
6
|
attr_reader :context
|
7
|
+
|
5
8
|
# Returns the appropriate Octokit::Error subclass based
|
6
9
|
# on status and response message
|
7
10
|
#
|
8
11
|
# @param [Hash] response HTTP response
|
9
12
|
# @return [Octokit::Error]
|
13
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
10
14
|
def self.from_response(response)
|
11
15
|
status = response[:status].to_i
|
12
16
|
body = response[:body].to_s
|
@@ -20,6 +24,7 @@ module Octokit
|
|
20
24
|
when 405 then Octokit::MethodNotAllowed
|
21
25
|
when 406 then Octokit::NotAcceptable
|
22
26
|
when 409 then Octokit::Conflict
|
27
|
+
when 410 then Octokit::Deprecated
|
23
28
|
when 415 then Octokit::UnsupportedMediaType
|
24
29
|
when 422 then error_for_422(body)
|
25
30
|
when 451 then Octokit::UnavailableForLegalReasons
|
@@ -33,14 +38,15 @@ module Octokit
|
|
33
38
|
klass.new(response)
|
34
39
|
end
|
35
40
|
end
|
41
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
36
42
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
43
|
+
def build_error_context
|
44
|
+
if RATE_LIMITED_ERRORS.include?(self.class)
|
45
|
+
@context = Octokit::RateLimit.from_response(@response)
|
46
|
+
end
|
47
|
+
end
|
42
48
|
|
43
|
-
def initialize(response=nil)
|
49
|
+
def initialize(response = nil)
|
44
50
|
@response = response
|
45
51
|
super(build_error_message)
|
46
52
|
build_error_context
|
@@ -55,7 +61,9 @@ module Octokit
|
|
55
61
|
|
56
62
|
# Returns most appropriate error for 401 HTTP status code
|
57
63
|
# @private
|
64
|
+
# rubocop:disable Naming/VariableNumber
|
58
65
|
def self.error_for_401(headers)
|
66
|
+
# rubocop:enbale Naming/VariableNumber
|
59
67
|
if Octokit::OneTimePasswordRequired.required_header(headers)
|
60
68
|
Octokit::OneTimePasswordRequired
|
61
69
|
else
|
@@ -66,25 +74,27 @@ module Octokit
|
|
66
74
|
# Returns most appropriate error for 403 HTTP status code
|
67
75
|
# @private
|
68
76
|
def self.error_for_403(body)
|
69
|
-
|
77
|
+
# rubocop:enable Naming/VariableNumber
|
78
|
+
case body
|
79
|
+
when /rate limit exceeded/i, /exceeded a secondary rate limit/i
|
70
80
|
Octokit::TooManyRequests
|
71
|
-
|
81
|
+
when /login attempts exceeded/i
|
72
82
|
Octokit::TooManyLoginAttempts
|
73
|
-
|
83
|
+
when /(returns|for) blobs (up to|between) [0-9-]+ MB/i
|
74
84
|
Octokit::TooLargeContent
|
75
|
-
|
85
|
+
when /abuse/i
|
76
86
|
Octokit::AbuseDetected
|
77
|
-
|
87
|
+
when /repository access blocked/i
|
78
88
|
Octokit::RepositoryUnavailable
|
79
|
-
|
89
|
+
when /email address must be verified/i
|
80
90
|
Octokit::UnverifiedEmail
|
81
|
-
|
91
|
+
when /account was suspended/i
|
82
92
|
Octokit::AccountSuspended
|
83
|
-
|
93
|
+
when /billing issue/i
|
84
94
|
Octokit::BillingIssue
|
85
|
-
|
95
|
+
when /Resource protected by organization SAML enforcement/i
|
86
96
|
Octokit::SAMLProtected
|
87
|
-
|
97
|
+
when /suspended your access|This installation has been suspended/i
|
88
98
|
Octokit::InstallationSuspended
|
89
99
|
else
|
90
100
|
Octokit::Forbidden
|
@@ -93,7 +103,9 @@ module Octokit
|
|
93
103
|
|
94
104
|
# Return most appropriate error for 404 HTTP status code
|
95
105
|
# @private
|
106
|
+
# rubocop:disable Naming/VariableNumber
|
96
107
|
def self.error_for_404(body)
|
108
|
+
# rubocop:enable Naming/VariableNumber
|
97
109
|
if body =~ /Branch not protected/i
|
98
110
|
Octokit::BranchNotProtected
|
99
111
|
else
|
@@ -103,7 +115,9 @@ module Octokit
|
|
103
115
|
|
104
116
|
# Return most appropriate error for 422 HTTP status code
|
105
117
|
# @private
|
118
|
+
# rubocop:disable Naming/VariableNumber
|
106
119
|
def self.error_for_422(body)
|
120
|
+
# rubocop:enable Naming/VariableNumber
|
107
121
|
if body =~ /PullRequestReviewComment/i && body =~ /(commit_id|end_commit_oid) is not part of the pull request/i
|
108
122
|
Octokit::CommitIsNotPartOfPullRequest
|
109
123
|
elsif body =~ /Path diff too large/i
|
@@ -116,7 +130,7 @@ module Octokit
|
|
116
130
|
# Array of validation errors
|
117
131
|
# @return [Array<Hash>] Error info
|
118
132
|
def errors
|
119
|
-
if data
|
133
|
+
if data.is_a?(Hash)
|
120
134
|
data[:errors] || []
|
121
135
|
else
|
122
136
|
[]
|
@@ -150,15 +164,13 @@ module Octokit
|
|
150
164
|
@data ||=
|
151
165
|
if (body = @response[:body]) && !body.empty?
|
152
166
|
if body.is_a?(String) &&
|
153
|
-
|
154
|
-
|
167
|
+
@response[:response_headers] &&
|
168
|
+
@response[:response_headers][:content_type] =~ /json/
|
155
169
|
|
156
170
|
Sawyer::Agent.serializer.decode(body)
|
157
171
|
else
|
158
172
|
body
|
159
173
|
end
|
160
|
-
else
|
161
|
-
nil
|
162
174
|
end
|
163
175
|
end
|
164
176
|
|
@@ -178,10 +190,10 @@ module Octokit
|
|
178
190
|
def response_error_summary
|
179
191
|
return nil unless data.is_a?(Hash) && !Array(data[:errors]).empty?
|
180
192
|
|
181
|
-
summary = "\nError summary:\n"
|
193
|
+
summary = +"\nError summary:\n"
|
182
194
|
summary << data[:errors].map do |error|
|
183
195
|
if error.is_a? Hash
|
184
|
-
error.map { |k,v| " #{k}: #{v}" }
|
196
|
+
error.map { |k, v| " #{k}: #{v}" }
|
185
197
|
else
|
186
198
|
" #{error}"
|
187
199
|
end
|
@@ -193,19 +205,21 @@ module Octokit
|
|
193
205
|
def build_error_message
|
194
206
|
return nil if @response.nil?
|
195
207
|
|
196
|
-
message =
|
197
|
-
message << redact_url(@response[:url].to_s)
|
208
|
+
message = +"#{@response[:method].to_s.upcase} "
|
209
|
+
message << "#{redact_url(@response[:url].to_s.dup)}: "
|
198
210
|
message << "#{@response[:status]} - "
|
199
|
-
message <<
|
200
|
-
message <<
|
201
|
-
message <<
|
211
|
+
message << response_message.to_s unless response_message.nil?
|
212
|
+
message << response_error.to_s unless response_error.nil?
|
213
|
+
message << response_error_summary.to_s unless response_error_summary.nil?
|
202
214
|
message << " // See: #{documentation_url}" unless documentation_url.nil?
|
203
215
|
message
|
204
216
|
end
|
205
217
|
|
206
218
|
def redact_url(url_string)
|
207
|
-
%w[client_secret access_token].each do |token|
|
208
|
-
|
219
|
+
%w[client_secret access_token api_key].each do |token|
|
220
|
+
if url_string.include? token
|
221
|
+
url_string.gsub!(/#{token}=\S+/, "#{token}=(redacted)")
|
222
|
+
end
|
209
223
|
end
|
210
224
|
url_string
|
211
225
|
end
|
@@ -223,10 +237,10 @@ module Octokit
|
|
223
237
|
# Raised when GitHub returns a 401 HTTP status code
|
224
238
|
# and headers include "X-GitHub-OTP"
|
225
239
|
class OneTimePasswordRequired < ClientError
|
226
|
-
|
227
|
-
OTP_DELIVERY_PATTERN = /required; (\w+)/i
|
240
|
+
# @private
|
241
|
+
OTP_DELIVERY_PATTERN = /required; (\w+)/i.freeze
|
228
242
|
|
229
|
-
|
243
|
+
# @private
|
230
244
|
def self.required_header(headers)
|
231
245
|
OTP_DELIVERY_PATTERN.match headers['X-GitHub-OTP'].to_s
|
232
246
|
end
|
@@ -306,6 +320,9 @@ module Octokit
|
|
306
320
|
# Raised when GitHub returns a 409 HTTP status code
|
307
321
|
class Conflict < ClientError; end
|
308
322
|
|
323
|
+
# Raised when GHES Manage return a 410 HTTP status code
|
324
|
+
class Deprecated < ClientError; end
|
325
|
+
|
309
326
|
# Raised when GitHub returns a 414 HTTP status code
|
310
327
|
class UnsupportedMediaType < ClientError; end
|
311
328
|
|
@@ -348,5 +365,5 @@ module Octokit
|
|
348
365
|
# Raised when a repository is created with an invalid format
|
349
366
|
class InvalidRepository < ArgumentError; end
|
350
367
|
|
351
|
-
RATE_LIMITED_ERRORS = [Octokit::TooManyRequests, Octokit::AbuseDetected]
|
368
|
+
RATE_LIMITED_ERRORS = [Octokit::TooManyRequests, Octokit::AbuseDetected].freeze
|
352
369
|
end
|
data/lib/octokit/gist.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module Octokit
|
3
4
|
# Class to parse and create Gist URLs
|
4
5
|
class Gist
|
5
|
-
|
6
6
|
# !@attribute id
|
7
7
|
# @return [String] Gist ID
|
8
8
|
attr_accessor :id
|
@@ -10,7 +10,7 @@ module Octokit
|
|
10
10
|
# Instantiate {Gist} object from Gist URL
|
11
11
|
# @ return [Gist]
|
12
12
|
def self.from_url(url)
|
13
|
-
Gist.new(URI.parse(url).path[1
|
13
|
+
Gist.new(URI.parse(url).path[1..])
|
14
14
|
end
|
15
15
|
|
16
16
|
def initialize(gist)
|
@@ -31,6 +31,5 @@ module Octokit
|
|
31
31
|
def url
|
32
32
|
"https://gist.github.com/#{@id}"
|
33
33
|
end
|
34
|
-
|
35
34
|
end
|
36
35
|
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Octokit
|
4
|
+
# Client for the Manage GitHub Enterprise Server API
|
5
|
+
class ManageGHESClient
|
6
|
+
# Methods for the Manage GitHub Enterprise Server API
|
7
|
+
#
|
8
|
+
# @see https://developer.github.com/v3/enterprise-admin/manage-ghes
|
9
|
+
module ManageAPI
|
10
|
+
# Get information about the maintenance status of the GHES instance
|
11
|
+
#
|
12
|
+
# @return [nil]
|
13
|
+
def maintenance_mode
|
14
|
+
conn = authenticated_client
|
15
|
+
|
16
|
+
@last_response = conn.get('/manage/v1/maintenance')
|
17
|
+
end
|
18
|
+
|
19
|
+
# Configure the maintenance mode of the GHES instance
|
20
|
+
#
|
21
|
+
# @param maintenance [Hash] A hash configuration of the maintenance mode status
|
22
|
+
# @return [nil]
|
23
|
+
def set_maintenance_mode(enabled, options = {})
|
24
|
+
conn = authenticated_client
|
25
|
+
|
26
|
+
options[:enabled] = enabled
|
27
|
+
@last_response = conn.post('/manage/v1/maintenance', options)
|
28
|
+
end
|
29
|
+
alias configure_maintenance_mode set_maintenance_mode
|
30
|
+
end
|
31
|
+
|
32
|
+
# Uploads a license for the first time
|
33
|
+
#
|
34
|
+
# @param license [String] The path to your .ghl license file.
|
35
|
+
#
|
36
|
+
# @return [nil]
|
37
|
+
def upload_license(license)
|
38
|
+
conn = authenticated_client
|
39
|
+
begin
|
40
|
+
conn.request :multipart
|
41
|
+
rescue Faraday::Error
|
42
|
+
raise Faraday::Error, <<~ERROR
|
43
|
+
The `faraday-multipart` gem is required to upload a license.
|
44
|
+
Please add `gem "faraday-multipart"` to your Gemfile.
|
45
|
+
ERROR
|
46
|
+
end
|
47
|
+
params = {}
|
48
|
+
params[:license] = Faraday::FilePart.new(license, 'binary')
|
49
|
+
params[:password] = @manage_ghes_password
|
50
|
+
@last_response = conn.post('/manage/v1/config/init', params, { 'Content-Type' => 'multipart/form-data' })
|
51
|
+
end
|
52
|
+
|
53
|
+
# Start a configuration process.
|
54
|
+
#
|
55
|
+
# @return [nil]
|
56
|
+
def start_configuration
|
57
|
+
conn = authenticated_client
|
58
|
+
@last_response = conn.post('/manage/v1/config/apply')
|
59
|
+
end
|
60
|
+
|
61
|
+
# Get information about the Enterprise installation
|
62
|
+
#
|
63
|
+
# @return [nil]
|
64
|
+
def config_status
|
65
|
+
conn = authenticated_client
|
66
|
+
@last_response = conn.get('/manage/v1/config/apply')
|
67
|
+
end
|
68
|
+
alias config_check config_status
|
69
|
+
|
70
|
+
# Get information about the Enterprise installation
|
71
|
+
#
|
72
|
+
# @return [nil]
|
73
|
+
def settings
|
74
|
+
conn = authenticated_client
|
75
|
+
@last_response = conn.get('/manage/v1/config/settings')
|
76
|
+
end
|
77
|
+
alias get_settings settings
|
78
|
+
|
79
|
+
# Modify the Enterprise settings
|
80
|
+
#
|
81
|
+
# @param settings [Hash] A hash configuration of the new settings
|
82
|
+
#
|
83
|
+
# @return [nil]
|
84
|
+
def edit_settings(settings)
|
85
|
+
conn = authenticated_client
|
86
|
+
@last_response = conn.put('/manage/v1/config/settings', settings.to_json.to_s)
|
87
|
+
end
|
88
|
+
|
89
|
+
def authorized_keys
|
90
|
+
conn = authenticated_client
|
91
|
+
@last_response = conn.get('/manage/v1/access/ssh')
|
92
|
+
end
|
93
|
+
alias get_authorized_keys authorized_keys
|
94
|
+
|
95
|
+
# Add an authorized SSH keys on the Enterprise install
|
96
|
+
#
|
97
|
+
# @param key Either the file path to a key, a File handler to the key, or the contents of the key itself
|
98
|
+
# @return [nil]
|
99
|
+
def add_authorized_key(key)
|
100
|
+
conn = authenticated_client
|
101
|
+
case key
|
102
|
+
when String
|
103
|
+
if File.exist?(key)
|
104
|
+
key = File.open(key, 'r')
|
105
|
+
content = key.read.strip
|
106
|
+
key.close
|
107
|
+
else
|
108
|
+
content = key
|
109
|
+
end
|
110
|
+
when File
|
111
|
+
content = key.read.strip
|
112
|
+
key.close
|
113
|
+
end
|
114
|
+
|
115
|
+
queries = {}
|
116
|
+
queries[:key] = content
|
117
|
+
@last_response = conn.post('/manage/v1/access/ssh', queries)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Removes an authorized SSH keys from the Enterprise install
|
121
|
+
#
|
122
|
+
# @param key Either the file path to a key, a File handler to the key, or the contents of the key itself
|
123
|
+
# @return [nil]
|
124
|
+
def remove_authorized_key(key)
|
125
|
+
conn = authenticated_client
|
126
|
+
case key
|
127
|
+
when String
|
128
|
+
if File.exist?(key)
|
129
|
+
key = File.open(key, 'r')
|
130
|
+
content = key.read.strip
|
131
|
+
key.close
|
132
|
+
else
|
133
|
+
content = key
|
134
|
+
end
|
135
|
+
when File
|
136
|
+
content = key.read.strip
|
137
|
+
key.close
|
138
|
+
end
|
139
|
+
|
140
|
+
queries = {}
|
141
|
+
queries[:key] = content
|
142
|
+
@last_response = conn.run_request(:delete, '/manage/v1/access/ssh', queries, nil)
|
143
|
+
end
|
144
|
+
alias delete_authorized_key remove_authorized_key
|
145
|
+
|
146
|
+
private
|
147
|
+
|
148
|
+
def basic_authenticated?
|
149
|
+
!!(@manage_ghes_username && @manage_ghes_password)
|
150
|
+
end
|
151
|
+
|
152
|
+
# If no username is provided, we assume root site admin should be used
|
153
|
+
def root_site_admin_assumed?
|
154
|
+
!@manage_ghes_username
|
155
|
+
end
|
156
|
+
|
157
|
+
def authenticated_client
|
158
|
+
@authenticated_client ||= Faraday.new(url: @manage_ghes_endpoint) do |c|
|
159
|
+
c.headers[:user_agent] = user_agent
|
160
|
+
c.request :json
|
161
|
+
c.response :json
|
162
|
+
c.adapter Faraday.default_adapter
|
163
|
+
|
164
|
+
if root_site_admin_assumed?
|
165
|
+
username = 'api_key'
|
166
|
+
elsif basic_authenticated?
|
167
|
+
username = @manage_ghes_username
|
168
|
+
end
|
169
|
+
c.request(*FARADAY_BASIC_AUTH_KEYS, username, @manage_ghes_password)
|
170
|
+
|
171
|
+
# Disabling SSL is essential for certain self-hosted Enterprise instances
|
172
|
+
c.ssl[:verify] = false if connection_options[:ssl] && !connection_options[:ssl][:verify]
|
173
|
+
|
174
|
+
c.use Octokit::Response::RaiseError
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'octokit/configurable'
|
4
|
+
require 'octokit/connection'
|
5
|
+
require 'octokit/warnable'
|
6
|
+
require 'octokit/manage_ghes_client/manage_ghes'
|
7
|
+
|
8
|
+
module Octokit
|
9
|
+
# ManageGHESClient is only meant to be used by GitHub Enterprise Server (GHES) operators
|
10
|
+
# and provides access to the Manage GHES API endpoints.
|
11
|
+
#
|
12
|
+
# @see Octokit::Client Use Octokit::Client for regular API use for GitHub
|
13
|
+
# and GitHub Enterprise.
|
14
|
+
# @see https://developer.github.com/v3/enterprise-admin/manage-ghes/
|
15
|
+
class ManageGHESClient
|
16
|
+
include Octokit::Configurable
|
17
|
+
include Octokit::Connection
|
18
|
+
include Octokit::Warnable
|
19
|
+
include Octokit::ManageGHESClient::ManageAPI
|
20
|
+
|
21
|
+
def initialize(options = {})
|
22
|
+
# Use options passed in, but fall back to module defaults
|
23
|
+
# rubocop:disable Style/HashEachMethods
|
24
|
+
#
|
25
|
+
# This may look like a `.keys.each` which should be replaced with `#each_key`, but
|
26
|
+
# this doesn't actually work, since `#keys` is just a method we've defined ourselves.
|
27
|
+
# The class doesn't fulfill the whole `Enumerable` contract.
|
28
|
+
Octokit::Configurable.keys.each do |key|
|
29
|
+
# rubocop:enable Style/HashEachMethods
|
30
|
+
instance_variable_set(:"@#{key}", options[key] || Octokit.instance_variable_get(:"@#{key}"))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def endpoint
|
37
|
+
manage_ghes_endpoint
|
38
|
+
end
|
39
|
+
|
40
|
+
# Set Manage GHES API endpoint
|
41
|
+
#
|
42
|
+
# @param value [String] Manage GHES API endpoint
|
43
|
+
def manage_ghes_endpoint=(value)
|
44
|
+
reset_agent
|
45
|
+
@manage_ghes_endpoint = value
|
46
|
+
end
|
47
|
+
|
48
|
+
# Set Manage GHES API username
|
49
|
+
#
|
50
|
+
# @param value [String] Manage GHES API username
|
51
|
+
def manage_ghes_username=(value)
|
52
|
+
reset_agent
|
53
|
+
@manage_ghes_username = value
|
54
|
+
end
|
55
|
+
|
56
|
+
# Set Manage GHES API password
|
57
|
+
#
|
58
|
+
# @param value [String] Manage GHES API password
|
59
|
+
def manage_ghes_password=(value)
|
60
|
+
reset_agent
|
61
|
+
@manage_ghes_password = value
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'faraday'
|
2
4
|
require 'set'
|
3
5
|
|
@@ -7,15 +9,13 @@ require 'set'
|
|
7
9
|
# https://github.com/lostisland/faraday_middleware/blob/138766e/lib/faraday_middleware/response/follow_redirects.rb
|
8
10
|
|
9
11
|
module Octokit
|
10
|
-
|
11
12
|
module Middleware
|
12
|
-
|
13
13
|
# Public: Exception thrown when the maximum amount of requests is exceeded.
|
14
14
|
class RedirectLimitReached < Faraday::ClientError
|
15
15
|
attr_reader :response
|
16
16
|
|
17
17
|
def initialize(response)
|
18
|
-
super
|
18
|
+
super("too many redirects; last one to: #{response['location']}")
|
19
19
|
@response = response
|
20
20
|
end
|
21
21
|
end
|
@@ -30,13 +30,13 @@ module Octokit
|
|
30
30
|
# doesn't support parallelism.
|
31
31
|
class FollowRedirects < Faraday::Middleware
|
32
32
|
# HTTP methods for which 30x redirects can be followed
|
33
|
-
ALLOWED_METHODS = Set.new [
|
33
|
+
ALLOWED_METHODS = Set.new %i[head options get post put patch delete]
|
34
34
|
|
35
35
|
# HTTP redirect status codes that this middleware implements
|
36
36
|
REDIRECT_CODES = Set.new [301, 302, 303, 307]
|
37
37
|
|
38
38
|
# Keys in env hash which will get cleared between requests
|
39
|
-
ENV_TO_CLEAR = Set.new [
|
39
|
+
ENV_TO_CLEAR = Set.new %i[status response response_headers]
|
40
40
|
|
41
41
|
# Default value for max redirects followed
|
42
42
|
FOLLOW_LIMIT = 3
|
@@ -44,7 +44,7 @@ module Octokit
|
|
44
44
|
# Regex that matches characters that need to be escaped in URLs, sans
|
45
45
|
# the "%" character which we assume already represents an escaped
|
46
46
|
# sequence.
|
47
|
-
URI_UNSAFE =
|
47
|
+
URI_UNSAFE = %r{[^\-_.!~*'()a-zA-Z\d;/?:@&=+$,\[\]%]}.freeze
|
48
48
|
|
49
49
|
# Public: Initialize the middleware.
|
50
50
|
#
|
@@ -64,7 +64,7 @@ module Octokit
|
|
64
64
|
private
|
65
65
|
|
66
66
|
def convert_to_get?(response)
|
67
|
-
|
67
|
+
!%i[head options].include?(response.env[:method]) &&
|
68
68
|
@convert_to_get.include?(response.status)
|
69
69
|
end
|
70
70
|
|
@@ -75,6 +75,7 @@ module Octokit
|
|
75
75
|
response.on_complete do |response_env|
|
76
76
|
if follow_redirect?(response_env, response)
|
77
77
|
raise(RedirectLimitReached, response) if follows.zero?
|
78
|
+
|
78
79
|
new_request_env = update_env(response_env, request_body, response)
|
79
80
|
response = perform_with_redirection(new_request_env, follows - 1)
|
80
81
|
end
|
@@ -84,12 +85,12 @@ module Octokit
|
|
84
85
|
|
85
86
|
def update_env(env, request_body, response)
|
86
87
|
original_url = env[:url]
|
87
|
-
env[:url] += safe_escape(response[
|
88
|
+
env[:url] += safe_escape(response['location'])
|
88
89
|
unless same_host?(original_url, env[:url])
|
89
90
|
# HACK: Faraday’s Authorization middlewares don’t touch the request if the `Authorization` header is set.
|
90
91
|
# This is a workaround to drop authentication info.
|
91
92
|
# See https://github.com/octokit/octokit.rb/pull/1359#issuecomment-925609697
|
92
|
-
env[:request_headers][
|
93
|
+
env[:request_headers]['Authorization'] = 'dummy'
|
93
94
|
end
|
94
95
|
|
95
96
|
if convert_to_get?(response)
|
@@ -125,9 +126,9 @@ module Octokit
|
|
125
126
|
# URI:HTTP using the `+` operator. Doesn't escape "%" characters so to not
|
126
127
|
# risk double-escaping.
|
127
128
|
def safe_escape(uri)
|
128
|
-
uri.to_s.gsub(URI_UNSAFE)
|
129
|
-
"
|
130
|
-
|
129
|
+
uri.to_s.gsub(URI_UNSAFE) do |match|
|
130
|
+
"%#{match.unpack('H2' * match.bytesize).join('%').upcase}"
|
131
|
+
end
|
131
132
|
end
|
132
133
|
end
|
133
134
|
end
|
data/lib/octokit/organization.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Octokit
|
2
4
|
# GitHub organization class to generate API path urls
|
3
5
|
class Organization
|
@@ -5,7 +7,7 @@ module Octokit
|
|
5
7
|
#
|
6
8
|
# @param org [String, Integer] GitHub organization login or id
|
7
9
|
# @return [String] Organization Api path
|
8
|
-
def self.path
|
10
|
+
def self.path(org)
|
9
11
|
case org
|
10
12
|
when String
|
11
13
|
"orgs/#{org}"
|
data/lib/octokit/rate_limit.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module Octokit
|
3
4
|
# Class for API Rate Limit info
|
4
5
|
#
|
5
6
|
# @!attribute [w] limit
|
@@ -13,17 +14,18 @@ module Octokit
|
|
13
14
|
#
|
14
15
|
# @see https://developer.github.com/v3/#rate-limiting
|
15
16
|
class RateLimit < Struct.new(:limit, :remaining, :resets_at, :resets_in)
|
16
|
-
|
17
17
|
# Get rate limit info from HTTP response
|
18
18
|
#
|
19
19
|
# @param response [#headers] HTTP response
|
20
20
|
# @return [RateLimit]
|
21
21
|
def self.from_response(response)
|
22
22
|
info = new
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
info.
|
23
|
+
headers = response.headers if response.respond_to?(:headers) && !response.headers.nil?
|
24
|
+
headers ||= response.response_headers if response.respond_to?(:response_headers) && !response.response_headers.nil?
|
25
|
+
if headers
|
26
|
+
info.limit = (headers['X-RateLimit-Limit'] || 1).to_i
|
27
|
+
info.remaining = (headers['X-RateLimit-Remaining'] || 1).to_i
|
28
|
+
info.resets_at = Time.at((headers['X-RateLimit-Reset'] || Time.now).to_i)
|
27
29
|
info.resets_in = [(info.resets_at - Time.now).to_i, 0].max
|
28
30
|
end
|
29
31
|
|
@@ -1,19 +1,18 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module Octokit
|
3
4
|
# Class to extract options from Ruby arguments for
|
4
5
|
# Repository-related methods
|
5
6
|
class RepoArguments < Arguments
|
6
|
-
|
7
7
|
# !@attribute [r] repo
|
8
8
|
# @return [Repository]
|
9
9
|
attr_reader :repo
|
10
10
|
|
11
11
|
def initialize(args)
|
12
|
-
arguments = super
|
12
|
+
arguments = super
|
13
13
|
@repo = arguments.shift
|
14
14
|
|
15
15
|
arguments
|
16
16
|
end
|
17
|
-
|
18
17
|
end
|
19
18
|
end
|