dependabot-common 0.213.0 → 0.214.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 23fa5c7ea872ca0849f22018af9b0811ad9044f03a4e7d59aa023b3dd80bd4e6
4
- data.tar.gz: cea778ebef75ccec5afcd3e5932af78d9711c51c4c864ea02d65930fce8ca4dc
3
+ metadata.gz: 1fab7bc375e03e37b65e94e3e05e7c9ad945d982295b6c9a030083ed038dbaf3
4
+ data.tar.gz: 9924a1980357d1833988bd19a8119a05162a28cc20cbdf157626744ef93be0ba
5
5
  SHA512:
6
- metadata.gz: b14ad55cbabd2a49bd35c7f8012f95972515eead80a71363353a8978286e9d756fd97da5442cb3013acdebfb1a77c7f8f7c450bac553a2d6f52b12687fcf2d43
7
- data.tar.gz: 86cbba3afb724d1ee0b6c1fd0bb357a33c288263b3032e0ef029e099b5d7f7d8d5104526a8890d6233fdb8850b56ecd05cb0746bd8e6fe8fd84338db8caa28dd
6
+ metadata.gz: 88069b0acbe42180a064046ab55cba565da0f9a3e00d40582a3fb406aee9e3b357cf8e3bdf34dc84da959c931c1519a87e02022e994baf947193f7d6fb949be8
7
+ data.tar.gz: 785cddd10adbed3413e7fdfcbfcc9b5fa00fde7a55f6e171db0c62f4e4a9f17000dc06d7e4c75d312fda6c7801e9fa6428642ea2b3473dc1b4d7f14e0a660bff
@@ -172,7 +172,8 @@ module Dependabot
172
172
 
173
173
  # rubocop:disable Metrics/ParameterLists
174
174
  def create_pull_request(pr_name, source_branch, target_branch,
175
- pr_description, labels, work_item = nil)
175
+ pr_description, labels,
176
+ reviewers = nil, assignees = nil, work_item = nil)
176
177
  pr_description = truncate_pr_description(pr_description)
177
178
 
178
179
  content = {
@@ -181,6 +182,7 @@ module Dependabot
181
182
  title: pr_name,
182
183
  description: pr_description,
183
184
  labels: labels.map { |label| { name: label } },
185
+ reviewers: pr_reviewers(reviewers, assignees),
184
186
  workItemRefs: [{ id: work_item }]
185
187
  }
186
188
 
@@ -324,6 +326,13 @@ module Dependabot
324
326
  message&.include?("TF401289")
325
327
  end
326
328
 
329
+ def pr_reviewers(reviewers, assignees)
330
+ return [] unless reviewers || assignees
331
+
332
+ pr_reviewers = reviewers&.map { |r_id| { id: r_id, isRequired: true } } || []
333
+ pr_reviewers + (assignees&.map { |r_id| { id: r_id, isRequired: false } } || [])
334
+ end
335
+
327
336
  attr_reader :auth_header
328
337
  attr_reader :credentials
329
338
  attr_reader :source
@@ -12,6 +12,8 @@ module Dependabot
12
12
 
13
13
  class Forbidden < StandardError; end
14
14
 
15
+ class TimedOut < StandardError; end
16
+
15
17
  #######################
16
18
  # Constructor methods #
17
19
  #######################
@@ -79,19 +81,24 @@ module Dependabot
79
81
  JSON.parse(response.body)
80
82
  end
81
83
 
82
- def pull_requests(repo, source_branch, target_branch)
83
- pr_path = "#{repo}/pullrequests"
84
- # Get pull requests with any status
85
- pr_path += "?status=OPEN&status=MERGED&status=DECLINED&status=SUPERSEDED"
84
+ def pull_requests(repo, source_branch, target_branch, status = %w(OPEN MERGED DECLINED SUPERSEDED))
85
+ pr_path = "#{repo}/pullrequests?"
86
+ # Get pull requests with given status
87
+ status.each { |n| pr_path += "status=#{n}&" }
86
88
  next_page_url = base_url + pr_path
87
89
  pull_requests = paginate({ "next" => next_page_url })
88
90
 
89
91
  pull_requests unless source_branch && target_branch
90
92
 
91
93
  pull_requests.select do |pr|
92
- pr_source_branch = pr.fetch("source").fetch("branch").fetch("name")
94
+ if source_branch.nil?
95
+ source_branch_matches = true
96
+ else
97
+ pr_source_branch = pr.fetch("source").fetch("branch").fetch("name")
98
+ source_branch_matches = pr_source_branch == source_branch
99
+ end
93
100
  pr_target_branch = pr.fetch("destination").fetch("branch").fetch("name")
