dependabot-common 0.244.0 → 0.246.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/lib/dependabot/clients/bitbucket.rb +113 -5
- data/lib/dependabot/clients/bitbucket_with_retries.rb +34 -10
- data/lib/dependabot/clients/codecommit.rb +107 -12
- data/lib/dependabot/clients/github_with_retries.rb +61 -19
- data/lib/dependabot/clients/gitlab_with_retries.rb +60 -7
- data/lib/dependabot/dependency.rb +1 -1
- data/lib/dependabot/errors.rb +8 -2
- data/lib/dependabot/git_commit_checker.rb +4 -3
- data/lib/dependabot/metadata_finders/base/changelog_finder.rb +1 -1
- data/lib/dependabot/metadata_finders/base/commits_finder.rb +1 -1
- data/lib/dependabot/metadata_finders/base/release_finder.rb +1 -1
- data/lib/dependabot/pull_request_creator/azure.rb +80 -9
- data/lib/dependabot/pull_request_creator/bitbucket.rb +73 -9
- data/lib/dependabot/pull_request_creator/codecommit.rb +96 -25
- data/lib/dependabot/pull_request_creator/github.rb +162 -49
- data/lib/dependabot/pull_request_creator/gitlab.rb +109 -21
- data/lib/dependabot/pull_request_creator/message_builder.rb +239 -89
- data/lib/dependabot/pull_request_creator/pr_name_prefixer.rb +11 -9
- data/lib/dependabot/pull_request_creator.rb +32 -27
- data/lib/dependabot/pull_request_updater/azure.rb +75 -11
- data/lib/dependabot/pull_request_updater/github.rb +89 -28
- data/lib/dependabot/pull_request_updater/gitlab.rb +61 -12
- data/lib/dependabot/pull_request_updater.rb +1 -1
- data/lib/dependabot/shared_helpers.rb +19 -1
- data/lib/dependabot/update_checkers/base.rb +121 -31
- data/lib/dependabot.rb +1 -1
- metadata +3 -3
@@ -1,7 +1,9 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "pathname"
|
5
|
+
require "sorbet-runtime"
|
6
|
+
|
5
7
|
require "dependabot/clients/github_with_retries"
|
6
8
|
require "dependabot/clients/gitlab_with_retries"
|
7
9
|
require "dependabot/dependency_group"
|
@@ -15,19 +17,72 @@ module Dependabot
|
|
15
17
|
class PullRequestCreator
|
16
18
|
# MessageBuilder builds PR message for a dependency update
|
17
19
|
class MessageBuilder
|
20
|
+
extend T::Sig
|
21
|
+
|
18
22
|
require_relative "message_builder/metadata_presenter"
|
19
23
|
require_relative "message_builder/issue_linker"
|
20
24
|
require_relative "message_builder/link_and_mention_sanitizer"
|
21
25
|
require_relative "pr_name_prefixer"
|
22
26
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
27
|
+
sig { returns(Dependabot::Source) }
|
28
|
+
attr_reader :source
|
29
|
+
|
30
|
+
sig { returns(T::Array[Dependabot::Dependency]) }
|
31
|
+
attr_reader :dependencies
|
32
|
+
|
33
|
+
sig { returns(T::Array[Dependabot::DependencyFile]) }
|
34
|
+
attr_reader :files
|
35
|
+
|
36
|
+
sig { returns(T::Array[Dependabot::Credential]) }
|
37
|
+
attr_reader :credentials
|
38
|
+
|
39
|
+
sig { returns(T.nilable(String)) }
|
40
|
+
attr_reader :pr_message_header
|
41
|
+
|
42
|
+
sig { returns(T.nilable(String)) }
|
43
|
+
attr_reader :pr_message_footer
|
44
|
+
|
45
|
+
sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
46
|
+
attr_reader :commit_message_options
|
47
|
+
|
48
|
+
sig { returns(T::Hash[String, T.untyped]) }
|
49
|
+
attr_reader :vulnerabilities_fixed
|
50
|
+
|
51
|
+
sig { returns(T.nilable(String)) }
|
52
|
+
attr_reader :github_redirection_service
|
53
|
+
|
54
|
+
sig { returns(T.nilable(Dependabot::DependencyGroup)) }
|
55
|
+
attr_reader :dependency_group
|
56
|
+
|
57
|
+
sig { returns(T.nilable(Integer)) }
|
58
|
+
attr_reader :pr_message_max_length
|
59
|
+
|
60
|
+
sig { returns(T.nilable(Encoding)) }
|
61
|
+
attr_reader :pr_message_encoding
|
62
|
+
|
63
|
+
sig { returns(T::Array[T::Hash[String, String]]) }
|
64
|
+
attr_reader :ignore_conditions
|
28
65
|
|
29
66
|
TRUNCATED_MSG = "...\n\n_Description has been truncated_"
|
30
67
|
|
68
|
+
sig do
|
69
|
+
params(
|
70
|
+
source: Dependabot::Source,
|
71
|
+
dependencies: T::Array[Dependabot::Dependency],
|
72
|
+
files: T::Array[Dependabot::DependencyFile],
|
73
|
+
credentials: T::Array[Dependabot::Credential],
|
74
|
+
pr_message_header: T.nilable(String),
|
75
|
+
pr_message_footer: T.nilable(String),
|
76
|
+
commit_message_options: T.nilable(T::Hash[Symbol, T.untyped]),
|
77
|
+
vulnerabilities_fixed: T::Hash[String, T.untyped],
|
78
|
+
github_redirection_service: T.nilable(String),
|
79
|
+
dependency_group: T.nilable(Dependabot::DependencyGroup),
|
80
|
+
pr_message_max_length: T.nilable(Integer),
|
81
|
+
pr_message_encoding: T.nilable(Encoding),
|
82
|
+
ignore_conditions: T::Array[T::Hash[String, String]]
|
83
|
+
)
|
84
|
+
.void
|
85
|
+
end
|
31
86
|
def initialize(source:, dependencies:, files:, credentials:,
|
32
87
|
pr_message_header: nil, pr_message_footer: nil,
|
33
88
|
commit_message_options: {}, vulnerabilities_fixed: {},
|
@@ -48,16 +103,20 @@ module Dependabot
|
|
48
103
|
@ignore_conditions = ignore_conditions
|
49
104
|
end
|
50
105
|
|
106
|
+
sig { params(pr_message_max_length: Integer).returns(Integer) }
|
51
107
|
attr_writer :pr_message_max_length
|
52
108
|
|
109
|
+
sig { params(pr_message_encoding: Encoding).returns(Encoding) }
|
53
110
|
attr_writer :pr_message_encoding
|
54
111
|
|
112
|
+
sig { returns(String) }
|
55
113
|
def pr_name
|
56
114
|
name = dependency_group ? group_pr_name : solo_pr_name
|
57
|
-
name[0] = name[0].capitalize if pr_name_prefixer.capitalize_first_word?
|
115
|
+
name[0] = T.must(name[0]).capitalize if pr_name_prefixer.capitalize_first_word?
|
58
116
|
"#{pr_name_prefix}#{name}"
|
59
117
|
end
|
60
118
|
|
119
|
+
sig { returns(String) }
|
61
120
|
def pr_message
|
62
121
|
msg = "#{suffixed_pr_message_header}" \
|
63
122
|
"#{commit_message_intro}" \
|
@@ -73,35 +132,42 @@ module Dependabot
|
|
73
132
|
|
74
133
|
# Truncate PR message as determined by the pr_message_max_length and pr_message_encoding instance variables
|
75
134
|
# The encoding is used when calculating length, all messages are returned as ruby UTF_8 encoded string
|
135
|
+
sig { params(msg: String).returns(String) }
|
76
136
|
def truncate_pr_message(msg)
|
77
137
|
return msg if pr_message_max_length.nil?
|
78
138
|
|
79
139
|
msg = msg.dup
|
80
|
-
msg = msg.force_encoding(pr_message_encoding) unless pr_message_encoding.nil?
|
140
|
+
msg = msg.force_encoding(T.must(pr_message_encoding)) unless pr_message_encoding.nil?
|
81
141
|
|
82
|
-
if msg.length > pr_message_max_length
|
83
|
-
tr_msg = pr_message_encoding.nil?
|
84
|
-
|
85
|
-
|
142
|
+
if msg.length > T.must(pr_message_max_length)
|
143
|
+
tr_msg = if pr_message_encoding.nil?
|
144
|
+
TRUNCATED_MSG
|
145
|
+
else
|
146
|
+
(+TRUNCATED_MSG).dup.force_encoding(T.must(pr_message_encoding))
|
147
|
+
end
|
148
|
+
trunc_length = T.must(pr_message_max_length) - tr_msg.length
|
149
|
+
msg = (T.must(msg[0..trunc_length]) + tr_msg)
|
86
150
|
end
|
87
151
|
# if we used a custom encoding for calculating length, then we need to force back to UTF-8
|
88
152
|
msg = msg.encode("utf-8", "binary", invalid: :replace, undef: :replace) unless pr_message_encoding.nil?
|
89
153
|
msg
|
90
154
|
end
|
91
155
|
|
156
|
+
sig { returns(String) }
|
92
157
|
def commit_message
|
93
158
|
message = commit_subject + "\n\n"
|
94
159
|
message += commit_message_intro
|
95
160
|
message += metadata_links
|
96
|
-
message += "\n\n" + message_trailers if message_trailers
|
161
|
+
message += "\n\n" + T.must(message_trailers) if message_trailers
|
97
162
|
message
|
98
163
|
rescue StandardError => e
|
99
164
|
Dependabot.logger.error("Error while generating commit message: #{e.message}")
|
100
165
|
message = commit_subject
|
101
|
-
message += "\n\n" + message_trailers if message_trailers
|
166
|
+
message += "\n\n" + T.must(message_trailers) if message_trailers
|
102
167
|
message
|
103
168
|
end
|
104
169
|
|
170
|
+
sig { returns(Dependabot::PullRequestCreator::Message) }
|
105
171
|
def message
|
106
172
|
Dependabot::PullRequestCreator::Message.new(
|
107
173
|
pr_name: pr_name,
|
@@ -112,65 +178,74 @@ module Dependabot
|
|
112
178
|
|
113
179
|
private
|
114
180
|
|
181
|
+
sig { returns(String) }
|
115
182
|
def solo_pr_name
|
116
183
|
name = library? ? library_pr_name : application_pr_name
|
117
184
|
"#{name}#{pr_name_directory}"
|
118
185
|
end
|
119
186
|
|
187
|
+
sig { returns(String) }
|
120
188
|
def library_pr_name
|
121
189
|
"update " +
|
122
190
|
if dependencies.count == 1
|
123
|
-
"#{dependencies.first.display_name} requirement " \
|
124
|
-
"#{from_version_msg(old_library_requirement(dependencies.first))}" \
|
125
|
-
"to #{new_library_requirement(dependencies.first)}"
|
191
|
+
"#{T.must(dependencies.first).display_name} requirement " \
|
192
|
+
"#{from_version_msg(old_library_requirement(T.must(dependencies.first)))}" \
|
193
|
+
"to #{new_library_requirement(T.must(dependencies.first))}"
|
126
194
|
else
|
127
195
|
names = dependencies.map(&:name).uniq
|
128
196
|
if names.count == 1
|
129
197
|
"requirements for #{names.first}"
|
130
198
|
else
|
131
|
-
"requirements for #{names[0..-2].join(', ')} and #{names[-1]}"
|
199
|
+
"requirements for #{T.must(names[0..-2]).join(', ')} and #{names[-1]}"
|
132
200
|
end
|
133
201
|
end
|
134
202
|
end
|
135
203
|
|
204
|
+
# rubocop:disable Metrics/AbcSize
|
205
|
+
sig { returns(String) }
|
136
206
|
def application_pr_name
|
137
207
|
"bump " +
|
138
208
|
if dependencies.count == 1
|
139
209
|
dependency = dependencies.first
|
140
|
-
"#{dependency.display_name} " \
|
141
|
-
"#{from_version_msg(dependency.humanized_previous_version)}" \
|
142
|
-
"to #{dependency.humanized_version}"
|
210
|
+
"#{T.must(dependency).display_name} " \
|
211
|
+
"#{from_version_msg(T.must(dependency).humanized_previous_version)}" \
|
212
|
+
"to #{T.must(dependency).humanized_version}"
|
143
213
|
elsif updating_a_property?
|
144
214
|
dependency = dependencies.first
|
145
215
|
"#{property_name} " \
|
146
|
-
"#{from_version_msg(dependency.humanized_previous_version)}" \
|
147
|
-
"to #{dependency.humanized_version}"
|
216
|
+
"#{from_version_msg(T.must(dependency).humanized_previous_version)}" \
|
217
|
+
"to #{T.must(dependency).humanized_version}"
|
148
218
|
elsif updating_a_dependency_set?
|
149
219
|
dependency = dependencies.first
|
150
220
|
"#{dependency_set.fetch(:group)} dependency set " \
|
151
|
-
"#{from_version_msg(dependency.humanized_previous_version)}" \
|
152
|
-
"to #{dependency.humanized_version}"
|
221
|
+
"#{from_version_msg(T.must(dependency).humanized_previous_version)}" \
|
222
|
+
"to #{T.must(dependency).humanized_version}"
|
153
223
|
else
|
154
224
|
names = dependencies.map(&:name).uniq
|
155
225
|
if names.count == 1
|
156
|
-
names.first
|
226
|
+
T.must(names.first)
|
157
227
|
else
|
158
|
-
"#{names[0..-2].join(', ')} and #{names[-1]}"
|
228
|
+
"#{T.must(names[0..-2]).join(', ')} and #{names[-1]}"
|
159
229
|
end
|
160
230
|
end
|
161
231
|
end
|
232
|
+
# rubocop:enable Metrics/AbcSize
|
162
233
|
|
234
|
+
sig { returns(String) }
|
163
235
|
def group_pr_name
|
164
236
|
updates = dependencies.map(&:name).uniq.count
|
165
237
|
|
166
|
-
if source
|
167
|
-
"bump the #{dependency_group.name} across #{source.directories.count} directories " \
|
238
|
+
if source.directories
|
239
|
+
"bump the #{T.must(dependency_group).name} across #{T.must(source.directories).count} directories " \
|
168
240
|
"with #{updates} update#{'s' if updates > 1}"
|
169
241
|
else
|
170
|
-
"bump the #{dependency_group.name} group#{pr_name_directory} with #{updates} update#{
|
242
|
+
"bump the #{T.must(dependency_group).name} group#{pr_name_directory} with #{updates} update#{if updates > 1
|
243
|
+
's'
|
244
|
+
end}"
|
171
245
|
end
|
172
246
|
end
|
173
247
|
|
248
|
+
sig { returns(String) }
|
174
249
|
def pr_name_prefix
|
175
250
|
pr_name_prefixer.pr_name_prefix
|
176
251
|
rescue StandardError => e
|
@@ -178,12 +253,14 @@ module Dependabot
|
|
178
253
|
""
|
179
254
|
end
|
180
255
|
|
256
|
+
sig { returns(String) }
|
181
257
|
def pr_name_directory
|
182
|
-
return "" if files.first.directory == "/"
|
258
|
+
return "" if T.must(files.first).directory == "/"
|
183
259
|
|
184
|
-
" in #{files.first.directory}"
|
260
|
+
" in #{T.must(files.first).directory}"
|
185
261
|
end
|
186
262
|
|
263
|
+
sig { returns(String) }
|
187
264
|
def commit_subject
|
188
265
|
subject = pr_name.gsub("⬆️", ":arrow_up:").gsub("🔒", ":lock:")
|
189
266
|
return subject unless subject.length > 72
|
@@ -191,57 +268,65 @@ module Dependabot
|
|
191
268
|
subject = subject.gsub(/ from [^\s]*? to [^\s]*/, "")
|
192
269
|
return subject unless subject.length > 72
|
193
270
|
|
194
|
-
subject.split(" in ").first
|
271
|
+
T.must(subject.split(" in ").first)
|
195
272
|
end
|
196
273
|
|
274
|
+
sig { returns(String) }
|
197
275
|
def commit_message_intro
|
198
276
|
return requirement_commit_message_intro if library?
|
199
277
|
|
200
278
|
version_commit_message_intro
|
201
279
|
end
|
202
280
|
|
281
|
+
sig { returns(String) }
|
203
282
|
def prefixed_pr_message_footer
|
204
283
|
return "" unless pr_message_footer
|
205
284
|
|
206
285
|
"\n\n#{pr_message_footer}"
|
207
286
|
end
|
208
287
|
|
288
|
+
sig { returns(String) }
|
209
289
|
def suffixed_pr_message_header
|
210
290
|
return "" unless pr_message_header
|
211
291
|
|
212
292
|
"#{pr_message_header}\n\n"
|
213
293
|
end
|
214
294
|
|
295
|
+
sig { returns(T.nilable(String)) }
|
215
296
|
def message_trailers
|
216
297
|
return unless signoff_trailers || custom_trailers
|
217
298
|
|
218
299
|
[signoff_trailers, custom_trailers].compact.join("\n")
|
219
300
|
end
|
220
301
|
|
302
|
+
sig { returns(T.nilable(String)) }
|
221
303
|
def custom_trailers
|
222
|
-
trailers = commit_message_options
|
304
|
+
trailers = commit_message_options&.dig(:trailers)
|
223
305
|
return if trailers.nil?
|
224
306
|
raise("Commit trailers must be a Hash object") unless trailers.is_a?(Hash)
|
225
307
|
|
226
308
|
trailers.compact.map { |k, v| "#{k}: #{v}" }.join("\n")
|
227
309
|
end
|
228
310
|
|
311
|
+
sig { returns(T.nilable(String)) }
|
229
312
|
def signoff_trailers
|
230
313
|
return unless on_behalf_of_message || signoff_message
|
231
314
|
|
232
315
|
[on_behalf_of_message, signoff_message].compact.join("\n")
|
233
316
|
end
|
234
317
|
|
318
|
+
sig { returns(T.nilable(String)) }
|
235
319
|
def signoff_message
|
236
|
-
signoff_details = commit_message_options
|
320
|
+
signoff_details = commit_message_options&.dig(:signoff_details)
|
237
321
|
return unless signoff_details.is_a?(Hash)
|
238
322
|
return unless signoff_details[:name] && signoff_details[:email]
|
239
323
|
|
240
324
|
"Signed-off-by: #{signoff_details[:name]} <#{signoff_details[:email]}>"
|
241
325
|
end
|
242
326
|
|
327
|
+
sig { returns(T.nilable(String)) }
|
243
328
|
def on_behalf_of_message
|
244
|
-
signoff_details = commit_message_options
|
329
|
+
signoff_details = commit_message_options&.dig(:signoff_details)
|
245
330
|
return unless signoff_details.is_a?(Hash)
|
246
331
|
return unless signoff_details[:org_name] && signoff_details[:org_email]
|
247
332
|
|
@@ -249,6 +334,7 @@ module Dependabot
|
|
249
334
|
"<#{signoff_details[:org_email]}>"
|
250
335
|
end
|
251
336
|
|
337
|
+
sig { returns(String) }
|
252
338
|
def requirement_commit_message_intro
|
253
339
|
msg = "Updates the requirements on "
|
254
340
|
|
@@ -256,7 +342,7 @@ module Dependabot
|
|
256
342
|
if dependencies.count == 1
|
257
343
|
"#{dependency_links.first} "
|
258
344
|
else
|
259
|
-
"#{dependency_links[0..-2].join(', ')} and #{dependency_links[-1]} "
|
345
|
+
"#{T.must(dependency_links[0..-2]).join(', ')} and #{dependency_links[-1]} "
|
260
346
|
end
|
261
347
|
|
262
348
|
msg + "to permit the latest version."
|
@@ -265,8 +351,9 @@ module Dependabot
|
|
265
351
|
# rubocop:disable Metrics/CyclomaticComplexity
|
266
352
|
# rubocop:disable Metrics/PerceivedComplexity
|
267
353
|
# rubocop:disable Metrics/AbcSize
|
354
|
+
sig { returns(String) }
|
268
355
|
def version_commit_message_intro
|
269
|
-
return multi_directory_group_intro if dependency_group && source
|
356
|
+
return multi_directory_group_intro if dependency_group && source.directories
|
270
357
|
|
271
358
|
return group_intro if dependency_group
|
272
359
|
|
@@ -283,14 +370,16 @@ module Dependabot
|
|
283
370
|
|
284
371
|
dependency = dependencies.first
|
285
372
|
msg = "Bumps #{dependency_links.first} " \
|
286
|
-
"#{from_version_msg(dependency.humanized_previous_version)}" \
|
287
|
-
"to #{dependency.humanized_version}."
|
373
|
+
"#{from_version_msg(T.must(dependency).humanized_previous_version)}" \
|
374
|
+
"to #{T.must(dependency).humanized_version}."
|
288
375
|
|
289
|
-
|
376
|
+
if switching_from_ref_to_release?(T.must(dependency))
|
377
|
+
msg += " This release includes the previously tagged commit."
|
378
|
+
end
|
290
379
|
|
291
|
-
if vulnerabilities_fixed[dependency.name]&.one?
|
380
|
+
if vulnerabilities_fixed[T.must(dependency).name]&.one?
|
292
381
|
msg += " **This update includes a security fix.**"
|
293
|
-
elsif vulnerabilities_fixed[dependency.name]&.any?
|
382
|
+
elsif vulnerabilities_fixed[T.must(dependency).name]&.any?
|
294
383
|
msg += " **This update includes security fixes.**"
|
295
384
|
end
|
296
385
|
|
@@ -300,35 +389,39 @@ module Dependabot
|
|
300
389
|
# rubocop:enable Metrics/PerceivedComplexity
|
301
390
|
# rubocop:enable Metrics/AbcSize
|
302
391
|
|
392
|
+
sig { returns(String) }
|
303
393
|
def multidependency_property_intro
|
304
394
|
dependency = dependencies.first
|
305
395
|
|
306
396
|
"Bumps `#{property_name}` " \
|
307
|
-
"#{from_version_msg(dependency.humanized_previous_version)}" \
|
308
|
-
"to #{dependency.humanized_version}."
|
397
|
+
"#{from_version_msg(T.must(dependency).humanized_previous_version)}" \
|
398
|
+
"to #{T.must(dependency).humanized_version}."
|
309
399
|
end
|
310
400
|
|
401
|
+
sig { returns(String) }
|
311
402
|
def dependency_set_intro
|
312
403
|
dependency = dependencies.first
|
313
404
|
|
314
405
|
"Bumps `#{dependency_set.fetch(:group)}` " \
|
315
|
-
"dependency set #{from_version_msg(dependency.humanized_previous_version)}" \
|
316
|
-
"to #{dependency.humanized_version}."
|
406
|
+
"dependency set #{from_version_msg(T.must(dependency).humanized_previous_version)}" \
|
407
|
+
"to #{T.must(dependency).humanized_version}."
|
317
408
|
end
|
318
409
|
|
410
|
+
sig { returns(String) }
|
319
411
|
def multidependency_intro
|
320
|
-
"Bumps #{dependency_links[0..-2].join(', ')} " \
|
412
|
+
"Bumps #{T.must(dependency_links[0..-2]).join(', ')} " \
|
321
413
|
"and #{dependency_links[-1]}. These " \
|
322
414
|
"dependencies needed to be updated together."
|
323
415
|
end
|
324
416
|
|
417
|
+
sig { returns(String) }
|
325
418
|
def transitive_multidependency_intro
|
326
419
|
dependency = dependencies.first
|
327
420
|
|
328
|
-
msg = "Bumps #{dependency_links[0]} to #{dependency.humanized_version}"
|
421
|
+
msg = "Bumps #{dependency_links[0]} to #{T.must(dependency).humanized_version}"
|
329
422
|
|
330
423
|
msg += if dependencies.count > 2
|
331
|
-
" and updates ancestor dependencies #{dependency_links[0..-2].join(', ')} " \
|
424
|
+
" and updates ancestor dependencies #{T.must(dependency_links[0..-2]).join(', ')} " \
|
332
425
|
"and #{dependency_links[-1]}. "
|
333
426
|
else
|
334
427
|
" and updates ancestor dependency #{dependency_links[1]}. "
|
@@ -339,11 +432,12 @@ module Dependabot
|
|
339
432
|
msg
|
340
433
|
end
|
341
434
|
|
435
|
+
sig { returns(String) }
|
342
436
|
def transitive_removed_dependency_intro
|
343
437
|
msg = "Removes #{dependency_links[0]}. It's no longer used after updating"
|
344
438
|
|
345
439
|
msg += if dependencies.count > 2
|
346
|
-
" ancestor dependencies #{dependency_links[0..-2].join(', ')} " \
|
440
|
+
" ancestor dependencies #{T.must(dependency_links[0..-2]).join(', ')} " \
|
347
441
|
"and #{dependency_links[-1]}. "
|
348
442
|
else
|
349
443
|
" ancestor dependency #{dependency_links[1]}. "
|
@@ -354,16 +448,18 @@ module Dependabot
|
|
354
448
|
msg
|
355
449
|
end
|
356
450
|
|
451
|
+
# rubocop:disable Metrics/AbcSize
|
452
|
+
sig { returns(String) }
|
357
453
|
def multi_directory_group_intro
|
358
454
|
msg = ""
|
359
455
|
|
360
|
-
source.directories.each do |directory|
|
456
|
+
T.must(source.directories).each do |directory|
|
361
457
|
dependencies_in_directory = dependencies.select { |dep| dep.metadata[:directory] == directory }
|
362
458
|
next unless dependencies_in_directory.any?
|
363
459
|
|
364
460
|
update_count = dependencies_in_directory.map(&:name).uniq.count
|
365
461
|
|
366
|
-
msg += "Bumps the #{dependency_group.name} " \
|
462
|
+
msg += "Bumps the #{T.must(dependency_group).name} " \
|
367
463
|
"with #{update_count} update#{update_count > 1 ? 's' : ''} in the #{directory} directory:"
|
368
464
|
|
369
465
|
msg += if update_count >= 5
|
@@ -378,10 +474,11 @@ module Dependabot
|
|
378
474
|
"\n\n#{table([header] + rows)}"
|
379
475
|
elsif update_count > 1
|
380
476
|
dependency_links_in_directory = dependency_links_for_directory(directory)
|
381
|
-
" #{dependency_links_in_directory[0..-2].join(', ')}
|
477
|
+
" #{T.must(T.must(dependency_links_in_directory)[0..-2]).join(', ')}" \
|
478
|
+
" and #{T.must(dependency_links_in_directory)[-1]}."
|
382
479
|
else
|
383
480
|
dependency_links_in_directory = dependency_links_for_directory(directory)
|
384
|
-
" #{dependency_links_in_directory.first}."
|
481
|
+
" #{T.must(dependency_links_in_directory).first}."
|
385
482
|
end
|
386
483
|
|
387
484
|
msg += "\n"
|
@@ -389,11 +486,13 @@ module Dependabot
|
|
389
486
|
|
390
487
|
msg
|
391
488
|
end
|
489
|
+
# rubocop:enable Metrics/AbcSize
|
392
490
|
|
491
|
+
sig { returns(String) }
|
393
492
|
def group_intro
|
394
493
|
update_count = dependencies.map(&:name).uniq.count
|
395
494
|
|
396
|
-
msg = "Bumps the #{dependency_group.name} group#{pr_name_directory} " \
|
495
|
+
msg = "Bumps the #{T.must(dependency_group).name} group#{pr_name_directory} " \
|
397
496
|
"with #{update_count} update#{update_count > 1 ? 's' : ''}:"
|
398
497
|
|
399
498
|
msg += if update_count >= 5
|
@@ -407,7 +506,7 @@ module Dependabot
|
|
407
506
|
end
|
408
507
|
"\n\n#{table([header] + rows)}"
|
409
508
|
elsif update_count > 1
|
410
|
-
" #{dependency_links[0..-2].join(', ')} and #{dependency_links[-1]}."
|
509
|
+
" #{T.must(dependency_links[0..-2]).join(', ')} and #{dependency_links[-1]}."
|
411
510
|
else
|
412
511
|
" #{dependency_links.first}."
|
413
512
|
end
|
@@ -417,66 +516,86 @@ module Dependabot
|
|
417
516
|
msg
|
418
517
|
end
|
419
518
|
|
519
|
+
sig { params(previous_version: T.nilable(String)).returns(String) }
|
420
520
|
def from_version_msg(previous_version)
|
421
521
|
return "" unless previous_version
|
422
522
|
|
423
523
|
"from #{previous_version} "
|
424
524
|
end
|
425
525
|
|
526
|
+
sig { returns(T::Boolean) }
|
426
527
|
def updating_a_property?
|
427
|
-
dependencies.first
|
428
|
-
|
429
|
-
|
528
|
+
T.must(dependencies.first)
|
529
|
+
.requirements
|
530
|
+
.any? { |r| r.dig(:metadata, :property_name) }
|
430
531
|
end
|
431
532
|
|
533
|
+
sig { returns(T::Boolean) }
|
432
534
|
def updating_a_dependency_set?
|
433
|
-
dependencies.first
|
434
|
-
|
435
|
-
|
535
|
+
T.must(dependencies.first)
|
536
|
+
.requirements
|
537
|
+
.any? { |r| r.dig(:metadata, :dependency_set) }
|
436
538
|
end
|
437
539
|
|
540
|
+
sig { returns(T::Boolean) }
|
438
541
|
def removing_a_transitive_dependency?
|
439
542
|
dependencies.any?(&:removed?)
|
440
543
|
end
|
441
544
|
|
545
|
+
sig { returns(T::Boolean) }
|
442
546
|
def updating_top_level_and_transitive_dependencies?
|
443
547
|
dependencies.any?(&:top_level?) &&
|
444
548
|
dependencies.any? { |dep| !dep.top_level? }
|
445
549
|
end
|
446
550
|
|
551
|
+
sig { returns(String) }
|
447
552
|
def property_name
|
448
|
-
@property_name ||=
|
449
|
-
|
450
|
-
|
553
|
+
@property_name ||=
|
554
|
+
T.let(
|
555
|
+
dependencies.first
|
556
|
+
&.requirements
|
557
|
+
&.find { |r| r.dig(:metadata, :property_name) }
|
558
|
+
&.dig(:metadata, :property_name),
|
559
|
+
T.nilable(String)
|
560
|
+
)
|
451
561
|
|
452
562
|
raise "No property name!" unless @property_name
|
453
563
|
|
454
564
|
@property_name
|
455
565
|
end
|
456
566
|
|
567
|
+
sig { returns(T::Hash[Symbol, String]) }
|
457
568
|
def dependency_set
|
458
|
-
@dependency_set ||=
|
459
|
-
|
460
|
-
|
569
|
+
@dependency_set ||=
|
570
|
+
T.let(
|
571
|
+
dependencies.first
|
572
|
+
&.requirements
|
573
|
+
&.find { |r| r.dig(:metadata, :dependency_set) }
|
574
|
+
&.dig(:metadata, :dependency_set),
|
575
|
+
T.nilable(T.nilable(T::Hash[Symbol, String]))
|
576
|
+
)
|
461
577
|
|
462
578
|
raise "No dependency set!" unless @dependency_set
|
463
579
|
|
464
580
|
@dependency_set
|
465
581
|
end
|
466
582
|
|
583
|
+
sig { returns(T::Array[String]) }
|
467
584
|
def dependency_links
|
468
|
-
return @dependency_links if defined?(@dependency_links)
|
585
|
+
return T.must(@dependency_links) if defined?(@dependency_links)
|
469
586
|
|
470
587
|
uniq_deps = dependencies.each_with_object({}) { |dep, memo| memo[dep.name] ||= dep }.values
|
471
588
|
@dependency_links = uniq_deps.map { |dep| dependency_link(dep) }
|
472
589
|
end
|
473
590
|
|
591
|
+
sig { params(directory: String).returns(T.nilable(T::Array[String])) }
|
474
592
|
def dependency_links_for_directory(directory)
|
475
593
|
dependencies_in_directory = dependencies.select { |dep| dep.metadata[:directory] == directory }
|
476
594
|
uniq_deps = dependencies_in_directory.each_with_object({}) { |dep, memo| memo[dep.name] ||= dep }.values
|
477
|
-
@dependency_links = uniq_deps.map { |dep| dependency_link(dep) }
|
595
|
+
@dependency_links = T.let(uniq_deps.map { |dep| dependency_link(dep) }, T.nilable(T::Array[String]))
|
478
596
|
end
|
479
597
|
|
598
|
+
sig { params(dependency: Dependabot::Dependency).returns(String) }
|
480
599
|
def dependency_link(dependency)
|
481
600
|
if source_url(dependency)
|
482
601
|
"[#{dependency.display_name}](#{source_url(dependency)})"
|
@@ -487,12 +606,14 @@ module Dependabot
|
|
487
606
|
end
|
488
607
|
end
|
489
608
|
|
609
|
+
sig { params(dependency: Dependabot::Dependency).returns(String) }
|
490
610
|
def dependency_version_update(dependency)
|
491
611
|
"#{dependency.humanized_previous_version} to #{dependency.humanized_version}"
|
492
612
|
end
|
493
613
|
|
614
|
+
sig { returns(String) }
|
494
615
|
def metadata_links
|
495
|
-
return metadata_links_for_dep(dependencies.first) if dependencies.count == 1 && dependency_group.nil?
|
616
|
+
return metadata_links_for_dep(T.must(dependencies.first)) if dependencies.count == 1 && dependency_group.nil?
|
496
617
|
|
497
618
|
dependencies.map do |dep|
|
498
619
|
if dep.removed?
|
@@ -506,6 +627,7 @@ module Dependabot
|
|
506
627
|
end.join
|
507
628
|
end
|
508
629
|
|
630
|
+
sig { params(dep: Dependabot::Dependency).returns(String) }
|
509
631
|
def metadata_links_for_dep(dep)
|
510
632
|
msg = ""
|
511
633
|
msg += "\n- [Release notes](#{releases_url(dep)})" if releases_url(dep)
|
@@ -515,13 +637,15 @@ module Dependabot
|
|
515
637
|
msg
|
516
638
|
end
|
517
639
|
|
640
|
+
sig { params(rows: T::Array[T::Array[String]]).returns(String) }
|
518
641
|
def table(rows)
|
519
642
|
[
|
520
|
-
table_header(rows[0]),
|
521
|
-
rows[1..].map { |r| table_row(r) }
|
643
|
+
table_header(T.must(rows[0])),
|
644
|
+
T.must(rows[1..]).map { |r| table_row(r) }
|
522
645
|
].join("\n")
|
523
646
|
end
|
524
647
|
|
648
|
+
sig { params(row: T::Array[String]).returns(String) }
|
525
649
|
def table_header(row)
|
526
650
|
[
|
527
651
|
table_row(row),
|
@@ -529,12 +653,14 @@ module Dependabot
|
|
529
653
|
].join("\n")
|
530
654
|
end
|
531
655
|
|
656
|
+
sig { params(row: T::Array[String]).returns(String) }
|
532
657
|
def table_row(row)
|
533
658
|
"| #{row.join(' | ')} |"
|
534
659
|
end
|
535
660
|
|
661
|
+
sig { returns(String) }
|
536
662
|
def metadata_cascades # rubocop:disable Metrics/PerceivedComplexity
|
537
|
-
return metadata_cascades_for_dep(dependencies.first) if dependencies.one? && !dependency_group
|
663
|
+
return metadata_cascades_for_dep(T.must(dependencies.first)) if dependencies.one? && !dependency_group
|
538
664
|
|
539
665
|
dependencies.map do |dep|
|
540
666
|
msg = if dep.removed?
|
@@ -555,6 +681,7 @@ module Dependabot
|
|
555
681
|
end.join
|
556
682
|
end
|
557
683
|
|
684
|
+
sig { params(dependency: Dependabot::Dependency).returns(String) }
|
558
685
|
def metadata_cascades_for_dep(dependency)
|
559
686
|
return "" if dependency.removed?
|
560
687
|
|
@@ -567,6 +694,7 @@ module Dependabot
|
|
567
694
|
).to_s
|
568
695
|
end
|
569
696
|
|
697
|
+
sig { returns(String) }
|
570
698
|
def ignore_conditions_table
|
571
699
|
# Return an empty string if ignore_conditions is empty
|
572
700
|
return "" if @ignore_conditions.empty?
|
@@ -580,7 +708,9 @@ module Dependabot
|
|
580
708
|
return "" if valid_ignore_conditions.empty?
|
581
709
|
|
582
710
|
# Sort them by updated_at (or created_at if updated_at is nil), taking the latest 20
|
583
|
-
sorted_ignore_conditions = valid_ignore_conditions.sort_by
|
711
|
+
sorted_ignore_conditions = valid_ignore_conditions.sort_by do |ic|
|
712
|
+
ic["updated_at"].nil? ? T.must(ic["created_at"]) : T.must(ic["updated_at"])
|
713
|
+
end.last(20)
|
584
714
|
|
585
715
|
# Map each condition to a row string
|
586
716
|
table_rows = sorted_ignore_conditions.map do |ic|
|
@@ -591,6 +721,7 @@ module Dependabot
|
|
591
721
|
build_table(summary, table_rows)
|
592
722
|
end
|
593
723
|
|
724
|
+
sig { params(summary: String, rows: T::Array[String]).returns(String) }
|
594
725
|
def build_table(summary, rows)
|
595
726
|
table_header = "| Dependency Name | Ignore Conditions |"
|
596
727
|
table_divider = "| --- | --- |"
|
@@ -607,74 +738,87 @@ module Dependabot
|
|
607
738
|
end
|
608
739
|
end
|
609
740
|
|
741
|
+
sig { params(dependency: Dependabot::Dependency).returns(T.nilable(String)) }
|
610
742
|
def changelog_url(dependency)
|
611
743
|
metadata_finder(dependency).changelog_url
|
612
744
|
end
|
613
745
|
|
746
|
+
sig { params(dependency: Dependabot::Dependency).returns(T.nilable(String)) }
|
614
747
|
def commits_url(dependency)
|
615
748
|
metadata_finder(dependency).commits_url
|
616
749
|
end
|
617
750
|
|
751
|
+
sig { params(dependency: Dependabot::Dependency).returns(T.nilable(String)) }
|
618
752
|
def homepage_url(dependency)
|
619
753
|
metadata_finder(dependency).homepage_url
|
620
754
|
end
|
621
755
|
|
756
|
+
sig { params(dependency: Dependabot::Dependency).returns(T.nilable(String)) }
|
622
757
|
def releases_url(dependency)
|
623
758
|
metadata_finder(dependency).releases_url
|
624
759
|
end
|
625
760
|
|
761
|
+
sig { params(dependency: Dependabot::Dependency).returns(T.nilable(String)) }
|
626
762
|
def source_url(dependency)
|
627
763
|
metadata_finder(dependency).source_url
|
628
764
|
end
|
629
765
|
|
766
|
+
sig { params(dependency: Dependabot::Dependency).returns(T.nilable(String)) }
|
630
767
|
def upgrade_url(dependency)
|
631
768
|
metadata_finder(dependency).upgrade_guide_url
|
632
769
|
end
|
633
770
|
|
771
|
+
sig { params(dependency: Dependabot::Dependency).returns(Dependabot::MetadataFinders::Base) }
|
634
772
|
def metadata_finder(dependency)
|
635
|
-
@metadata_finder ||= {}
|
773
|
+
@metadata_finder ||= T.let({}, T.nilable(T::Hash[String, Dependabot::MetadataFinders::Base]))
|
636
774
|
@metadata_finder[dependency.name] ||=
|
637
775
|
MetadataFinders
|
638
776
|
.for_package_manager(dependency.package_manager)
|
639
777
|
.new(dependency: dependency, credentials: credentials)
|
640
778
|
end
|
641
779
|
|
780
|
+
sig { returns(Dependabot::PullRequestCreator::PrNamePrefixer) }
|
642
781
|
def pr_name_prefixer
|
643
782
|
@pr_name_prefixer ||=
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
783
|
+
T.let(
|
784
|
+
PrNamePrefixer.new(
|
785
|
+
source: source,
|
786
|
+
dependencies: dependencies,
|
787
|
+
credentials: credentials,
|
788
|
+
commit_message_options: commit_message_options,
|
789
|
+
security_fix: vulnerabilities_fixed.values.flatten.any?
|
790
|
+
),
|
791
|
+
T.nilable(Dependabot::PullRequestCreator::PrNamePrefixer)
|
650
792
|
)
|
651
793
|
end
|
652
794
|
|
795
|
+
sig { params(dependency: Dependabot::Dependency).returns(T.nilable(String)) }
|
653
796
|
def old_library_requirement(dependency)
|
654
797
|
old_reqs =
|
655
|
-
dependency.previous_requirements - dependency.requirements
|
798
|
+
T.must(dependency.previous_requirements) - dependency.requirements
|
656
799
|
|
657
800
|
gemspec =
|
658
801
|
old_reqs.find { |r| r[:file].match?(%r{^[^/]*\.gemspec$}) }
|
659
802
|
return gemspec.fetch(:requirement) if gemspec
|
660
803
|
|
661
|
-
req = old_reqs.first.fetch(:requirement)
|
804
|
+
req = T.must(old_reqs.first).fetch(:requirement)
|
662
805
|
return req if req
|
663
806
|
|
664
807
|
dependency.previous_ref if dependency.ref_changed?
|
665
808
|
end
|
666
809
|
|
810
|
+
sig { params(dependency: Dependabot::Dependency).returns(String) }
|
667
811
|
def new_library_requirement(dependency)
|
668
812
|
updated_reqs =
|
669
|
-
dependency.requirements - dependency.previous_requirements
|
813
|
+
dependency.requirements - T.must(dependency.previous_requirements)
|
670
814
|
|
671
815
|
gemspec =
|
672
816
|
updated_reqs.find { |r| r[:file].match?(%r{^[^/]*\.gemspec$}) }
|
673
817
|
return gemspec.fetch(:requirement) if gemspec
|
674
818
|
|
675
|
-
req = updated_reqs.first.fetch(:requirement)
|
819
|
+
req = T.must(updated_reqs.first).fetch(:requirement)
|
676
820
|
return req if req
|
677
|
-
return dependency.new_ref if dependency.ref_changed? && dependency.new_ref
|
821
|
+
return T.must(dependency.new_ref) if dependency.ref_changed? && dependency.new_ref
|
678
822
|
|
679
823
|
raise "No new requirement!"
|
680
824
|
end
|
@@ -684,6 +828,7 @@ module Dependabot
|
|
684
828
|
# `requirements_update_strategy`.
|
685
829
|
#
|
686
830
|
# TODO reuse in BranchNamer
|
831
|
+
sig { returns(T::Boolean) }
|
687
832
|
def library?
|
688
833
|
# Reject any nested child gemspecs/vendored git dependencies
|
689
834
|
root_files = files.map(&:name)
|
@@ -693,6 +838,7 @@ module Dependabot
|
|
693
838
|
dependencies.any? { |d| d.humanized_previous_version.nil? }
|
694
839
|
end
|
695
840
|
|
841
|
+
sig { params(dependency: Dependabot::Dependency).returns(T::Boolean) }
|
696
842
|
def switching_from_ref_to_release?(dependency)
|
697
843
|
unless dependency.previous_version&.match?(/^[0-9a-f]{40}$/) ||
|
698
844
|
(dependency.previous_version.nil? && dependency.previous_ref)
|
@@ -702,8 +848,12 @@ module Dependabot
|
|
702
848
|
Gem::Version.correct?(dependency.version)
|
703
849
|
end
|
704
850
|
|
851
|
+
sig { returns(String) }
|
705
852
|
def package_manager
|
706
|
-
@package_manager ||=
|
853
|
+
@package_manager ||= T.let(
|
854
|
+
T.must(dependencies.first).package_manager,
|
855
|
+
T.nilable(String)
|
856
|
+
)
|
707
857
|
end
|
708
858
|
end
|
709
859
|
end
|