dependabot-common 0.211.0 → 0.213.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/lib/dependabot/clients/azure.rb +1 -1
  3. data/lib/dependabot/clients/bitbucket.rb +10 -3
  4. data/lib/dependabot/config/file.rb +1 -1
  5. data/lib/dependabot/config/ignore_condition.rb +1 -1
  6. data/lib/dependabot/dependency.rb +27 -12
  7. data/lib/dependabot/errors.rb +10 -10
  8. data/lib/dependabot/experiments.rb +19 -0
  9. data/lib/dependabot/file_fetchers/base.rb +146 -83
  10. data/lib/dependabot/file_parsers/base/dependency_set.rb +107 -42
  11. data/lib/dependabot/file_updaters/vendor_updater.rb +2 -0
  12. data/lib/dependabot/git_commit_checker.rb +29 -13
  13. data/lib/dependabot/git_metadata_fetcher.rb +3 -3
  14. data/lib/dependabot/metadata_finders/base/changelog_finder.rb +5 -5
  15. data/lib/dependabot/metadata_finders/base/changelog_pruner.rb +4 -4
  16. data/lib/dependabot/metadata_finders/base/commits_finder.rb +4 -4
  17. data/lib/dependabot/metadata_finders/base/release_finder.rb +4 -4
  18. data/lib/dependabot/pull_request_creator/branch_namer.rb +25 -16
  19. data/lib/dependabot/pull_request_creator/github.rb +5 -5
  20. data/lib/dependabot/pull_request_creator/labeler.rb +8 -6
  21. data/lib/dependabot/pull_request_creator/message_builder/issue_linker.rb +5 -5
  22. data/lib/dependabot/pull_request_creator/message_builder/link_and_mention_sanitizer.rb +34 -6
  23. data/lib/dependabot/pull_request_creator/message_builder/metadata_presenter.rb +11 -13
  24. data/lib/dependabot/pull_request_creator/message_builder.rb +117 -45
  25. data/lib/dependabot/pull_request_creator/pr_name_prefixer.rb +8 -12
  26. data/lib/dependabot/pull_request_creator.rb +6 -3
  27. data/lib/dependabot/pull_request_updater/azure.rb +1 -1
  28. data/lib/dependabot/pull_request_updater/github.rb +16 -13
  29. data/lib/dependabot/pull_request_updater.rb +2 -1
  30. data/lib/dependabot/security_advisory.rb +3 -3
  31. data/lib/dependabot/shared_helpers.rb +12 -12
  32. data/lib/dependabot/source.rb +11 -11
  33. data/lib/dependabot/update_checkers/base.rb +2 -2
  34. data/lib/dependabot/version.rb +1 -1
  35. metadata +17 -44
@@ -8,17 +8,19 @@ module Dependabot
8
8
  class PullRequestCreator
9
9
  class MessageBuilder
10
10
  class LinkAndMentionSanitizer