94
- pr_source_branch == source_branch && pr_target_branch == target_branch
101
+ source_branch_matches && pr_target_branch == target_branch
95
102
  end
96
103
  end
97
104
 
@@ -106,8 +113,7 @@ module Dependabot
106
113
  }
107
114
 
108
115
  files.each do |file|
109
- absolute_path = file.name.start_with?("/") ? file.name : "/" + file.name
110
- parameters[absolute_path] = file.content
116
+ parameters[file.path] = file.content
111
117
  end
112
118
 
113
119
  body = encode_form_parameters(parameters)
@@ -144,6 +150,23 @@ module Dependabot
144
150
  end
145
151
  # rubocop:enable Metrics/ParameterLists
146
152
 
153
+ def decline_pull_request(repo, pr_id, comment = nil)
154
+ # https://developer.atlassian.com/cloud/bitbucket/rest/api-group-pullrequests/
155
+ decline_path = "#{repo}/pullrequests/#{pr_id}/decline"
156
+ post(base_url + decline_path, "")
157
+
158
+ comment = "Dependabot declined the pull request." if comment.nil?
159
+
160
+ content = {
161
+ content: {
162
+ raw: comment
163
+ }
164
+ }
165
+
166
+ comment_path = "#{repo}/pullrequests/#{pr_id}/comments"
167
+ post(base_url + comment_path, content.to_json)
168
+ end
169
+
147
170
  def current_user
148
171
  base_url = "https://api.bitbucket.org/2.0/user?fields=uuid"
149
172
  response = get(base_url)
@@ -205,6 +228,14 @@ module Dependabot
205
228
  end
206
229
 
207
230
  def post(url, body, content_type = "application/json")
231
+ headers = auth_header
232
+
233
+ headers = if body.empty?
234
+ headers.merge({ "Accept" => "application/json" })
235
+ else
236
+ headers.merge({ "Content-Type" => content_type })
237
+ end
238
+
208
239
  response = Excon.post(
209
240
  url,
210
241
  body: body,
@@ -212,16 +243,13 @@ module Dependabot
212
243
  password: credentials&.fetch("password", nil),
213
244
  idempotent: false,
214
245
  **SharedHelpers.excon_defaults(
215
- headers: auth_header.merge(
216
- {
217
- "Content-Type" => content_type
218
- }
219
- )
246
+ headers: headers
220
247
  )
221
248
  )
222
249
  raise Unauthorized if response.status == 401
223
250
  raise Forbidden if response.status == 403
224
251
  raise NotFound if response.status == 404
252
+ raise TimedOut if response.status == 555
225
253
 
226
254
  response
227
255
  end
@@ -84,7 +84,16 @@ module Dependabot
84
84
  access_tokens << nil if access_tokens.empty?
85
85
  access_tokens.uniq!
86
86
 
87
- @max_retries = max_retries || 3
87
+ Octokit.middleware = Faraday::RackBuilder.new do |builder|
88
+ builder.use Faraday::Retry::Middleware, exceptions: RETRYABLE_ERRORS, max: max_retries || 3
89
+
90
+ Octokit::Default::MIDDLEWARE.handlers.each do |handler|
91
+ next if handler.klass == Faraday::Retry::Middleware
92
+
93
+ builder.use handler.klass
94
+ end
95
+ end
96
+
88
97
  @clients = access_tokens.map do |token|
89
98
  Octokit::Client.new(args.merge(access_token: token))
90
99
  end
@@ -95,13 +104,11 @@ module Dependabot
95
104
  client = untried_clients.pop
96
105
 
97
106
  begin
98
- retry_connection_failures do
99
- if client.respond_to?(method_name)
100
- mutatable_args = args.map(&:dup)
101
- client.public_send(method_name, *mutatable_args, &block)
102
- else
103
- super
104
- end
107
+ if client.respond_to?(method_name)
108
+ mutatable_args = args.map(&:dup)
109
+ client.public_send(method_name, *mutatable_args, &block)
110
+ else
111
+ super
105
112
  end
106
113
  rescue Octokit::NotFound, Octokit::Unauthorized, Octokit::Forbidden
107
114
  raise unless (client = untried_clients.pop)
@@ -113,17 +120,6 @@ module Dependabot
113
120
  def respond_to_missing?(method_name, include_private = false)
114
121
  @clients.first.respond_to?(method_name) || super
115
122
  end
116
-
117
- def retry_connection_failures
118
- retry_attempt = 0
119
-
120
- begin
121
- yield
122
- rescue *RETRYABLE_ERRORS
123
- retry_attempt += 1
124
- retry_attempt <= @max_retries ? retry : raise
125
- end
126
- end
127
123
  end
128
124
  end
129
125
  end
@@ -67,6 +67,10 @@ module Dependabot
67
67
  @removed
68
68
  end
