dependabot-common 0.242.1 → 0.243.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/dependabot/clients/azure.rb +112 -24
- data/lib/dependabot/clients/bitbucket.rb +1 -1
- data/lib/dependabot/credential.rb +40 -0
- data/lib/dependabot/dependency_group.rb +8 -2
- data/lib/dependabot/file_fetchers/base.rb +35 -3
- data/lib/dependabot/file_parsers/base.rb +4 -3
- data/lib/dependabot/file_updaters/artifact_updater.rb +1 -1
- data/lib/dependabot/file_updaters/base.rb +4 -3
- data/lib/dependabot/file_updaters/vendor_updater.rb +1 -1
- data/lib/dependabot/git_commit_checker.rb +3 -2
- data/lib/dependabot/git_metadata_fetcher.rb +3 -2
- data/lib/dependabot/metadata_finders/base/changelog_finder.rb +151 -56
- data/lib/dependabot/metadata_finders/base/changelog_pruner.rb +45 -14
- data/lib/dependabot/metadata_finders/base/commits_finder.rb +123 -53
- data/lib/dependabot/metadata_finders/base/release_finder.rb +84 -31
- data/lib/dependabot/metadata_finders/base.rb +4 -3
- data/lib/dependabot/pull_request_creator/azure.rb +1 -1
- data/lib/dependabot/pull_request_creator/branch_namer/solo_strategy.rb +2 -2
- data/lib/dependabot/pull_request_creator/labeler.rb +3 -2
- data/lib/dependabot/pull_request_creator/message_builder/issue_linker.rb +14 -6
- data/lib/dependabot/pull_request_creator/message_builder/metadata_presenter.rb +50 -9
- data/lib/dependabot/pull_request_creator/message_builder.rb +2 -2
- data/lib/dependabot/pull_request_creator/pr_name_prefixer.rb +164 -58
- data/lib/dependabot/pull_request_creator.rb +6 -5
- data/lib/dependabot/pull_request_updater.rb +3 -2
- data/lib/dependabot/security_advisory.rb +2 -2
- data/lib/dependabot/shared_helpers.rb +3 -2
- data/lib/dependabot/utils.rb +1 -13
- data/lib/dependabot/workspace/git.rb +1 -1
- data/lib/dependabot.rb +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c66b8233da2a6599d23a5c9a0db612e4225e7a1ef54aad500fd8861e9a98273
|
4
|
+
data.tar.gz: 682b44c5d4ec337dd4a29a80f029e1e84869b9434aea2619969b5079aecac51c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9e5c58e16b97382100d7b9b72dcc85ed38d48b8df82a9a1135d72ecda5deab0182a333a4e4ddbb1840b3d2b73c8cf36d3555c5a89af4bf780b76998fabc36404
|
7
|
+
data.tar.gz: 65b24a2eb7ab108af968ccfde8934e74e5a1bf584af8b517df75a369b48a515a3011c2c2e4392ffb57f6848b800d83c2eea82dac6d9820fa1bd45ec4b56af166
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "dependabot/shared_helpers"
|
@@ -7,6 +7,7 @@ require "sorbet-runtime"
|
|
7
7
|
|
8
8
|
module Dependabot
|
9
9
|
module Clients
|
10
|
+
# rubocop:disable Metrics/ClassLength
|
10
11
|
class Azure
|
11
12
|
extend T::Sig
|
12
13
|
|
@@ -24,12 +25,16 @@ module Dependabot
|
|
24
25
|
|
25
26
|
class TagsCreationForbidden < StandardError; end
|
26
27
|
|
27
|
-
RETRYABLE_ERRORS =
|
28
|
+
RETRYABLE_ERRORS = T.let(
|
29
|
+
[InternalServerError, BadGateway, ServiceNotAvailable].freeze,
|
30
|
+
T::Array[T.class_of(StandardError)]
|
31
|
+
)
|
28
32
|
|
29
33
|
#######################
|
30
34
|
# Constructor methods #
|
31
35
|
#######################
|
32
36
|
|
37
|
+
sig { params(source: Dependabot::Source, credentials: T::Array[Dependabot::Credential]).returns(Azure) }
|
33
38
|
def self.for_source(source:, credentials:)
|
34
39
|
credential =
|
35
40
|
credentials
|
@@ -43,15 +48,24 @@ module Dependabot
|
|
43
48
|
# Client #
|
44
49
|
##########
|
45
50
|
|
51
|
+
sig do
|
52
|
+
params(
|
53
|
+
source: Dependabot::Source,
|
54
|
+
credentials: T.nilable(Dependabot::Credential),
|
55
|
+
max_retries: T.nilable(Integer)
|
56
|
+
)
|
57
|
+
.void
|
58
|
+
end
|
46
59
|
def initialize(source, credentials, max_retries: 3)
|
47
60
|
@source = source
|
48
61
|
@credentials = credentials
|
49
|
-
@auth_header = auth_header_for(credentials&.fetch("token", nil))
|
50
|
-
@max_retries = max_retries || 3
|
62
|
+
@auth_header = T.let(auth_header_for(credentials&.fetch("token", nil)), T::Hash[String, String])
|
63
|
+
@max_retries = T.let(max_retries || 3, Integer)
|
51
64
|
end
|
52
65
|
|
66
|
+
sig { params(_repo: T.nilable(String), branch: String).returns(String) }
|
53
67
|
def fetch_commit(_repo, branch)
|
54
|
-
response = get(source.api_endpoint +
|
68
|
+
response = get(T.must(source.api_endpoint) +
|
55
69
|
source.organization + "/" + source.project +
|
56
70
|
"/_apis/git/repositories/" + source.unscoped_repo +
|
57
71
|
"/stats/branches?name=" + branch)
|
@@ -61,18 +75,26 @@ module Dependabot
|
|
61
75
|
JSON.parse(response.body).fetch("commit").fetch("commitId")
|
62
76
|
end
|
63
77
|
|
78
|
+
sig { params(_repo: String).returns(String) }
|
64
79
|
def fetch_default_branch(_repo)
|
65
|
-
response = get(source.api_endpoint +
|
80
|
+
response = get(T.must(source.api_endpoint) +
|
66
81
|
source.organization + "/" + source.project +
|
67
82
|
"/_apis/git/repositories/" + source.unscoped_repo)
|
68
83
|
|
69
84
|
JSON.parse(response.body).fetch("defaultBranch").gsub("refs/heads/", "")
|
70
85
|
end
|
71
86
|
|
87
|
+
sig do
|
88
|
+
params(
|
89
|
+
commit: T.nilable(String),
|
90
|
+
path: T.nilable(String)
|
91
|
+
)
|
92
|
+
.returns(T::Array[T::Hash[String, T.untyped]])
|
93
|
+
end
|
72
94
|
def fetch_repo_contents(commit = nil, path = nil)
|
73
95
|
tree = fetch_repo_contents_treeroot(commit, path)
|
74
96
|
|
75
|
-
response = get(source.api_endpoint +
|
97
|
+
response = get(T.must(source.api_endpoint) +
|
76
98
|
source.organization + "/" + source.project +
|
77
99
|
"/_apis/git/repositories/" + source.unscoped_repo +
|
78
100
|
"/trees/" + tree + "?recursive=false")
|
@@ -80,18 +102,19 @@ module Dependabot
|
|
80
102
|
JSON.parse(response.body).fetch("treeEntries")
|
81
103
|
end
|
82
104
|
|
105
|
+
sig { params(commit: T.nilable(String), path: T.nilable(String)).returns(String) }
|
83
106
|
def fetch_repo_contents_treeroot(commit = nil, path = nil)
|
84
107
|
actual_path = path
|
85
108
|
actual_path = "/" if path.to_s.empty?
|
86
109
|
|
87
|
-
tree_url = source.api_endpoint +
|
110
|
+
tree_url = T.must(source.api_endpoint) +
|
88
111
|
source.organization + "/" + source.project +
|
89
112
|
"/_apis/git/repositories/" + source.unscoped_repo +
|
90
|
-
"/items?path=" + actual_path
|
113
|
+
"/items?path=" + T.must(actual_path)
|
91
114
|
|
92
115
|
unless commit.to_s.empty?
|
93
116
|
tree_url += "&versionDescriptor.versionType=commit" \
|
94
|
-
"&versionDescriptor.version=" + commit
|
117
|
+
"&versionDescriptor.version=" + T.must(commit)
|
95
118
|
end
|
96
119
|
|
97
120
|
tree_response = get(tree_url)
|
@@ -99,8 +122,9 @@ module Dependabot
|
|
99
122
|
JSON.parse(tree_response.body).fetch("objectId")
|
100
123
|
end
|
101
124
|
|
125
|
+
sig { params(commit: String, path: String).returns(String) }
|
102
126
|
def fetch_file_contents(commit, path)
|
103
|
-
response = get(source.api_endpoint +
|
127
|
+
response = get(T.must(source.api_endpoint) +
|
104
128
|
source.organization + "/" + source.project +
|
105
129
|
"/_apis/git/repositories/" + source.unscoped_repo +
|
106
130
|
"/items?path=" + path +
|
@@ -110,21 +134,23 @@ module Dependabot
|
|
110
134
|
response.body
|
111
135
|
end
|
112
136
|
|
137
|
+
sig { params(branch_name: T.nilable(String)).returns(T::Array[T::Hash[String, T.untyped]]) }
|
113
138
|
def commits(branch_name = nil)
|
114
|
-
commits_url = source.api_endpoint +
|
139
|
+
commits_url = T.must(source.api_endpoint) +
|
115
140
|
source.organization + "/" + source.project +
|
116
141
|
"/_apis/git/repositories/" + source.unscoped_repo +
|
117
142
|
"/commits"
|
118
143
|
|
119
|
-
commits_url += "?searchCriteria.itemVersion.version=" + branch_name unless branch_name.to_s.empty?
|
144
|
+
commits_url += "?searchCriteria.itemVersion.version=" + T.must(branch_name) unless branch_name.to_s.empty?
|
120
145
|
|
121
146
|
response = get(commits_url)
|
122
147
|
|
123
148
|
JSON.parse(response.body).fetch("value")
|
124
149
|
end
|
125
150
|
|
151
|
+
sig { params(branch_name: String).returns(T.nilable(T::Hash[String, T.untyped])) }
|
126
152
|
def branch(branch_name)
|
127
|
-
response = get(source.api_endpoint +
|
153
|
+
response = get(T.must(source.api_endpoint) +
|
128
154
|
source.organization + "/" + source.project +
|
129
155
|
"/_apis/git/repositories/" + source.unscoped_repo +
|
130
156
|
"/refs?filter=heads/" + branch_name)
|
@@ -132,8 +158,9 @@ module Dependabot
|
|
132
158
|
JSON.parse(response.body).fetch("value").first
|
133
159
|
end
|
134
160
|
|
161
|
+
sig { params(source_branch: String, target_branch: String).returns(T::Array[T::Hash[String, T.untyped]]) }
|
135
162
|
def pull_requests(source_branch, target_branch)
|
136
|
-
response = get(source.api_endpoint +
|
163
|
+
response = get(T.must(source.api_endpoint) +
|
137
164
|
source.organization + "/" + source.project +
|
138
165
|
"/_apis/git/repositories/" + source.unscoped_repo +
|
139
166
|
"/pullrequests?searchCriteria.status=all" \
|
@@ -143,6 +170,16 @@ module Dependabot
|
|
143
170
|
JSON.parse(response.body).fetch("value")
|
144
171
|
end
|
145
172
|
|
173
|
+
sig do
|
174
|
+
params(
|
175
|
+
branch_name: String,
|
176
|
+
base_commit: String,
|
177
|
+
commit_message: String,
|
178
|
+
files: T::Array[Dependabot::DependencyFile],
|
179
|
+
author_details: T.nilable(T::Hash[String, String])
|
180
|
+
)
|
181
|
+
.returns(T.untyped)
|
182
|
+
end
|
146
183
|
def create_commit(branch_name, base_commit, commit_message, files,
|
147
184
|
author_details)
|
148
185
|
content = {
|
@@ -158,7 +195,7 @@ module Dependabot
|
|
158
195
|
changeType: "edit",
|
159
196
|
item: { path: file.path },
|
160
197
|
newContent: {
|
161
|
-
content: Base64.encode64(file.content),
|
198
|
+
content: Base64.encode64(T.must(file.content)),
|
162
199
|
contentType: "base64encoded"
|
163
200
|
}
|
164
201
|
}
|
@@ -167,12 +204,25 @@ module Dependabot
|
|
167
204
|
]
|
168
205
|
}
|
169
206
|
|
170
|
-
post(source.api_endpoint + source.organization + "/" + source.project +
|
207
|
+
post(T.must(source.api_endpoint) + source.organization + "/" + source.project +
|
171
208
|
"/_apis/git/repositories/" + source.unscoped_repo +
|
172
209
|
"/pushes?api-version=5.0", content.to_json)
|
173
210
|
end
|
174
211
|
|
175
212
|
# rubocop:disable Metrics/ParameterLists
|
213
|
+
sig do
|
214
|
+
params(
|
215
|
+
pr_name: String,
|
216
|
+
source_branch: String,
|
217
|
+
target_branch: String,
|
218
|
+
pr_description: String,
|
219
|
+
labels: T::Array[String],
|
220
|
+
reviewers: T.nilable(T::Array[String]),
|
221
|
+
assignees: T.nilable(T::Array[String]),
|
222
|
+
work_item: T.nilable(Integer)
|
223
|
+
)
|
224
|
+
.returns(T.untyped)
|
225
|
+
end
|
176
226
|
def create_pull_request(pr_name, source_branch, target_branch,
|
177
227
|
pr_description, labels,
|
178
228
|
reviewers = nil, assignees = nil, work_item = nil)
|
@@ -187,12 +237,25 @@ module Dependabot
|
|
187
237
|
workItemRefs: [{ id: work_item }]
|
188
238
|
}
|
189
239
|
|
190
|
-
post(source.api_endpoint +
|
240
|
+
post(T.must(source.api_endpoint) +
|
191
241
|
source.organization + "/" + source.project +
|
192
242
|
"/_apis/git/repositories/" + source.unscoped_repo +
|
193
243
|
"/pullrequests?api-version=5.0", content.to_json)
|
194
244
|
end
|
195
245
|
|
246
|
+
sig do
|
247
|
+
params(
|
248
|
+
pull_request_id: Integer,
|
249
|
+
auto_complete_set_by: String,
|
250
|
+
merge_commit_message: String,
|
251
|
+
delete_source_branch: T::Boolean,
|
252
|
+
squash_merge: T::Boolean,
|
253
|
+
merge_strategy: String,
|
254
|
+
trans_work_items: T::Boolean,
|
255
|
+
ignore_config_ids: T::Array[String]
|
256
|
+
)
|
257
|
+
.returns(T.untyped)
|
258
|
+
end
|
196
259
|
def autocomplete_pull_request(pull_request_id, auto_complete_set_by, merge_commit_message,
|
197
260
|
delete_source_branch = true, squash_merge = true, merge_strategy = "squash",
|
198
261
|
trans_work_items = true, ignore_config_ids = [])
|
@@ -211,7 +274,7 @@ module Dependabot
|
|
211
274
|
}
|
212
275
|
}
|
213
276
|
|
214
|
-
response = patch(source.api_endpoint +
|
277
|
+
response = patch(T.must(source.api_endpoint) +
|
215
278
|
source.organization + "/" + source.project +
|
216
279
|
"/_apis/git/repositories/" + source.unscoped_repo +
|
217
280
|
"/pullrequests/" + pull_request_id.to_s + "?api-version=5.1", content.to_json)
|
@@ -219,14 +282,16 @@ module Dependabot
|
|
219
282
|
JSON.parse(response.body)
|
220
283
|
end
|
221
284
|
|
285
|
+
sig { params(pull_request_id: String).returns(T::Hash[String, T.untyped]) }
|
222
286
|
def pull_request(pull_request_id)
|
223
|
-
response = get(source.api_endpoint +
|
287
|
+
response = get(T.must(source.api_endpoint) +
|
224
288
|
source.organization + "/" + source.project +
|
225
289
|
"/_apis/git/pullrequests/" + pull_request_id)
|
226
290
|
|
227
291
|
JSON.parse(response.body)
|
228
292
|
end
|
229
293
|
|
294
|
+
sig { params(branch_name: String, old_commit: String, new_commit: String).returns(T::Hash[String, T.untyped]) }
|
230
295
|
def update_ref(branch_name, old_commit, new_commit)
|
231
296
|
content = [
|
232
297
|
{
|
@@ -236,7 +301,7 @@ module Dependabot
|
|
236
301
|
}
|
237
302
|
]
|
238
303
|
|
239
|
-
response = post(source.api_endpoint + source.organization + "/" + source.project +
|
304
|
+
response = post(T.must(source.api_endpoint) + source.organization + "/" + source.project +
|
240
305
|
"/_apis/git/repositories/" + source.unscoped_repo +
|
241
306
|
"/refs?api-version=5.0", content.to_json)
|
242
307
|
|
@@ -244,8 +309,15 @@ module Dependabot
|
|
244
309
|
end
|
245
310
|
# rubocop:enable Metrics/ParameterLists
|
246
311
|
|
312
|
+
sig do
|
313
|
+
params(
|
314
|
+
previous_tag: T.nilable(String), new_tag: T.nilable(String),
|
315
|
+
type: String
|
316
|
+
)
|
317
|
+
.returns(T::Array[T::Hash[String, T.untyped]])
|
318
|
+
end
|
247
319
|
def compare(previous_tag, new_tag, type)
|
248
|
-
response = get(source.api_endpoint +
|
320
|
+
response = get(T.must(source.api_endpoint) +
|
249
321
|
source.organization + "/" + source.project +
|
250
322
|
"/_apis/git/repositories/" + source.unscoped_repo +
|
251
323
|
"/commits?searchCriteria.itemVersion.versionType=#{type}" \
|
@@ -311,7 +383,7 @@ module Dependabot
|
|
311
383
|
raise Unauthorized if response&.status == 401
|
312
384
|
|
313
385
|
if response&.status == 403
|
314
|
-
raise TagsCreationForbidden if tags_creation_forbidden?(response)
|
386
|
+
raise TagsCreationForbidden if tags_creation_forbidden?(T.must(response))
|
315
387
|
|
316
388
|
raise Forbidden
|
317
389
|
end
|
@@ -354,7 +426,8 @@ module Dependabot
|
|
354
426
|
|
355
427
|
private
|
356
428
|
|
357
|
-
|
429
|
+
sig { params(blk: T.proc.void).void }
|
430
|
+
def retry_connection_failures(&blk) # rubocop:disable Lint/UnusedMethodArgument
|
358
431
|
retry_attempt = 0
|
359
432
|
|
360
433
|
begin
|
@@ -365,6 +438,7 @@ module Dependabot
|
|
365
438
|
end
|
366
439
|
end
|
367
440
|
|
441
|
+
sig { params(token: T.nilable(String)).returns(T::Hash[String, String]) }
|
368
442
|
def auth_header_for(token)
|
369
443
|
return {} unless token
|
370
444
|
|
@@ -379,6 +453,7 @@ module Dependabot
|
|
379
453
|
end
|
380
454
|
end
|
381
455
|
|
456
|
+
sig { params(response: Excon::Response).returns(T::Boolean) }
|
382
457
|
def tags_creation_forbidden?(response)
|
383
458
|
return false if response.body.empty?
|
384
459
|
|
@@ -386,6 +461,13 @@ module Dependabot
|
|
386
461
|
message&.include?("TF401289")
|
387
462
|
end
|
388
463
|
|
464
|
+
sig do
|
465
|
+
params(
|
466
|
+
reviewers: T.nilable(T::Array[String]),
|
467
|
+
assignees: T.nilable(T::Array[String])
|
468
|
+
)
|
469
|
+
.returns(T::Array[T::Hash[Symbol, T.untyped]])
|
470
|
+
end
|
389
471
|
def pr_reviewers(reviewers, assignees)
|
390
472
|
return [] unless reviewers || assignees
|
391
473
|
|
@@ -393,9 +475,15 @@ module Dependabot
|
|
393
475
|
pr_reviewers + (assignees&.map { |r_id| { id: r_id, isRequired: false } } || [])
|
394
476
|
end
|
395
477
|
|
478
|
+
sig { returns(T::Hash[String, String]) }
|
396
479
|
attr_reader :auth_header
|
480
|
+
|
481
|
+
sig { returns(T.nilable(Dependabot::Credential)) }
|
397
482
|
attr_reader :credentials
|
483
|
+
|
484
|
+
sig { returns(Dependabot::Source) }
|
398
485
|
attr_reader :source
|
399
486
|
end
|
487
|
+
# rubocop:enable Metrics/ClassLength
|
400
488
|
end
|
401
489
|
end
|
@@ -282,7 +282,7 @@ module Dependabot
|
|
282
282
|
#
|
283
283
|
# With POST (for endpoints that provide POST methods for long query parameters)
|
284
284
|
# response = post(url, body)
|
285
|
-
# first_page = JSON.parse(
|
285
|
+
# first_page = JSON.parse(response.body)
|
286
286
|
# paginate(first_page)
|
287
287
|
def paginate(page)
|
288
288
|
Enumerator.new do |yielder|
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
6
|
+
module Dependabot
|
7
|
+
class Credential
|
8
|
+
extend T::Sig
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
def_delegators :@credential, :fetch, :keys, :[]=, :delete, :slice, :values, :entries
|
12
|
+
|
13
|
+
sig { params(credential: T::Hash[String, T.any(T::Boolean, String)]).void }
|
14
|
+
def initialize(credential)
|
15
|
+
@replaces_base = T.let(credential["replaces-base"] == true, T::Boolean)
|
16
|
+
credential.delete("replaces-base")
|
17
|
+
@credential = T.let(T.unsafe(credential), T::Hash[String, String])
|
18
|
+
end
|
19
|
+
|
20
|
+
sig { returns(T::Boolean) }
|
21
|
+
def replaces_base?
|
22
|
+
@replaces_base
|
23
|
+
end
|
24
|
+
|
25
|
+
sig { params(key: String).returns(T.nilable(String)) }
|
26
|
+
def [](key)
|
27
|
+
@credential[key]
|
28
|
+
end
|
29
|
+
|
30
|
+
sig { params(other: Credential).returns(Credential) }
|
31
|
+
def merge(other)
|
32
|
+
Credential.new(@credential.merge(other.to_h))
|
33
|
+
end
|
34
|
+
|
35
|
+
sig { returns(T::Hash[String, String]) }
|
36
|
+
def to_h
|
37
|
+
@credential
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -22,15 +22,21 @@ module Dependabot
|
|
22
22
|
sig { returns(T::Array[Dependabot::Dependency]) }
|
23
23
|
attr_reader :dependencies
|
24
24
|
|
25
|
+
sig { returns(String) }
|
26
|
+
attr_reader :applies_to
|
27
|
+
|
25
28
|
sig do
|
26
29
|
params(
|
27
30
|
name: String,
|
28
|
-
rules: T::Hash[String, T.untyped]
|
31
|
+
rules: T::Hash[String, T.untyped],
|
32
|
+
applies_to: T.nilable(String)
|
29
33
|
)
|
30
34
|
.void
|
31
35
|
end
|
32
|
-
def initialize(name:, rules:)
|
36
|
+
def initialize(name:, rules:, applies_to: "version-updates")
|
33
37
|
@name = name
|
38
|
+
# For backwards compatibility, if no applies_to is provided, default to "version-updates"
|
39
|
+
@applies_to = T.let(applies_to || "version-updates", String)
|
34
40
|
@rules = rules
|
35
41
|
@dependencies = T.let([], T::Array[Dependabot::Dependency])
|
36
42
|
end
|
@@ -7,6 +7,7 @@ require "dependabot/config"
|
|
7
7
|
require "dependabot/dependency_file"
|
8
8
|
require "dependabot/source"
|
9
9
|
require "dependabot/errors"
|
10
|
+
require "dependabot/credential"
|
10
11
|
require "dependabot/clients/azure"
|
11
12
|
require "dependabot/clients/codecommit"
|
12
13
|
require "dependabot/clients/github_with_retries"
|
@@ -26,7 +27,7 @@ module Dependabot
|
|
26
27
|
sig { returns(Dependabot::Source) }
|
27
28
|
attr_reader :source
|
28
29
|
|
29
|
-
sig { returns(T::Array[
|
30
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
30
31
|
attr_reader :credentials
|
31
32
|
|
32
33
|
sig { returns(T.nilable(String)) }
|
@@ -51,6 +52,24 @@ module Dependabot
|
|
51
52
|
GIT_SUBMODULE_CLONE_ERROR =
|
52
53
|
/^fatal: clone of '(?<url>.*)' into submodule path '.*' failed$/
|
53
54
|
GIT_SUBMODULE_ERROR_REGEX = /(#{GIT_SUBMODULE_INACCESSIBLE_ERROR})|(#{GIT_SUBMODULE_CLONE_ERROR})/
|
55
|
+
GIT_RETRYABLE_ERRORS =
|
56
|
+
T.let(
|
57
|
+
[
|
58
|
+
/remote error: Internal Server Error/,
|
59
|
+
/fatal: Couldn\'t find remote ref/,
|
60
|
+
%r{git fetch_pack: expected ACK/NAK, got},
|
61
|
+
/protocol error: bad pack header/,
|
62
|
+
/The remote end hung up unexpectedly/,
|
63
|
+
/TLS packet with unexpected length was received/,
|
64
|
+
/RPC failed; result=\d+, HTTP code = \d+/,
|
65
|
+
/Connection timed out/,
|
66
|
+
/Connection reset by peer/,
|
67
|
+
/Unable to look up/,
|
68
|
+
/Couldn\'t resolve host/,
|
69
|
+
/The requested URL returned error: (429|5\d{2})/
|
70
|
+
].freeze,
|
71
|
+
T::Array[Regexp]
|
72
|
+
)
|
54
73
|
|
55
74
|
sig { overridable.params(filenames: T::Array[String]).returns(T::Boolean) }
|
56
75
|
def self.required_files_in?(filenames)
|
@@ -76,7 +95,7 @@ module Dependabot
|
|
76
95
|
sig do
|
77
96
|
params(
|
78
97
|
source: Dependabot::Source,
|
79
|
-
credentials: T::Array[
|
98
|
+
credentials: T::Array[Dependabot::Credential],
|
80
99
|
repo_contents_path: T.nilable(String),
|
81
100
|
options: T::Hash[String, String]
|
82
101
|
)
|
@@ -500,7 +519,7 @@ module Dependabot
|
|
500
519
|
repo_path = File.join(clone_repo_contents, relative_path)
|
501
520
|
return [] unless Dir.exist?(repo_path)
|
502
521
|
|
503
|
-
Dir.entries(repo_path).filter_map do |name|
|
522
|
+
Dir.entries(repo_path).sort.filter_map do |name|
|
504
523
|
next if name == "." || name == ".."
|
505
524
|
|
506
525
|
absolute_path = File.join(repo_path, name)
|
@@ -757,6 +776,7 @@ module Dependabot
|
|
757
776
|
# rubocop:disable Metrics/MethodLength
|
758
777
|
# rubocop:disable Metrics/PerceivedComplexity
|
759
778
|
# rubocop:disable Metrics/BlockLength
|
779
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
760
780
|
sig { params(target_directory: T.nilable(String)).returns(String) }
|
761
781
|
def _clone_repo_contents(target_directory:)
|
762
782
|
SharedHelpers.with_git_configured(credentials: credentials) do
|
@@ -777,6 +797,7 @@ module Dependabot
|
|
777
797
|
clone_options << " --branch #{source.branch} --single-branch" if source.branch
|
778
798
|
|
779
799
|
submodule_cloning_failed = false
|
800
|
+
retries = 0
|
780
801
|
begin
|
781
802
|
SharedHelpers.run_shell_command(
|
782
803
|
<<~CMD
|
@@ -786,6 +807,16 @@ module Dependabot
|
|
786
807
|
|
787
808
|
@submodules = find_submodules(path) if recurse_submodules_when_cloning?
|
788
809
|
rescue SharedHelpers::HelperSubprocessFailed => e
|
810
|
+
if GIT_RETRYABLE_ERRORS.any? { |error| error.match?(e.message) } && retries < 5
|
811
|
+
retries += 1
|
812
|
+
# 3, 6, 12, 24, 48, ...
|
813
|
+
sleep_seconds = (2 ^ (retries - 1)) * 3
|
814
|
+
Dependabot.logger.warn(
|
815
|
+
"Failed to clone repo #{source.url} due to #{e.message}. Retrying in #{sleep_seconds} seconds..."
|
816
|
+
)
|
817
|
+
sleep(sleep_seconds)
|
818
|
+
retry
|
819
|
+
end
|
789
820
|
raise unless e.message.match(GIT_SUBMODULE_ERROR_REGEX) && e.message.downcase.include?("submodule")
|
790
821
|
|
791
822
|
submodule_cloning_failed = true
|
@@ -831,6 +862,7 @@ module Dependabot
|
|
831
862
|
# rubocop:enable Metrics/MethodLength
|
832
863
|
# rubocop:enable Metrics/PerceivedComplexity
|
833
864
|
# rubocop:enable Metrics/BlockLength
|
865
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
834
866
|
|
835
867
|
sig { params(str: String).returns(String) }
|
836
868
|
def decode_binary_string(str)
|
@@ -2,6 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "sorbet-runtime"
|
5
|
+
require "dependabot/credential"
|
5
6
|
|
6
7
|
module Dependabot
|
7
8
|
module FileParsers
|
@@ -17,7 +18,7 @@ module Dependabot
|
|
17
18
|
sig { returns(T.nilable(String)) }
|
18
19
|
attr_reader :repo_contents_path
|
19
20
|
|
20
|
-
sig { returns(T::Array[
|
21
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
21
22
|
attr_reader :credentials
|
22
23
|
|
23
24
|
sig { returns(T.nilable(Dependabot::Source)) }
|
@@ -31,7 +32,7 @@ module Dependabot
|
|
31
32
|
dependency_files: T::Array[Dependabot::DependencyFile],
|
32
33
|
source: T.nilable(Dependabot::Source),
|
33
34
|
repo_contents_path: T.nilable(String),
|
34
|
-
credentials: T::Array[
|
35
|
+
credentials: T::Array[Dependabot::Credential],
|
35
36
|
reject_external_code: T::Boolean,
|
36
37
|
options: T::Hash[Symbol, T.untyped]
|
37
38
|
)
|
@@ -49,7 +50,7 @@ module Dependabot
|
|
49
50
|
check_required_files
|
50
51
|
end
|
51
52
|
|
52
|
-
sig { abstract.returns(Dependabot::
|
53
|
+
sig { abstract.returns(T::Array[Dependabot::Dependency]) }
|
53
54
|
def parse; end
|
54
55
|
|
55
56
|
private
|
@@ -4,7 +4,7 @@
|
|
4
4
|
require "sorbet-runtime"
|
5
5
|
require "dependabot/dependency_file"
|
6
6
|
|
7
|
-
# This class provides a utility to check for
|
7
|
+
# This class provides a utility to check for arbitrary modified files within a
|
8
8
|
# git directory that need to be wrapped as Dependabot::DependencyFile object
|
9
9
|
# and returned as along with anything managed by the FileUpdater itself.
|
10
10
|
module Dependabot
|
@@ -2,6 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "sorbet-runtime"
|
5
|
+
require "dependabot/credential"
|
5
6
|
|
6
7
|
module Dependabot
|
7
8
|
module FileUpdaters
|
@@ -19,13 +20,13 @@ module Dependabot
|
|
19
20
|
sig { returns(T.nilable(String)) }
|
20
21
|
attr_reader :repo_contents_path
|
21
22
|
|
22
|
-
sig { returns(T::Array[
|
23
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
23
24
|
attr_reader :credentials
|
24
25
|
|
25
26
|
sig { returns(T::Hash[Symbol, T.untyped]) }
|
26
27
|
attr_reader :options
|
27
28
|
|
28
|
-
sig { overridable.returns(
|
29
|
+
sig { overridable.returns(T::Array[Regexp]) }
|
29
30
|
def self.updated_files_regex
|
30
31
|
raise NotImplementedError
|
31
32
|
end
|
@@ -34,7 +35,7 @@ module Dependabot
|
|
34
35
|
params(
|
35
36
|
dependencies: T::Array[Dependabot::Dependency],
|
36
37
|
dependency_files: T::Array[Dependabot::DependencyFile],
|
37
|
-
credentials: T::Array[
|
38
|
+
credentials: T::Array[Dependabot::Credential],
|
38
39
|
repo_contents_path: T.nilable(String),
|
39
40
|
options: T::Hash[Symbol, T.untyped]
|
40
41
|
).void
|
@@ -17,7 +17,7 @@ module Dependabot
|
|
17
17
|
extend T::Sig
|
18
18
|
extend T::Helpers
|
19
19
|
|
20
|
-
# This provides backwards
|
20
|
+
# This provides backwards compatibility for anyone who used this class
|
21
21
|
# before the base ArtifactUpdater class was introduced and aligns the
|
22
22
|
# method's public signatures with it's special-case domain.
|
23
23
|
sig { params(repo_contents_path: T.nilable(String), vendor_dir: T.nilable(String)).void }
|
@@ -12,6 +12,7 @@ require "dependabot/errors"
|
|
12
12
|
require "dependabot/utils"
|
13
13
|
require "dependabot/source"
|
14
14
|
require "dependabot/dependency"
|
15
|
+
require "dependabot/credential"
|
15
16
|
require "dependabot/git_metadata_fetcher"
|
16
17
|
module Dependabot
|
17
18
|
# rubocop:disable Metrics/ClassLength
|
@@ -29,7 +30,7 @@ module Dependabot
|
|
29
30
|
sig do
|
30
31
|
params(
|
31
32
|
dependency: Dependabot::Dependency,
|
32
|
-
credentials: T::Array[
|
33
|
+
credentials: T::Array[Dependabot::Credential],
|
33
34
|
ignored_versions: T::Array[String],
|
34
35
|
raise_on_ignored: T::Boolean,
|
35
36
|
consider_version_branches_pinned: T::Boolean,
|
@@ -226,7 +227,7 @@ module Dependabot
|
|
226
227
|
sig { returns(Dependabot::Dependency) }
|
227
228
|
attr_reader :dependency
|
228
229
|
|
229
|
-
sig { returns(T::Array[
|
230
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
230
231
|
attr_reader :credentials
|
231
232
|
|
232
233
|
sig { returns(T::Array[String]) }
|
@@ -7,6 +7,7 @@ require "sorbet-runtime"
|
|
7
7
|
|
8
8
|
require "dependabot/errors"
|
9
9
|
require "dependabot/git_ref"
|
10
|
+
require "dependabot/credential"
|
10
11
|
|
11
12
|
module Dependabot
|
12
13
|
class GitMetadataFetcher
|
@@ -17,7 +18,7 @@ module Dependabot
|
|
17
18
|
sig do
|
18
19
|
params(
|
19
20
|
url: String,
|
20
|
-
credentials: T::Array[
|
21
|
+
credentials: T::Array[Dependabot::Credential]
|
21
22
|
)
|
22
23
|
.void
|
23
24
|
end
|
@@ -97,7 +98,7 @@ module Dependabot
|
|
97
98
|
sig { returns(String) }
|
98
99
|
attr_reader :url
|
99
100
|
|
100
|
-
sig { returns(T::Array[
|
101
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
101
102
|
attr_reader :credentials
|
102
103
|
|
103
104
|
sig { params(uri: String).returns(String) }
|