11
- GITHUB_USERNAME = /[a-z0-9]+(-[a-z0-9]+)*/i.freeze
11
+ GITHUB_USERNAME = /[a-z0-9]+(-[a-z0-9]+)*/i
12
12
  GITHUB_REF_REGEX = %r{
13
13
  (?:https?://)?
14
14
  github\.com/(?<repo>#{GITHUB_USERNAME}/[^/\s]+)/
15
15
  (?:issue|pull)s?/(?<number>\d+)
16
- }x.freeze
17
- MENTION_REGEX = %r{(?<![A-Za-z0-9`~])@#{GITHUB_USERNAME}/?}.freeze
16
+ }x
17
+ # [^/\s#]+ means one or more characters not matching (^) the class /, whitespace (\s), or #
18
+ GITHUB_NWO_REGEX = %r{(?<repo>#{GITHUB_USERNAME}/[^/\s#]+)#(?<number>\d+)}
19
+ MENTION_REGEX = %r{(?<![A-Za-z0-9`~])@#{GITHUB_USERNAME}/?}
18
20
  # regex to match a team mention on github
19
- TEAM_MENTION_REGEX = %r{(?<![A-Za-z0-9`~])@(?<org>#{GITHUB_USERNAME})/(?<team>#{GITHUB_USERNAME})/?}.freeze
21
+ TEAM_MENTION_REGEX = %r{(?<![A-Za-z0-9`~])@(?<org>#{GITHUB_USERNAME})/(?<team>#{GITHUB_USERNAME})/?}
20
22
  # End of string
21
- EOS_REGEX = /\z/.freeze
23
+ EOS_REGEX = /\z/
22
24
  COMMONMARKER_OPTIONS = %i(
23
25
  GITHUB_PRE_LANG FULL_INFO_STRING
24
26
  ).freeze
@@ -40,6 +42,7 @@ module Dependabot
40
42
  sanitize_team_mentions(doc)
41
43
  sanitize_mentions(doc)
42
44
  sanitize_links(doc)
45
+ sanitize_nwo_text(doc)
43
46
 
44
47
  mode = unsafe ? :UNSAFE : :DEFAULT
45
48
  doc.to_html(([mode] + COMMONMARKER_OPTIONS), COMMONMARKER_EXTENSIONS)
@@ -109,6 +112,25 @@ module Dependabot
109
112
  end
110
113
  end
111
114
 
115
+ def sanitize_nwo_text(doc)
116
+ doc.walk do |node|
117
+ if node.type == :text &&
118
+ node.string_content.match?(GITHUB_NWO_REGEX) &&
119
+ !parent_node_link?(node)
120
+ replace_nwo_node(node)
121
+ end
122
+ end
123
+ end
124
+
125
+ def replace_nwo_node(node)
126
+ match = node.string_content.match(GITHUB_NWO_REGEX)
127
+ repo = match.named_captures.fetch("repo")
128
+ number = match.named_captures.fetch("number")
129
+ new_node = build_nwo_text_node("#{repo}##{number}")
130
+ node.insert_before(new_node)
131
+ node.delete
132
+ end
133
+
112
134
  def replace_github_host(text)
113
135
  text.gsub(
114
136
  /(www\.)?github.com/, github_redirection_service || "github.com"
@@ -171,6 +193,12 @@ module Dependabot
171
193
  [code_node]
172
194
  end
173
195
 
196
+ def build_nwo_text_node(text)
197
+ code_node = CommonMarker::Node.new(:code)
198
+ code_node.string_content = text
199
+ code_node
200
+ end
201
+
174
202
  def create_link_node(url, text)
175
203
  link_node = CommonMarker::Node.new(:link)
176
204
  code_node = CommonMarker::Node.new(:code)
@@ -189,7 +217,7 @@ module Dependabot
189
217
  end
190
218
 
191
219
  def parent_node_link?(node)
192
- node.type == :link || node.parent && parent_node_link?(node.parent)
220
+ node.type == :link || (node.parent && parent_node_link?(node.parent))
193
221
  end
194
222
  end
195
223
  end
@@ -63,7 +63,7 @@ module Dependabot
63
63
  def release_cascade
64
64
  return "" unless releases_text && releases_url
65
65
 
66
- msg = "*Sourced from [#{dependency.display_name}'s releases]"\
66
+ msg = "*Sourced from [#{dependency.display_name}'s releases]" \
67
67
  "(#{releases_url}).*\n\n"
68
68
  msg += quote_and_truncate(releases_text)
69
69
  msg = link_issues(text: msg)
@@ -80,8 +80,8 @@ module Dependabot
80
80
  def changelog_cascade
81
81
  return "" unless changelog_url && changelog_text
82
82
 
83
- msg = "*Sourced from "\
84
- "[#{dependency.display_name}'s changelog]"\
83
+ msg = "*Sourced from " \
84
+ "[#{dependency.display_name}'s changelog]" \
85
85
  "(#{changelog_url}).*\n\n"
86
86
  msg += quote_and_truncate(changelog_text)
87
87
  msg = link_issues(text: msg)
@@ -95,8 +95,8 @@ module Dependabot
95
95
  def upgrade_guide_cascade
96
96
  return "" unless upgrade_guide_url && upgrade_guide_text
97
97
 
98
- msg = "*Sourced from "\
99
- "[#{dependency.display_name}'s upgrade guide]"\
98
+ msg = "*Sourced from " \
99
+ "[#{dependency.display_name}'s upgrade guide]" \
100
100
  "(#{upgrade_guide_url}).*\n\n"
101
101
  msg += quote_and_truncate(upgrade_guide_text)
102
102
  msg = link_issues(text: msg)
@@ -112,7 +112,7 @@ module Dependabot
112
112
 
113
113
  msg = ""
114
114
 
115
- commits.reverse.first(10).each do |commit|
115
+ commits.last(10).reverse_each do |commit|
116
116
  title = commit[:message].strip.split("\n").first
117
117
  title = title.slice(0..76) + "..." if title && title.length > 80
118
118
  title = title&.gsub(/(?<=[^\w.-])([_*`~])/, '\\1')
@@ -124,8 +124,8 @@ module Dependabot
124
124
 
125
125
  msg +=
126
126
  if commits.count > 10
127
- "- Additional commits viewable in "\
128
- "[compare view](#{commits_url})\n"
127
+ "- Additional commits viewable in " \
128
+ "[compare view](#{commits_url})\n"
129
129
  else
130
130
  "- See full diff in [compare view](#{commits_url})\n"
131
131
  end
@@ -153,7 +153,7 @@ module Dependabot
153
153
  msg += body
154
154
  msg + "</details>\n"
155
155
  else
156
- "\n\##{summary}\n\n#{body}"
156
+ "\n##{summary}\n\n#{body}"
157
157
  end
158
158
  end
159
159
 
@@ -175,8 +175,8 @@ module Dependabot
175
175
 
176
176
  def vulnerability_source_line(details)
177
177
  if details["source_url"] && details["source_name"]
178
- "*Sourced from [#{details['source_name']}]"\
179
- "(#{details['source_url']}).*\n\n"
178
+ "*Sourced from [#{details['source_name']}]" \
179
+ "(#{details['source_url']}).*\n\n"
180
180
  elsif details["source_name"]
181
181
  "*Sourced from #{details['source_name']}.*\n\n"
182
182
  else
@@ -245,8 +245,6 @@ module Dependabot
245
245
  end
246
246
 
247
247
  def sanitize_links_and_mentions(text, unsafe: false)
248
- return text unless source.provider == "github"
249
-
250
248
  LinkAndMentionSanitizer.
251
249
  new(github_redirection_service: github_redirection_service).
252
250
  sanitize_links_and_mentions(text: text, unsafe: unsafe)
@@ -3,6 +3,7 @@
3
3
  require "pathname"
4
4
  require "dependabot/clients/github_with_retries"
5
5
  require "dependabot/clients/gitlab_with_retries"
6
+ require "dependabot/logger"
6
7
  require "dependabot/metadata_finders"
7
8
  require "dependabot/pull_request_creator"
8
9
  require "dependabot/pull_request_creator/message"
@@ -38,7 +39,12 @@ module Dependabot
38
39
  end
39
40
 
40
41
  def pr_name
41
- pr_name = pr_name_prefixer.pr_name_prefix
42
+ begin
43
+ pr_name = pr_name_prefixer.pr_name_prefix
44
+ rescue StandardError => e
45
+ Dependabot.logger.error("Error while generating PR name: #{e.message}")
46
+ pr_name = ""
47
+ end
42
48
  pr_name += library? ? library_pr_name : application_pr_name
43
49
  return pr_name if files.first.directory == "/"
44
50
 
@@ -48,6 +54,9 @@ module Dependabot
48
54
  def pr_message
49
55
  suffixed_pr_message_header + commit_message_intro + \
50
56
  metadata_cascades + prefixed_pr_message_footer
57
+ rescue StandardError => e
58
+ Dependabot.logger.error("Error while generating PR message: #{e.message}")
59
+ suffixed_pr_message_header + prefixed_pr_message_footer
51
60
  end
52
61
 
53
62
  def commit_message
@@ -56,6 +65,11 @@ module Dependabot
56
65
  message += metadata_links
57
66
  message += "\n\n" + message_trailers if message_trailers
58
67
  message
68
+ rescue StandardError => e
69
+ Dependabot.logger.error("Error while generating commit message: #{e.message}")
70
+ message = commit_subject
71
+ message += "\n\n" + message_trailers if message_trailers
72
+ message
59
73
  end
60
74
 
61
75
  def message
@@ -74,15 +88,20 @@ module Dependabot
74
88
 
75
89
  pr_name +
76
90
  if dependencies.count == 1
77
- "#{dependencies.first.display_name} requirement "\
78
- "#{from_version_msg(old_library_requirement(dependencies.first))}"\
79
- "to #{new_library_requirement(dependencies.first)}"
91
+ "#{dependencies.first.display_name} requirement " \
92
+ "#{from_version_msg(old_library_requirement(dependencies.first))}" \
93
+ "to #{new_library_requirement(dependencies.first)}"
80
94
  else
81
- names = dependencies.map(&:name)
82
- "requirements for #{names[0..-2].join(', ')} and #{names[-1]}"
95
+ names = dependencies.map(&:name).uniq
96
+ if names.count == 1
97
+ "requirements for #{names.first}"
98
+ else
99
+ "requirements for #{names[0..-2].join(', ')} and #{names[-1]}"
100
+ end
83
101
  end
84
102
  end
85
103
 
104
+ # rubocop:disable Metrics/AbcSize
86
105
  def application_pr_name
87
106
  pr_name = "bump "
88
107
  pr_name = pr_name.capitalize if pr_name_prefixer.capitalize_first_word?
@@ -90,24 +109,29 @@ module Dependabot
90
109
  pr_name +
91
110
  if dependencies.count == 1
92
111
  dependency = dependencies.first
93
- "#{dependency.display_name} "\
94
- "#{from_version_msg(previous_version(dependency))}"\
95
- "to #{new_version(dependency)}"
112
+ "#{dependency.display_name} " \
113
+ "#{from_version_msg(previous_version(dependency))}" \
114
+ "to #{new_version(dependency)}"
96
115
  elsif updating_a_property?
97
116
  dependency = dependencies.first
98
- "#{property_name} "\
99
- "#{from_version_msg(previous_version(dependency))}"\
100
- "to #{new_version(dependency)}"
117
+ "#{property_name} " \
118
+ "#{from_version_msg(previous_version(dependency))}" \
119
+ "to #{new_version(dependency)}"
101
120
  elsif updating_a_dependency_set?
102
121
  dependency = dependencies.first
103
- "#{dependency_set.fetch(:group)} dependency set "\
104
- "#{from_version_msg(previous_version(dependency))}"\
105
- "to #{new_version(dependency)}"
122
+ "#{dependency_set.fetch(:group)} dependency set " \
123
+ "#{from_version_msg(previous_version(dependency))}" \
124
+ "to #{new_version(dependency)}"
106
125
  else
107
- names = dependencies.map(&:name)
108
- "#{names[0..-2].join(', ')} and #{names[-1]}"
126
+ names = dependencies.map(&:name).uniq
127
+ if names.count == 1
128
+ names.first
129
+ else
130
+ "#{names[0..-2].join(', ')} and #{names[-1]}"
131
+ end
109
132
  end
110
133
  end
134
+ # rubocop:enable Metrics/AbcSize
111
135
 
112
136
  def pr_name_prefix
113
137
  pr_name_prefixer.pr_name_prefix
@@ -174,8 +198,8 @@ module Dependabot
174
198
  return unless signoff_details.is_a?(Hash)
175
199
  return unless signoff_details[:org_name] && signoff_details[:org_email]
176
200
 
177
- "On-behalf-of: @#{signoff_details[:org_name]} "\
178
- "<#{signoff_details[:org_email]}>"
201
+ "On-behalf-of: @#{signoff_details[:org_name]} " \
202
+ "<#{signoff_details[:org_email]}>"
179
203
  end
180
204
 
181
205
  def requirement_commit_message_intro
@@ -192,16 +216,22 @@ module Dependabot
192
216
  end
193
217
 
194
218
  # rubocop:disable Metrics/PerceivedComplexity
219
+ # rubocop:disable Metrics/AbcSize
195
220
  def version_commit_message_intro
196
221
  return multidependency_property_intro if dependencies.count > 1 && updating_a_property?
197
222
 
198
223
  return dependency_set_intro if dependencies.count > 1 && updating_a_dependency_set?
199
224
 
225
+ return transitive_removed_dependency_intro if dependencies.count > 1 && removing_a_transitive_dependency?
226
+
227
+ return transitive_multidependency_intro if dependencies.count > 1 &&
228
+ updating_top_level_and_transitive_dependencies?
229
+
200
230
  return multidependency_intro if dependencies.count > 1
201
231
 
202
232
  dependency = dependencies.first
203
- msg = "Bumps #{dependency_links.first} "\
204
- "#{from_version_msg(previous_version(dependency))}"\
233
+ msg = "Bumps #{dependency_links.first} " \
234
+ "#{from_version_msg(previous_version(dependency))}" \
205
235
  "to #{new_version(dependency)}."
206
236
 
207
237
  msg += " This release includes the previously tagged commit." if switching_from_ref_to_release?(dependency)
@@ -216,27 +246,60 @@ module Dependabot
216
246
  end
217
247
 
218
248
  # rubocop:enable Metrics/PerceivedComplexity
249
+ # rubocop:enable Metrics/AbcSize
219
250
 
220
251
  def multidependency_property_intro
221
252
  dependency = dependencies.first
222
253
 
223
- "Bumps `#{property_name}` "\
224
- "#{from_version_msg(previous_version(dependency))}"\
225
- "to #{new_version(dependency)}."
254
+ "Bumps `#{property_name}` " \
255
+ "#{from_version_msg(previous_version(dependency))}" \
256
+ "to #{new_version(dependency)}."
226
257
  end
227
258
 
228
259
  def dependency_set_intro
229
260
  dependency = dependencies.first
230
261
 
231
- "Bumps `#{dependency_set.fetch(:group)}` "\
232
- "dependency set #{from_version_msg(previous_version(dependency))}"\
233
- "to #{new_version(dependency)}."
262
+ "Bumps `#{dependency_set.fetch(:group)}` " \
263
+ "dependency set #{from_version_msg(previous_version(dependency))}" \
264
+ "to #{new_version(dependency)}."
234
265
  end
235
266
 
236
267
  def multidependency_intro
237
- "Bumps #{dependency_links[0..-2].join(', ')} "\
238
- "and #{dependency_links[-1]}. These "\
239
- "dependencies needed to be updated together."
268
+ "Bumps #{dependency_links[0..-2].join(', ')} " \
269
+ "and #{dependency_links[-1]}. These " \
270
+ "dependencies needed to be updated together."
271
+ end
272
+
273
+ def transitive_multidependency_intro
274
+ dependency = dependencies.first
275
+
276
+ msg = "Bumps #{dependency_links[0]} to #{new_version(dependency)}"
277
+
278
+ msg += if dependencies.count > 2
279
+ " and updates ancestor dependencies #{dependency_links[0..-2].join(', ')} " \
280
+ "and #{dependency_links[-1]}. "
281
+ else
282
+ " and updates ancestor dependency #{dependency_links[1]}. "
283
+ end
284
+
285
+ msg += "These dependencies need to be updated together.\n"
286
+
287
+ msg
288
+ end
289
+
290
+ def transitive_removed_dependency_intro
291
+ msg = "Removes #{dependency_links[0]}. It's no longer used after updating"
292
+
293
+ msg += if dependencies.count > 2
294
+ " ancestor dependencies #{dependency_links[0..-2].join(', ')} " \
295
+ "and #{dependency_links[-1]}. "
296
+ else
297
+ " ancestor dependency #{dependency_links[1]}. "
298
+ end
299
+
300
+ msg += "These dependencies need to be updated together.\n"
301
+
302
+ msg
240
303
  end
241
304
 
242
305
  def from_version_msg(previous_version)
@@ -257,6 +320,15 @@ module Dependabot
257
320
  any? { |r| r.dig(:metadata, :dependency_set) }
258
321
  end
259
322
 
323
+ def removing_a_transitive_dependency?
324
+ dependencies.any?(&:removed?)
325
+ end
326
+
327
+ def updating_top_level_and_transitive_dependencies?
328
+ dependencies.any?(&:top_level?) &&
329
+ dependencies.any? { |dep| !dep.top_level? }
330
+ end
331
+
260
332
  def property_name
261
333
  @property_name ||= dependencies.first.requirements.
262
334
  find { |r| r.dig(:metadata, :property_name) }&.
@@ -296,10 +368,10 @@ module Dependabot
296
368
  if dep.removed?
297
369
  "\n\nRemoves `#{dep.display_name}`"
298
370
  else
299
- "\n\nUpdates `#{dep.display_name}` "\
300
- "#{from_version_msg(previous_version(dep))}to "\
301
- "#{new_version(dep)}"\
302
- "#{metadata_links_for_dep(dep)}"
371
+ "\n\nUpdates `#{dep.display_name}` " \
372
+ "#{from_version_msg(previous_version(dep))}to " \
373
+ "#{new_version(dep)}" \
374
+ "#{metadata_links_for_dep(dep)}"
303
375
  end
304
376
  end.join
305
377
  end
@@ -318,11 +390,11 @@ module Dependabot
318
390
 
319
391
  dependencies.map do |dep|
320
392
  msg = if dep.removed?
321
- "\nRemoves `#{dep.display_name}`"
393
+ "\nRemoves `#{dep.display_name}`\n"
322
394
  else
323
- "\nUpdates `#{dep.display_name}` "\
324
- "#{from_version_msg(previous_version(dep))}"\
325
- "to #{new_version(dep)}"
395
+ "\nUpdates `#{dep.display_name}` " \
396
+ "#{from_version_msg(previous_version(dep))}" \
397
+ "to #{new_version(dep)}"
326
398
  end
327
399
 
328
400
  if vulnerabilities_fixed[dep.name]&.one?
@@ -427,21 +499,21 @@ module Dependabot
427
499
 
428
500
  def docker_digest_from_reqs(requirements)
429
501
  requirements.
430
- map { |r| r.dig(:source, "digest") || r.dig(:source, :digest) }.
431
- compact.first
502
+ filter_map { |r| r.dig(:source, "digest") || r.dig(:source, :digest) }.
503
+ first
432
504
  end
433
505
 
434
506
  def previous_ref(dependency)
435
- previous_refs = dependency.previous_requirements.map do |r|
507
+ previous_refs = dependency.previous_requirements.filter_map do |r|
436
508
  r.dig(:source, "ref") || r.dig(:source, :ref)
437
- end.compact.uniq
509
+ end.uniq
438
510
  return previous_refs.first if previous_refs.count == 1
439
511
  end
440
512
 
441
513
  def new_ref(dependency)
442
- new_refs = dependency.requirements.map do |r|
514
+ new_refs = dependency.requirements.filter_map do |r|
443
515
  r.dig(:source, "ref") || r.dig(:source, :ref)
444
- end.compact.uniq
516
+ end.uniq
445
517
  return new_refs.first if new_refs.count == 1
446
518
  end
447
519
 
@@ -493,7 +565,7 @@ module Dependabot
493
565
 
494
566
  def switching_from_ref_to_release?(dependency)
495
567
  unless dependency.previous_version&.match?(/^[0-9a-f]{40}$/) ||
496
- dependency.previous_version.nil? && previous_ref(dependency)
568
+ (dependency.previous_version.nil? && previous_ref(dependency))
497
569
  return false
498
570
  end
499
571
 
@@ -43,11 +43,12 @@ module Dependabot
43
43
  end
44
44
 
45
45
  def capitalize_first_word?
46
- return !commit_message_options[:prefix]&.strip&.match?(/\A[a-z]/) if commit_message_options.key?(:prefix)
47
-
48
46
  return capitalise_first_word_from_last_dependabot_commit_style if last_dependabot_commit_style
49
47
 
50
48
  capitalise_first_word_from_previous_commits
49
+ rescue StandardError
50
+ # ignoring failure due to network call to find out if the PR should be capitalized
51
+ false
51
52
  end
52
53
 
53
54
  private
@@ -280,8 +281,7 @@ module Dependabot
280
281
  reject { |c| c.author&.type == "Bot" }.
281
282
  reject { |c| c.commit&.message&.start_with?("Merge") }.
282
283
  map(&:commit).
283
- map(&:message).
284
- compact.
284
+ filter_map(&:message).
285
285
  map(&:strip)
286
286
  end
287
287
 
@@ -292,8 +292,7 @@ module Dependabot
292
292
  @recent_gitlab_commit_messages.
293
293
  reject { |c| c.author_email == dependabot_email }.
294
294
  reject { |c| c.message&.start_with?("merge !") }.
295
- map(&:message).
296
- compact.
295
+ filter_map(&:message).
297
296
  map(&:strip)
298
297
  end
299
298
 
@@ -304,8 +303,7 @@ module Dependabot
304
303
  @recent_azure_commit_messages.
305
304
  reject { |c| azure_commit_author_email(c) == dependabot_email }.
306
305
  reject { |c| c.fetch("comment")&.start_with?("Merge") }.
307
- map { |c| c.fetch("comment") }.
308
- compact.
306
+ filter_map { |c| c.fetch("comment") }.
309
307
  map(&:strip)
310
308
  end
311
309
 
@@ -315,8 +313,7 @@ module Dependabot
315
313
 
316
314
  @recent_bitbucket_commit_messages.
317
315
  reject { |c| bitbucket_commit_author_email(c) == dependabot_email }.
318
- map { |c| c.fetch("message", nil) }.
319
- compact.
316
+ filter_map { |c| c.fetch("message", nil) }.
320
317
  reject { |m| m.start_with?("Merge") }.
321
318
  map(&:strip)
322
319
  end
@@ -327,8 +324,7 @@ module Dependabot
327
324
  @recent_codecommit_commit_messages.commits.
328
325
  reject { |c| c.author.email == dependabot_email }.
329
326
  reject { |c| c.message&.start_with?("Merge") }.
330
- map(&:message).
331
- compact.
327
+ filter_map(&:message).
332
328
  map(&:strip)
333
329
  end
334
330
 
@@ -48,7 +48,7 @@ module Dependabot
48
48
  :custom_labels, :author_details, :signature_key,
49
49
  :commit_message_options, :vulnerabilities_fixed,
50
50
  :reviewers, :assignees, :milestone, :branch_name_separator,
51
- :branch_name_prefix, :github_redirection_service,
51
+ :branch_name_prefix, :branch_name_max_length, :github_redirection_service,
52
52
  :custom_headers, :provider_metadata
53
53
 
54
54
  def initialize(source:, base_commit:, dependencies:, files:, credentials:,
@@ -57,7 +57,8 @@ module Dependabot
57
57
  commit_message_options: {}, vulnerabilities_fixed: {},
58
58
  reviewers: nil, assignees: nil, milestone: nil,
59
59
  branch_name_separator: "/", branch_name_prefix: "dependabot",
60
- label_language: false, automerge_candidate: false,
60
+ branch_name_max_length: nil, label_language: false,
61
+ automerge_candidate: false,
61
62
  github_redirection_service: DEFAULT_GITHUB_REDIRECTION_SERVICE,
62
63
  custom_headers: nil, require_up_to_date_base: false,
63
64
  provider_metadata: {}, message: nil)
@@ -78,6 +79,7 @@ module Dependabot
78
79
  @vulnerabilities_fixed = vulnerabilities_fixed
79
80
  @branch_name_separator = branch_name_separator
80
81
  @branch_name_prefix = branch_name_prefix
82
+ @branch_name_max_length = branch_name_max_length
81
83
  @label_language = label_language
82
84
  @automerge_candidate = automerge_candidate
83
85
  @github_redirection_service = github_redirection_service
@@ -232,7 +234,8 @@ module Dependabot
232
234
  files: files,
233
235
  target_branch: source.branch,
234
236
  separator: branch_name_separator,
235
- prefix: branch_name_prefix
237
+ prefix: branch_name_prefix,
238
+ max_length: branch_name_max_length
236
239
  )
237
240
  end
238
241
 
@@ -53,7 +53,7 @@ module Dependabot
53
53
  end
54
54
 
55
55
  # Currently the PR diff in ADO shows difference in commits instead of actual diff in files.
56
- # This workaround is done to get the target branch commit history on the source branch alongwith file changes
56
+ # This workaround puts the target branch commit history on the source branch along with the file changes.
57
57
  def update_source_branch
58
58
  # 1) Push the file changes to a newly created temporary branch (from base commit)
59
59
  new_commit = create_temp_branch
@@ -173,7 +173,7 @@ module Dependabot
173
173
 
174
174
  if e.message.match?(/protected branch/i) ||
175
175
  e.message.match?(/not authorized to push/i) ||
176
- e.message.match?(/must not contain merge commits/) ||
176
+ e.message.include?("must not contain merge commits") ||
177
177
  e.message.match?(/required status check/i)
178
178
  raise BranchProtected
179
179
  end
@@ -182,28 +182,31 @@ module Dependabot
182
182
  end
183
183
 
184
184
  def commit_message
185
- # Take the commit message from the old commit
186
- commit_being_updated.message
185
+ fallback_message =
186
+ "#{pull_request.title}" \
187
+ "\n\n" \
188
+ "Dependabot couldn't find the original pull request head commit, " \
189
+ "#{old_commit}."
190
+
191
+ # Take the commit message from the old commit. If the old commit can't
192
+ # be found, use the PR title as the commit message.
193
+ commit_being_updated&.message || fallback_message
187
194
  end
188
195
 
189
196
  def commit_being_updated
190
- @commit_being_updated ||=
197
+ return @commit_being_updated if defined?(@commit_being_updated)
198
+
199
+ @commit_being_updated =
191
200
  if pull_request.commits == 1
192
201
  github_client_for_source.
193
202
  git_commit(source.repo, pull_request.head.sha)
194
203
  else
195
- author_name = author_details&.fetch(:name, nil) || "dependabot"
196
204
  commits =
197
205
  github_client_for_source.
198
- pull_request_commits(source.repo, pull_request_number).
199
- reverse
200
-
201
- commit =
202
- commits.find { |c| c.sha == old_commit } ||
203
- commits.find { |c| c.commit.author.name.include?(author_name) } ||
204
- commits.first
206
+ pull_request_commits(source.repo, pull_request_number)
205
207
 
206
- commit.commit
208
+ commit = commits.find { |c| c.sha == old_commit }
209
+ commit&.commit
207
210
  end
208
211
  end
209
212
 
@@ -69,7 +69,8 @@ module Dependabot
69
69
  old_commit: old_commit,
70
70
  files: files,
71
71
  credentials: credentials,
72
- pull_request_number: pull_request_number
72
+ pull_request_number: pull_request_number,
73
+ author_details: author_details
73
74
  )
74
75
  end
75
76
  end
@@ -51,7 +51,7 @@ module Dependabot
51
51
  # @return [Boolean]
52
52
  def fixed_by?(dependency)
53
53
  # Handle case mismatch between the security advisory and parsed name
54
- return false unless dependency_name.downcase == dependency.name.downcase
54
+ return false unless dependency_name.casecmp(dependency.name).zero?
55
55
  return false unless package_manager == dependency.package_manager
56
56
  # TODO: Support no previous version to the same level as dependency graph
57
57
  # and security alerts. We currently ignore dependency updates without a
@@ -112,13 +112,13 @@ module Dependabot
112
112
  def check_version_requirements
113
113
  unless vulnerable_versions.is_a?(Array) &&
114
114
  vulnerable_versions.all? { |i| requirement_class <= i.class }
115
- raise ArgumentError, "vulnerable_versions must be an array "\
115
+ raise ArgumentError, "vulnerable_versions must be an array " \
116
116
  "of #{requirement_class} instances"
117
117
  end
118
118
 
119
119
  unless safe_versions.is_a?(Array) &&
120
120
  safe_versions.all? { |i| requirement_class <= i.class }
121
- raise ArgumentError, "safe_versions must be an array "\
121
+ raise ArgumentError, "safe_versions must be an array " \
122
122
  "of #{requirement_class} instances"
123
123
  end
124
124
  end