69
69
 
70
+ def numeric_version
71
+ @numeric_version ||= version_class.new(version) if version && version_class.correct?(version)
72
+ end
73
+
70
74
  def to_h
71
75
  {
72
76
  "name" => name,
@@ -136,6 +140,10 @@ module Dependabot
136
140
 
137
141
  private
138
142
 
143
+ def version_class
144
+ Utils.version_class_for_package_manager(package_manager)
145
+ end
146
+
139
147
  def check_values
140
148
  raise ArgumentError, "blank strings must not be provided as versions" if [version, previous_version].any?("")
141
149
 
@@ -5,7 +5,7 @@ require "pathname"
5
5
  module Dependabot
6
6
  class DependencyFile
7
7
  attr_accessor :name, :content, :directory, :type, :support_file,
8
- :symlink_target, :content_encoding, :operation
8
+ :symlink_target, :content_encoding, :operation, :mode
9
9
 
10
10
  class ContentEncoding
11
11
  UTF_8 = "utf-8"
@@ -20,7 +20,8 @@ module Dependabot
20
20
 
21
21
  def initialize(name:, content:, directory: "/", type: "file",
22
22
  support_file: false, symlink_target: nil,
23
- content_encoding: ContentEncoding::UTF_8, deleted: false, operation: Operation::UPDATE)
23
+ content_encoding: ContentEncoding::UTF_8, deleted: false,
24
+ operation: Operation::UPDATE, mode: nil)
24
25
  @name = name
25
26
  @content = content
26
27
  @directory = clean_directory(directory)
@@ -40,6 +41,12 @@ module Dependabot
40
41
  # support_file flag instead)
41
42
  @type = type
42
43
 
44
+ begin
45
+ @mode = File.stat((symlink_target || path).sub(%r{^/}, "")).mode.to_s(8)
46
+ rescue StandardError
47
+ @mode = mode
48
+ end
49
+
43
50
  return unless (type == "symlink") ^ symlink_target
44
51
 
45
52
  raise "Symlinks must specify a target!" unless symlink_target
@@ -55,7 +62,8 @@ module Dependabot
55
62
  "support_file" => support_file,
56
63
  "content_encoding" => content_encoding,
57
64
  "deleted" => deleted,
58
- "operation" => operation
65
+ "operation" => operation,
66
+ "mode" => mode
59
67
  }
60
68
 
61
69
  details["symlink_target"] = symlink_target if symlink_target
@@ -26,6 +26,12 @@ module Dependabot
26
26
  Dependabot::Clients::CodeCommit::NotFound
27
27
  ].freeze
28
28
 
29
+ GIT_SUBMODULE_INACCESSIBLE_ERROR =
30
+ /^fatal: unable to access '(?<url>.*)': The requested URL returned error: (?<code>\d+)$/
31
+ GIT_SUBMODULE_CLONE_ERROR =
32
+ /^fatal: clone of '(?<url>.*)' into submodule path '.*' failed$/
33
+ GIT_SUBMODULE_ERROR_REGEX = /(#{GIT_SUBMODULE_INACCESSIBLE_ERROR})|(#{GIT_SUBMODULE_CLONE_ERROR})/
34
+
29
35
  def self.required_files_in?(_filename_array)
30
36
  raise NotImplementedError
31
37
  end
@@ -592,11 +598,26 @@ module Dependabot
592
598
  " --no-recurse-submodules"
593
599
  end
594
600
  clone_options << " --branch #{source.branch} --single-branch" if source.branch
595
- SharedHelpers.run_shell_command(
596
- <<~CMD
597
- git clone #{clone_options.string} #{source.url} #{path}
598
- CMD
599
- )
601
+
602
+ submodule_cloning_failed = false
603
+ begin
604
+ SharedHelpers.run_shell_command(
605
+ <<~CMD
606
+ git clone #{clone_options.string} #{source.url} #{path}
607
+ CMD
608
+ )
609
+ rescue SharedHelpers::HelperSubprocessFailed => e
610
+ raise unless GIT_SUBMODULE_ERROR_REGEX && e.message.downcase.include?("submodule")
611
+
612
+ submodule_cloning_failed = true
613
+ match = e.message.match(GIT_SUBMODULE_ERROR_REGEX)
614
+ url = match.named_captures["url"]
615
+ code = match.named_captures["code"]
616
+
617
+ # Submodules might be in the repo but unrelated to dependencies,
618
+ # so ignoring this error to try the update anyway since the base repo exists.
619
+ Dependabot.logger.error("Cloning of submodule failed: #{url} error: #{code || 'unknown'}")
620
+ end
600
621
 
601
622
  if source.commit
602
623
  # This code will only be called for testing. Production will never pass a commit
@@ -604,7 +625,7 @@ module Dependabot
604
625
  Dir.chdir(path) do
605
626
  fetch_options = StringIO.new
606
627
  fetch_options << "--depth 1"
607
- fetch_options << if recurse_submodules_when_cloning?
628
+ fetch_options << if recurse_submodules_when_cloning? && !submodule_cloning_failed
608
629
  " --recurse-submodules=on-demand"
609
630
  else
610
631
  " --no-recurse-submodules"
@@ -614,7 +635,7 @@ module Dependabot
614
635
 
615
636
  reset_options = StringIO.new
616
637
  reset_options << "--hard"
617
- reset_options << if recurse_submodules_when_cloning?
638
+ reset_options << if recurse_submodules_when_cloning? && !submodule_cloning_failed
618
639
  " --recurse-submodules"
619
640
  else
620
641
  " --no-recurse-submodules"
@@ -23,13 +23,12 @@ module Dependabot
23
23
 
24
24
  def initialize(dependency:, credentials:,
25
25
  ignored_versions: [], raise_on_ignored: false,
26
- requirement_class: nil, version_class: nil)
26
+ consider_version_branches_pinned: false)
27
27
  @dependency = dependency
28
28
  @credentials = credentials
29
29
  @ignored_versions = ignored_versions
30
30
  @raise_on_ignored = raise_on_ignored
31
- @requirement_class = requirement_class
32
- @version_class = version_class
31
+ @consider_version_branches_pinned = consider_version_branches_pinned
33
32
  end
34
33
 
35
34
  def git_dependency?
@@ -52,17 +51,17 @@ module Dependabot
52
51
  # If the specified `ref` is actually a tag, we're pinned
53
52
  return true if local_upload_pack.match?(%r{ refs/tags/#{ref}$})
54
53
 
55
- # If the specified `ref` is actually a branch, we're NOT pinned
56
- return false if local_upload_pack.match?(%r{ refs/heads/#{ref}$})
54
+ # Assume we're pinned unless the specified `ref` is actually a branch
55
+ return true unless local_upload_pack.match?(%r{ refs/heads/#{ref}$})
57
56
 
58
- # Otherwise, assume we're pinned
59
- true
57
+ # TODO: Research whether considering branches that look like versions pinned makes sense for all ecosystems
58
+ @consider_version_branches_pinned && version_tag?(ref)
60
59
  end
61
60
 
62
61
  def pinned_ref_looks_like_version?
63
62
  return false unless pinned?
64
63
 
65
- dependency_source_details.fetch(:ref).match?(VERSION_REGEX)
64
+ version_tag?(dependency_source_details.fetch(:ref))
66
65
  end
67
66
 
68
67
  def pinned_ref_looks_like_commit_sha?
@@ -70,6 +69,11 @@ module Dependabot
70
69
  ref_looks_like_commit_sha?(ref)
71
70
  end
72
71
 
72
+ def head_commit_for_pinned_ref
73
+ ref = dependency_source_details.fetch(:ref)
74
+ local_repo_git_metadata_fetcher.head_commit_for_ref_sha(ref)
75
+ end
76
+
73
77
  def ref_looks_like_commit_sha?(ref)
74
78
  return false unless ref&.match?(/^[0-9a-f]{6,40}$/)
75
79
 
@@ -85,13 +89,8 @@ module Dependabot
85
89
  def head_commit_for_current_branch
86
90
  ref = ref_or_branch || "HEAD"
87
91
 
88
- if pinned?
89
- return dependency.version ||
90
- local_repo_git_metadata_fetcher.head_commit_for_ref(ref)
91
- end
92
-
93
- sha = local_repo_git_metadata_fetcher.head_commit_for_ref(ref)
94
- return sha if sha
92
+ sha = head_commit_for_local_branch(ref)
93
+ return sha if pinned? || sha
95
94
 
96
95
  raise Dependabot::GitDependencyReferenceNotFound, dependency.name
97
96
  end
@@ -100,75 +99,45 @@ module Dependabot
100
99
  local_repo_git_metadata_fetcher.head_commit_for_ref(name)
101
100
  end
102
101
 
103
- def local_tags_for_latest_version_commit_sha
104
- tags = allowed_version_tags
105
- max_tag = max_version_tag(tags)
106
-
107
- return [] unless max_tag
102
+ def local_tag_for_latest_version_matching_existing_precision
103
+ max_local_tag_for_current_precision(allowed_version_tags)
104
+ end
108
105
 
109
- tags.
110
- select { |t| t.commit_sha == max_tag.commit_sha }.
111
- map do |t|
112
- version = t.name.match(VERSION_REGEX).named_captures.fetch("version")
113
- {
114
- tag: t.name,
115
- version: version_class.new(version),
116
- commit_sha: t.commit_sha,
117
- tag_sha: t.tag_sha
118
- }
119
- end
106
+ def local_ref_for_latest_version_matching_existing_precision
107
+ max_local_tag_for_current_precision(allowed_version_refs)
120
108
  end
121
109
 
122
110
  def local_tag_for_latest_version
123
- tag = max_version_tag(allowed_version_tags)
124
-
125
- return unless tag
111
+ max_local_tag(allowed_version_tags)
112
+ end
126
113
 
127
- version = tag.name.match(VERSION_REGEX).named_captures.fetch("version")
128
- {
129
- tag: tag.name,
130
- version: version_class.new(version),
131
- commit_sha: tag.commit_sha,
132
- tag_sha: tag.tag_sha
133
- }
114
+ def local_tags_for_allowed_versions_matching_existing_precision
115
+ select_matching_existing_precision(allowed_version_tags).map { |t| to_local_tag(t) }
134
116
  end
135
117
 
136
- def max_version_tag(tags)
137
- tags.
138
- max_by do |t|
139
- version = t.name.match(VERSION_REGEX).named_captures.
140
- fetch("version")
141
- version_class.new(version)
142
- end
118
+ def local_tags_for_allowed_versions
119
+ allowed_version_tags.map { |t| to_local_tag(t) }
143
120
  end
144
121
 
145
122
  def allowed_version_tags
146
- tags =
147
- local_tags.
148
- select { |t| version_tag?(t.name) && matches_existing_prefix?(t.name) }
149
- filtered = tags.
150
- reject { |t| tag_included_in_ignore_requirements?(t) }
151
- if @raise_on_ignored && filter_lower_versions(filtered).empty? && filter_lower_versions(tags).any?
152
- raise Dependabot::AllVersionsIgnored
153
- end
123
+ allowed_versions(local_tags)
124
+ end
154
125
 
155
- filtered.
156
- reject { |t| tag_is_prerelease?(t) && !wants_prerelease? }
126
+ def allowed_version_refs
127
+ allowed_versions(local_refs)
157
128
  end
158
129
 
159
130
  def current_version
160
131
  return unless dependency.version && version_tag?(dependency.version)
161
132
 
162
- version = dependency.version.match(VERSION_REGEX).named_captures.fetch("version")
163
- version_class.new(version)
133
+ version_from_ref(dependency.version)
164
134
  end
165
135
 
166
136
  def filter_lower_versions(tags)
167
137
  return tags unless current_version
168
138
 
169
139
  versions = tags.map do |t|
170
- version = t.name.match(VERSION_REGEX).named_captures.fetch("version")
171
- version_class.new(version)
140
+ version_from_tag(t)
172
141
  end
173
142
 
174
143
  versions.select do |version|
@@ -176,15 +145,14 @@ module Dependabot
176
145
  end
177
146
  end
178
147
 
179
- def local_tag_for_pinned_version
180
- return unless pinned?
181
-
182
- ref = dependency_source_details.fetch(:ref)
183
- tags = local_tags.select { |t| t.commit_sha == ref && version_class.correct?(t.name) }.
184
- sort_by { |t| version_class.new(t.name) }
185
- return if tags.empty?
148
+ def most_specific_tag_equivalent_to_pinned_ref
149
+ commit_sha = head_commit_for_local_branch(dependency_source_details.fetch(:ref))
150
+ most_specific_version_tag_for_sha(commit_sha)
151
+ end
186
152
 
187
- tags[-1].name
153
+ def local_tag_for_pinned_sha
154
+ commit_sha = dependency_source_details.fetch(:ref)
155
+ most_specific_version_tag_for_sha(commit_sha)
188
156
  end
189
157
 
190
158
  def git_repo_reachable?
@@ -198,6 +166,49 @@ module Dependabot
198
166
 
199
167
  attr_reader :dependency, :credentials, :ignored_versions
200
168
 
169
+ def max_local_tag_for_current_precision(tags)
170
+ max_local_tag(select_matching_existing_precision(tags))
171
+ end
172
+
173
+ def max_local_tag(tags)
174
+ max_version_tag = tags.max_by { |t| version_from_tag(t) }
175
+
176
+ to_local_tag(max_version_tag)
177
+ end
178
+
179
+ # Find the latest version with the same precision as the pinned version.
180
+ def select_matching_existing_precision(tags)
181
+ current_precision = precision(dependency.version)
182
+
183
+ tags.select { |tag| precision(scan_version(tag.name)) == current_precision }
184
+ end
185
+
186
+ def precision(version)
187
+ version.split(".").length
188
+ end
189
+
190
+ def most_specific_version_tag_for_sha(commit_sha)
191
+ tags = local_tags.select { |t| t.commit_sha == commit_sha && version_class.correct?(t.name) }.
192
+ sort_by { |t| version_class.new(t.name) }
193
+ return if tags.empty?
194
+
195
+ tags[-1].name
196
+ end
197
+
198
+ def allowed_versions(local_tags)
199
+ tags =
200
+ local_tags.
201
+ select { |t| version_tag?(t.name) && matches_existing_prefix?(t.name) }
202
+ filtered = tags.
203
+ reject { |t| tag_included_in_ignore_requirements?(t) }
204
+ if @raise_on_ignored && filter_lower_versions(filtered).empty? && filter_lower_versions(tags).any?
205
+ raise Dependabot::AllVersionsIgnored
206
+ end
207
+
208
+ filtered.
209
+ reject { |t| tag_is_prerelease?(t) && !wants_prerelease? }
210
+ end
211
+
201
212
  def pinned_ref_in_release?(version)
202
213
  raise "Not a git dependency!" unless git_dependency?
203
214
 
@@ -236,9 +247,15 @@ module Dependabot
236
247
  local_repo_git_metadata_fetcher.upload_pack
237
248
  end
238
249
 
250
+ def local_refs
251
+ handle_tag_prefix(local_repo_git_metadata_fetcher.refs_for_upload_pack)
252
+ end
253
+
239
254
  def local_tags
240
- tags = local_repo_git_metadata_fetcher.tags
255
+ handle_tag_prefix(local_repo_git_metadata_fetcher.tags_for_upload_pack)
256
+ end
241
257
 
258
+ def handle_tag_prefix(tags)
242
259
  if dependency_source_details&.fetch(:ref, nil)&.start_with?("tags/")
243
260
  tags = tags.map do |tag|
244
261
  tag.dup.tap { |t| t.name = "tags/#{tag.name}" }
@@ -341,6 +358,18 @@ module Dependabot
341
358
  tag.gsub(VERSION_REGEX, "").gsub(/v$/i, "")
342
359
  end
343
360
 
361
+ def to_local_tag(tag)
362
+ return unless tag
363
+
364
+ version = version_from_tag(tag)
365
+ {
366
+ tag: tag.name,
367
+ version: version,
368
+ commit_sha: tag.commit_sha,
369
+ tag_sha: tag.ref_sha
370
+ }
371
+ end
372
+
344
373
  def listing_source_url
345
374
  @listing_source_url ||=
346
375
  begin
@@ -404,31 +433,37 @@ module Dependabot
404
433
  return false unless dependency_source_details&.fetch(:ref, nil)
405
434
  return false unless pinned_ref_looks_like_version?
406
435
 
407
- version = dependency_source_details.fetch(:ref).match(VERSION_REGEX).
408
- named_captures.fetch("version")
409
- version_class.new(version).prerelease?
436
+ version = version_from_ref(dependency_source_details.fetch(:ref))
437
+ version.prerelease?
410
438
  end
411
439
 
412
440
  def tag_included_in_ignore_requirements?(tag)
413
- version = tag.name.match(VERSION_REGEX).named_captures.fetch("version")
414
- ignore_requirements.any? { |r| r.satisfied_by?(version_class.new(version)) }
441
+ version = version_from_tag(tag)
442
+ ignore_requirements.any? { |r| r.satisfied_by?(version) }
415
443
  end
416
444
 
417
445
  def tag_is_prerelease?(tag)
418
- version = tag.name.match(VERSION_REGEX).named_captures.fetch("version")
419
- version_class.new(version).prerelease?
446
+ version_from_tag(tag).prerelease?
420
447
  end
421
448
 
422
- def version_class
423
- return @version_class if @version_class
449
+ def version_from_tag(tag)
450
+ version_from_ref(tag.name)
451
+ end
424
452
 
425
- Utils.version_class_for_package_manager(dependency.package_manager)
453
+ def version_from_ref(name)
454
+ version_class.new(scan_version(name))
426
455
  end
427
456
 
428
- def requirement_class
429
- return @requirement_class if @requirement_class
457
+ def scan_version(name)
458
+ name.match(VERSION_REGEX).named_captures.fetch("version")
459
+ end
430
460
 
431
- Utils.requirement_class_for_package_manager(dependency.package_manager)
461
+ def version_class
462
+ @version_class ||= Utils.version_class_for_package_manager(dependency.package_manager)
463
+ end
464
+
465
+ def requirement_class
466
+ @requirement_class ||= Utils.requirement_class_for_package_manager(dependency.package_manager)
432
467
  end
433
468
 
434
469
  def local_repo_git_metadata_fetcher
@@ -22,7 +22,21 @@ module Dependabot
22
22
  def tags
23
23
  return [] unless upload_pack
24
24
 
25
- @tags ||= tags_for_upload_pack
25
+ @tags ||= tags_for_upload_pack.map do |ref|
26
+ OpenStruct.new(
27
+ name: ref.name,
28
+ tag_sha: ref.ref_sha,
29
+ commit_sha: ref.commit_sha
30
+ )
31
+ end
32
+ end
33
+
34
+ def tags_for_upload_pack
35
+ @tags_for_upload_pack ||= refs_for_upload_pack.select { |ref| ref.ref_type == :tag }
36
+ end
37
+
38
+ def refs_for_upload_pack
39
+ @refs_for_upload_pack ||= parse_refs_for_upload_pack
26
40
  end
27
41
 
28
42
  def ref_names
@@ -44,6 +58,12 @@ module Dependabot
44
58
  commit_sha
45
59
  end
46
60
 
61
+ def head_commit_for_ref_sha(ref)
62
+ refs_for_upload_pack.
63
+ find { |r| r.ref_sha == ref }&.
64
+ commit_sha
65
+ end
66
+
47
67
  private
48
68
 
49
69
  attr_reader :url, :credentials
@@ -102,22 +122,6 @@ module Dependabot
102
122
  end
103
123
  end
104
124
 
105
- def tags_for_upload_pack
106
- refs_for_upload_pack.
107
- select { |ref| ref.ref_type == :tag }.
108
- map do |ref|
109
- OpenStruct.new(
110
- name: ref.name,
111
- tag_sha: ref.ref_sha,
112
- commit_sha: ref.commit_sha
113
- )
114
- end
115
- end
116
-
117
- def refs_for_upload_pack
118
- @refs_for_upload_pack ||= parse_refs_for_upload_pack
119
- end
120
-
121
125
  def parse_refs_for_upload_pack
122
126
  peeled_lines = []
123
127
 
@@ -8,11 +8,11 @@ module Dependabot
8
8
  class Azure
9
9
  attr_reader :source, :branch_name, :base_commit, :credentials,
10
10
  :files, :commit_message, :pr_description, :pr_name,
11
- :author_details, :labeler, :work_item
11
+ :author_details, :labeler, :reviewers, :assignees, :work_item
12
12
 
13
13
  def initialize(source:, branch_name:, base_commit:, credentials:,
14
14
  files:, commit_message:, pr_description:, pr_name:,
15
- author_details:, labeler:, work_item: nil)
15
+ author_details:, labeler:, reviewers: nil, assignees: nil, work_item: nil)
16
16
  @source = source
17
17
  @branch_name = branch_name
18
18
  @base_commit = base_commit
@@ -23,6 +23,8 @@ module Dependabot
23
23
  @pr_name = pr_name
24
24
  @author_details = author_details
25
25
  @labeler = labeler
26
+ @reviewers = reviewers
27
+ @assignees = assignees
26
28
  @work_item = work_item
27
29
  end
28
30
 
@@ -79,6 +81,8 @@ module Dependabot
79
81
  source.branch || default_branch,
80
82
  pr_description,
81
83
  labeler.labels_for_pr,
84
+ reviewers,
85
+ assignees,
82
86
  work_item
83
87
  )
84
88
  end
@@ -193,7 +193,7 @@ module Dependabot
193
193
  {
194
194
  path: (file.symlink_target ||
195
195
  file.path).sub(%r{^/}, ""),
196
- mode: "100644",
196
+ mode: (file.mode || "100644"),
197
197
  type: "blob"
198
198
  }.merge(content)
199
199
  end
@@ -176,6 +176,8 @@ module Dependabot
176
176
  pr_name: message.pr_name,
177
177
  author_details: author_details,
178
178
  labeler: labeler,
179
+ reviewers: reviewers,
180
+ assignees: assignees,
179
181
  work_item: provider_metadata&.fetch(:work_item, nil)
180
182
  )
181
183
  end
@@ -137,8 +137,7 @@ module Dependabot
137
137
  # Can't (currently) detect whether git dependencies are vulnerable
138
138
  return false if existing_version_is_sha?
139
139
 
140
- version = version_class.new(dependency.version)
141
- security_advisories.any? { |a| a.vulnerable?(version) }
140
+ active_advisories.any?
142
141
  end
143
142
 
144
143
  def ignore_requirements
@@ -147,6 +146,10 @@ module Dependabot
147
146
 
148
147
  private
149
148
 
149
+ def active_advisories
150
+ security_advisories.select { |a| a.vulnerable?(current_version) }
151
+ end
152
+
150
153
  def latest_version_resolvable_with_full_unlock?
151
154
  raise NotImplementedError
152
155
  end
@@ -235,7 +238,7 @@ module Dependabot
235
238
  # this case we treat the version as up-to-date so that it's ignored.
236
239
  return true if latest_version.to_s.match?(/^[0-9a-f]{40}$/)
237
240
 
238
- latest_version <= version_class.new(dependency.version)
241
+ latest_version <= current_version
239
242
  end
240
243
 
241
244
  def numeric_version_can_update?(requirements_to_unlock:)
@@ -244,7 +247,7 @@ module Dependabot
244
247
  case requirements_to_unlock&.to_sym
245
248
  when :none
246
249
  new_version = latest_resolvable_version_with_no_unlock
247
- new_version && new_version > version_class.new(dependency.version)
250
+ new_version && new_version > current_version
248
251
  when :own
249
252
  preferred_version_resolvable_with_unlock?
250
253
  when :all
@@ -259,7 +262,7 @@ module Dependabot
259
262
 
260
263
  if existing_version_is_sha?
261
264
  return false if new_version.to_s.start_with?(dependency.version)
262
- elsif new_version <= version_class.new(dependency.version)
265
+ elsif new_version <= current_version
263
266
  return false
264
267
  end
265
268
 
@@ -275,6 +278,10 @@ module Dependabot
275
278
  changed_requirements.none?
276
279
  end
277
280
 
281
+ def current_version
282
+ @current_version ||= dependency.numeric_version
283
+ end
284
+
278
285
  def can_compare_requirements?
279
286
  version_from_requirements &&
280
287
  latest_version &&
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dependabot
4
- VERSION = "0.213.0"
4
+ VERSION = "0.214.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-common
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.213.0
4
+ version: 0.214.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-31 00:00:00.000000000 Z
11
+ date: 2022-12-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -119,6 +119,9 @@ dependencies:
119
119
  - - "~>"
120
120
  - !ruby/object:Gem::Version
121
121
  version: '0.75'
122
+ - - "<"
123
+ - !ruby/object:Gem::Version
124
+ version: '0.94'
122
125
  type: :runtime
123
126
  prerelease: false
124
127
  version_requirements: !ruby/object:Gem::Requirement
@@ -126,6 +129,9 @@ dependencies:
126
129
  - - "~>"
127
130
  - !ruby/object:Gem::Version
128
131
  version: '0.75'
132
+ - - "<"
133
+ - !ruby/object:Gem::Version
134
+ version: '0.94'
129
135
  - !ruby/object:Gem::Dependency
130
136
  name: faraday
131
137
  requirement: !ruby/object:Gem::Requirement
@@ -140,6 +146,20 @@ dependencies:
140
146
  - - '='
141
147
  - !ruby/object:Gem::Version
142
148
  version: 2.6.0
149
+ - !ruby/object:Gem::Dependency
150
+ name: faraday-retry
151
+ requirement: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - '='
154
+ - !ruby/object:Gem::Version
155
+ version: 2.0.0
156
+ type: :runtime
157
+ prerelease: false
158
+ version_requirements: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - '='
161
+ - !ruby/object:Gem::Version
162
+ version: 2.0.0
143
163
  - !ruby/object:Gem::Dependency
144
164
  name: gitlab
145
165
  requirement: !ruby/object:Gem::Requirement
@@ -262,14 +282,14 @@ dependencies:
262
282
  requirements:
263
283
  - - "~>"
264
284
  - !ruby/object:Gem::Version
265
- version: 3.13.0
285
+ version: 4.0.0
266
286
  type: :development
267
287
  prerelease: false
268
288
  version_requirements: !ruby/object:Gem::Requirement
269
289
  requirements:
270
290
  - - "~>"
271
291
  - !ruby/object:Gem::Version
272
- version: 3.13.0
292
+ version: 4.0.0
273
293
  - !ruby/object:Gem::Dependency
274
294
  name: rake
275
295
  requirement: !ruby/object:Gem::Requirement
@@ -318,14 +338,14 @@ dependencies:
318
338
  requirements:
319
339
  - - "~>"
320
340
  - !ruby/object:Gem::Version
321
- version: 1.37.1
341
+ version: 1.39.0
322
342
  type: :development
323
343
  prerelease: false
324
344
  version_requirements: !ruby/object:Gem::Requirement
325
345
  requirements:
326
346
  - - "~>"
327
347
  - !ruby/object:Gem::Version
328
- version: 1.37.1
348
+ version: 1.39.0
329
349
  - !ruby/object:Gem::Dependency
330
350
  name: rubocop-performance
331
351
  requirement: !ruby/object:Gem::Requirement
@@ -503,7 +523,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
503
523
  requirements:
504
524
  - - ">="
505
525
  - !ruby/object:Gem::Version
506
- version: 3.3.22
526
+ version: 3.3.7
507
527
  requirements: []
508
528
  rubygems_version: 3.3.7
509
529
  signing_key: