dependabot-common 0.392.0 → 0.394.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/azure.rb +42 -22
- data/lib/dependabot/clients/bitbucket.rb +52 -26
- data/lib/dependabot/clients/bitbucket_with_retries.rb +11 -12
- data/lib/dependabot/clients/codecommit.rb +73 -53
- data/lib/dependabot/clients/github_resource_parser.rb +70 -0
- data/lib/dependabot/clients/github_with_retries.rb +63 -23
- data/lib/dependabot/clients/gitlab_with_retries.rb +19 -17
- data/lib/dependabot/clients/json_response_parser.rb +103 -0
- data/lib/dependabot/command_helpers.rb +79 -11
- data/lib/dependabot/credential.rb +12 -3
- data/lib/dependabot/errors.rb +4 -1
- data/lib/dependabot/file_fetchers/base.rb +199 -151
- data/lib/dependabot/file_filtering.rb +0 -2
- data/lib/dependabot/file_updaters/vendor_updater.rb +8 -2
- data/lib/dependabot/git_tag_details.rb +8 -14
- data/lib/dependabot/metadata_finders/base/changelog_finder.rb +211 -110
- data/lib/dependabot/metadata_finders/base/commit_response_parser.rb +68 -0
- data/lib/dependabot/metadata_finders/base/commits_finder.rb +44 -38
- data/lib/dependabot/package/npm_package_manager_config.rb +72 -0
- data/lib/dependabot/package/npm_registry_package.rb +186 -0
- data/lib/dependabot/pull_request_creator/azure.rb +1 -1
- data/lib/dependabot/pull_request_creator/codecommit.rb +10 -12
- data/lib/dependabot/pull_request_creator/github.rb +55 -35
- data/lib/dependabot/pull_request_creator/gitlab.rb +37 -11
- data/lib/dependabot/pull_request_creator/labeler.rb +65 -15
- data/lib/dependabot/pull_request_creator/pr_name_prefixer.rb +179 -78
- data/lib/dependabot/pull_request_updater/azure.rb +63 -11
- data/lib/dependabot/pull_request_updater/github.rb +44 -34
- data/lib/dependabot/pull_request_updater/gitlab.rb +23 -12
- data/lib/dependabot/pull_request_updater.rb +3 -3
- data/lib/dependabot/shared_helpers.rb +77 -32
- data/lib/dependabot/update_checkers/base.rb +9 -5
- data/lib/dependabot/update_checkers/version_filters.rb +5 -0
- data/lib/dependabot/update_checkers/vulnerability_audit.rb +282 -0
- data/lib/dependabot/workspace/git.rb +35 -4
- data/lib/dependabot.rb +1 -1
- metadata +10 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strong
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "excon"
|
|
@@ -7,51 +7,21 @@ require "sorbet-runtime"
|
|
|
7
7
|
require "dependabot/clients/github_with_retries"
|
|
8
8
|
require "dependabot/clients/gitlab_with_retries"
|
|
9
9
|
require "dependabot/clients/bitbucket_with_retries"
|
|
10
|
+
require "dependabot/errors"
|
|
10
11
|
require "dependabot/shared_helpers"
|
|
11
12
|
require "dependabot/metadata_finders/base"
|
|
12
13
|
|
|
13
14
|
module Dependabot
|
|
14
15
|
module MetadataFinders
|
|
15
16
|
class Base
|
|
16
|
-
class ChangelogFile
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
sig { returns(Integer) }
|
|
26
|
-
attr_reader :size
|
|
27
|
-
|
|
28
|
-
sig { returns(String) }
|
|
29
|
-
attr_reader :html_url
|
|
30
|
-
|
|
31
|
-
sig { returns(String) }
|
|
32
|
-
attr_reader :download_url
|
|
33
|
-
|
|
34
|
-
sig { returns(T.nilable(String)) }
|
|
35
|
-
attr_reader :path
|
|
36
|
-
|
|
37
|
-
sig do
|
|
38
|
-
params(
|
|
39
|
-
name: String,
|
|
40
|
-
type: String,
|
|
41
|
-
size: Integer,
|
|
42
|
-
html_url: String,
|
|
43
|
-
download_url: String,
|
|
44
|
-
path: T.nilable(String)
|
|
45
|
-
).void
|
|
46
|
-
end
|
|
47
|
-
def initialize(name:, type:, size:, html_url:, download_url:, path: nil)
|
|
48
|
-
@name = name
|
|
49
|
-
@type = type
|
|
50
|
-
@size = size
|
|
51
|
-
@html_url = html_url
|
|
52
|
-
@download_url = download_url
|
|
53
|
-
@path = path
|
|
54
|
-
end
|
|
17
|
+
class ChangelogFile < T::ImmutableStruct
|
|
18
|
+
const :name, String
|
|
19
|
+
const :type, String
|
|
20
|
+
const :size, Integer
|
|
21
|
+
const :html_url, String
|
|
22
|
+
const :download_url, String
|
|
23
|
+
const :path, T.nilable(String), default: nil
|
|
24
|
+
const :api_url, T.nilable(String), default: nil
|
|
55
25
|
end
|
|
56
26
|
|
|
57
27
|
# rubocop:disable Metrics/ClassLength
|
|
@@ -63,6 +33,7 @@ module Dependabot
|
|
|
63
33
|
|
|
64
34
|
# Earlier entries are preferred
|
|
65
35
|
CHANGELOG_NAMES = %w(changelog news changes history release whatsnew releases).freeze
|
|
36
|
+
CHANGELOG_FILE_TYPES = %w(file dir).freeze
|
|
66
37
|
|
|
67
38
|
sig { returns(T.nilable(Dependabot::Source)) }
|
|
68
39
|
attr_reader :source
|
|
@@ -99,7 +70,9 @@ module Dependabot
|
|
|
99
70
|
@suggested_changelog_url = @suggested_changelog_url&.split("#")&.first
|
|
100
71
|
|
|
101
72
|
@new_version = T.let(nil, T.nilable(String))
|
|
102
|
-
@changelog_from_suggested_url = T.let(nil, T.nilable(
|
|
73
|
+
@changelog_from_suggested_url = T.let(nil, T.nilable(ChangelogFile))
|
|
74
|
+
@file_text = T.let({}, T::Hash[String, T.nilable(String)])
|
|
75
|
+
@dependency_file_list = T.let({}, T::Hash[T.nilable(String), T::Array[ChangelogFile]])
|
|
103
76
|
end
|
|
104
77
|
|
|
105
78
|
sig { returns(T.nilable(String)) }
|
|
@@ -124,10 +97,11 @@ module Dependabot
|
|
|
124
97
|
|
|
125
98
|
sig { returns(T.nilable(String)) }
|
|
126
99
|
def upgrade_guide_text
|
|
127
|
-
|
|
100
|
+
guide = upgrade_guide
|
|
101
|
+
return unless guide
|
|
128
102
|
|
|
129
103
|
@upgrade_guide_text ||= T.let(
|
|
130
|
-
fetch_file_text(
|
|
104
|
+
fetch_file_text(guide),
|
|
131
105
|
T.nilable(String)
|
|
132
106
|
)
|
|
133
107
|
end
|
|
@@ -135,22 +109,24 @@ module Dependabot
|
|
|
135
109
|
private
|
|
136
110
|
|
|
137
111
|
# rubocop:disable Metrics/PerceivedComplexity
|
|
138
|
-
sig { returns(T.
|
|
112
|
+
sig { returns(T.nilable(ChangelogFile)) }
|
|
139
113
|
def changelog
|
|
140
114
|
return unless changelog_from_suggested_url || source
|
|
141
115
|
return if git_source? && !ref_changed?
|
|
142
116
|
return changelog_from_suggested_url if changelog_from_suggested_url
|
|
143
117
|
|
|
144
118
|
# If there is a changelog, and it includes the new version, return it
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
119
|
+
default_changelog = default_branch_changelog
|
|
120
|
+
if new_version && default_changelog &&
|
|
121
|
+
fetch_file_text(default_changelog)&.include?(T.must(new_version))
|
|
122
|
+
return default_changelog
|
|
148
123
|
end
|
|
149
124
|
|
|
150
125
|
# Otherwise, look for a changelog at the tag for this version
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
126
|
+
tag_changelog = relevant_tag_changelog
|
|
127
|
+
if new_version && tag_changelog &&
|
|
128
|
+
fetch_file_text(tag_changelog)&.include?(T.must(new_version))
|
|
129
|
+
return tag_changelog
|
|
154
130
|
end
|
|
155
131
|
|
|
156
132
|
# Fall back to the changelog (or nil) from the default branch
|
|
@@ -158,7 +134,7 @@ module Dependabot
|
|
|
158
134
|
end
|
|
159
135
|
# rubocop:enable Metrics/PerceivedComplexity
|
|
160
136
|
|
|
161
|
-
sig { returns(T.nilable(
|
|
137
|
+
sig { returns(T.nilable(ChangelogFile)) }
|
|
162
138
|
def changelog_from_suggested_url
|
|
163
139
|
return @changelog_from_suggested_url unless @changelog_from_suggested_url.nil?
|
|
164
140
|
return unless suggested_changelog_url
|
|
@@ -169,27 +145,27 @@ module Dependabot
|
|
|
169
145
|
|
|
170
146
|
opts = { path: suggested_source&.directory, ref: suggested_source&.branch }.compact
|
|
171
147
|
suggested_source_client = github_client_for_source(T.must(suggested_source))
|
|
172
|
-
|
|
148
|
+
response = suggested_source_client.contents(T.must(suggested_source).repo, opts)
|
|
149
|
+
tmp_files = github_changelog_files(response, source_url: T.must(suggested_source).url)
|
|
173
150
|
|
|
174
151
|
filename = T.must(T.must(suggested_changelog_url).split("/").last)
|
|
175
|
-
@changelog_from_suggested_url =
|
|
176
|
-
tmp_files.find { |f| f.name == filename }
|
|
152
|
+
@changelog_from_suggested_url = tmp_files.find { |f| f.name == filename }
|
|
177
153
|
rescue Octokit::NotFound, Octokit::UnavailableForLegalReasons
|
|
178
154
|
@changelog_from_suggested_url = nil
|
|
179
155
|
end
|
|
180
156
|
|
|
181
|
-
sig { returns(T.nilable(
|
|
157
|
+
sig { returns(T.nilable(ChangelogFile)) }
|
|
182
158
|
def default_branch_changelog
|
|
183
159
|
return unless source
|
|
184
160
|
|
|
185
161
|
@default_branch_changelog ||=
|
|
186
162
|
T.let(
|
|
187
163
|
changelog_from_ref(nil),
|
|
188
|
-
T.nilable(
|
|
164
|
+
T.nilable(ChangelogFile)
|
|
189
165
|
)
|
|
190
166
|
end
|
|
191
167
|
|
|
192
|
-
sig { returns(T.nilable(
|
|
168
|
+
sig { returns(T.nilable(ChangelogFile)) }
|
|
193
169
|
def relevant_tag_changelog
|
|
194
170
|
return unless source
|
|
195
171
|
return unless tag_for_new_version
|
|
@@ -197,11 +173,11 @@ module Dependabot
|
|
|
197
173
|
@relevant_tag_changelog ||=
|
|
198
174
|
T.let(
|
|
199
175
|
changelog_from_ref(tag_for_new_version),
|
|
200
|
-
T.nilable(
|
|
176
|
+
T.nilable(ChangelogFile)
|
|
201
177
|
)
|
|
202
178
|
end
|
|
203
179
|
|
|
204
|
-
sig { params(ref: T.nilable(String)).returns(T.nilable(
|
|
180
|
+
sig { params(ref: T.nilable(String)).returns(T.nilable(ChangelogFile)) }
|
|
205
181
|
def changelog_from_ref(ref)
|
|
206
182
|
files =
|
|
207
183
|
dependency_file_list(ref)
|
|
@@ -216,7 +192,7 @@ module Dependabot
|
|
|
216
192
|
end
|
|
217
193
|
|
|
218
194
|
# rubocop:disable Metrics/PerceivedComplexity
|
|
219
|
-
sig { params(files: T::Array[
|
|
195
|
+
sig { params(files: T::Array[ChangelogFile]).returns(T.nilable(ChangelogFile)) }
|
|
220
196
|
def select_best_changelog(files)
|
|
221
197
|
CHANGELOG_NAMES.each do |name|
|
|
222
198
|
candidates = files.select { |f| f.name =~ /\A#{name}/i }
|
|
@@ -257,15 +233,14 @@ module Dependabot
|
|
|
257
233
|
|
|
258
234
|
sig { returns(T.nilable(String)) }
|
|
259
235
|
def full_changelog_text
|
|
260
|
-
|
|
236
|
+
selected_changelog = changelog
|
|
237
|
+
return unless selected_changelog
|
|
261
238
|
|
|
262
|
-
fetch_file_text(
|
|
239
|
+
fetch_file_text(selected_changelog)
|
|
263
240
|
end
|
|
264
241
|
|
|
265
|
-
sig { params(file:
|
|
242
|
+
sig { params(file: ChangelogFile).returns(T.nilable(String)) }
|
|
266
243
|
def fetch_file_text(file)
|
|
267
|
-
@file_text ||= T.let({}, T.nilable(T::Hash[String, T.untyped]))
|
|
268
|
-
|
|
269
244
|
unless @file_text.key?(file.download_url)
|
|
270
245
|
file_source = T.must(Source.from_url(file.html_url))
|
|
271
246
|
@file_text[file.download_url] =
|
|
@@ -279,19 +254,24 @@ module Dependabot
|
|
|
279
254
|
end
|
|
280
255
|
end
|
|
281
256
|
|
|
282
|
-
|
|
257
|
+
text = @file_text[file.download_url]
|
|
258
|
+
return unless text&.valid_encoding?
|
|
283
259
|
|
|
284
|
-
|
|
260
|
+
text.rstrip
|
|
285
261
|
end
|
|
286
262
|
|
|
287
|
-
sig { params(file_source: Dependabot::Source, file:
|
|
263
|
+
sig { params(file_source: Dependabot::Source, file: ChangelogFile).returns(String) }
|
|
288
264
|
def fetch_github_file(file_source, file)
|
|
289
265
|
# Hitting the download URL directly causes encoding problems
|
|
290
|
-
|
|
266
|
+
response = github_client_for_source(file_source).get(T.must(file.api_url))
|
|
267
|
+
raise_bad_metadata_response("GitHub", "file response must be an object", source_url: file_source.url) unless
|
|
268
|
+
response.is_a?(Sawyer::Resource)
|
|
269
|
+
|
|
270
|
+
raw_content = sawyer_string(response, :content, source_url: file_source.url)
|
|
291
271
|
Base64.decode64(raw_content).force_encoding("UTF-8").encode
|
|
292
272
|
end
|
|
293
273
|
|
|
294
|
-
sig { params(file:
|
|
274
|
+
sig { params(file: ChangelogFile).returns(String) }
|
|
295
275
|
def fetch_gitlab_file(file)
|
|
296
276
|
Excon.get(
|
|
297
277
|
file.download_url,
|
|
@@ -300,19 +280,19 @@ module Dependabot
|
|
|
300
280
|
).body.force_encoding("UTF-8").encode
|
|
301
281
|
end
|
|
302
282
|
|
|
303
|
-
sig { params(file:
|
|
283
|
+
sig { params(file: ChangelogFile).returns(String) }
|
|
304
284
|
def fetch_bitbucket_file(file)
|
|
305
285
|
bitbucket_client.get(file.download_url).body
|
|
306
286
|
.force_encoding("UTF-8").encode
|
|
307
287
|
end
|
|
308
288
|
|
|
309
|
-
sig { params(file:
|
|
289
|
+
sig { params(file: ChangelogFile).returns(String) }
|
|
310
290
|
def fetch_azure_file(file)
|
|
311
291
|
azure_client.get(file.download_url).body
|
|
312
292
|
.force_encoding("UTF-8").encode
|
|
313
293
|
end
|
|
314
294
|
|
|
315
|
-
sig { returns(T.
|
|
295
|
+
sig { returns(T.nilable(ChangelogFile)) }
|
|
316
296
|
def upgrade_guide
|
|
317
297
|
return unless source
|
|
318
298
|
|
|
@@ -322,18 +302,17 @@ module Dependabot
|
|
|
322
302
|
|
|
323
303
|
dependency_file_list
|
|
324
304
|
.select { |f| f.type == "file" }
|
|
325
|
-
.select { |f| f.name.casecmp("upgrade.md")
|
|
305
|
+
.select { |f| f.name.casecmp?("upgrade.md") }
|
|
326
306
|
.reject { |f| f.size > 1_000_000 }
|
|
327
307
|
.max_by(&:size)
|
|
328
308
|
end
|
|
329
309
|
|
|
330
|
-
sig { params(ref: T.nilable(String)).returns(T
|
|
310
|
+
sig { params(ref: T.nilable(String)).returns(T::Array[ChangelogFile]) }
|
|
331
311
|
def dependency_file_list(ref = nil)
|
|
332
|
-
@dependency_file_list ||= T.let({}, T.nilable(T::Hash[T.nilable(String), T.untyped]))
|
|
333
312
|
@dependency_file_list[ref] ||= fetch_dependency_file_list(ref)
|
|
334
313
|
end
|
|
335
314
|
|
|
336
|
-
sig { params(ref: T.nilable(String)).returns(T::Array[
|
|
315
|
+
sig { params(ref: T.nilable(String)).returns(T::Array[ChangelogFile]) }
|
|
337
316
|
def fetch_dependency_file_list(ref)
|
|
338
317
|
case T.must(source).provider
|
|
339
318
|
when "github" then fetch_github_file_list(ref)
|
|
@@ -346,45 +325,55 @@ module Dependabot
|
|
|
346
325
|
end
|
|
347
326
|
end
|
|
348
327
|
|
|
349
|
-
sig { params(ref: T.nilable(String)).returns(T::Array[
|
|
328
|
+
sig { params(ref: T.nilable(String)).returns(T::Array[ChangelogFile]) }
|
|
350
329
|
def fetch_github_file_list(ref)
|
|
351
|
-
files = []
|
|
330
|
+
files = T.let([], T::Array[ChangelogFile])
|
|
352
331
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
332
|
+
directory = T.must(source).directory
|
|
333
|
+
if directory
|
|
334
|
+
options = { path: directory, ref: ref }.compact
|
|
335
|
+
response = github_client.contents(T.must(source).repo, options)
|
|
336
|
+
files.concat(github_changelog_files(response, source_url: T.must(source).url)) if response.is_a?(Array)
|
|
357
337
|
end
|
|
358
|
-
|
|
359
|
-
opts = { ref: ref }.compact
|
|
360
|
-
files += github_client.contents(T.must(source).repo, opts)
|
|
338
|
+
files.concat(github_files_at(path: nil, ref: ref))
|
|
361
339
|
|
|
362
340
|
files.uniq.each do |f|
|
|
363
341
|
next unless f.type == "dir" && f.name.match?(/docs?/o)
|
|
364
342
|
|
|
365
|
-
|
|
366
|
-
files += github_client.contents(T.must(source).repo, opts)
|
|
343
|
+
files.concat(github_files_at(path: f.path, ref: ref))
|
|
367
344
|
end
|
|
368
345
|
|
|
369
346
|
files
|
|
370
347
|
rescue Octokit::NotFound, Octokit::UnavailableForLegalReasons
|
|
371
348
|
[]
|
|
372
349
|
end
|
|
373
|
-
|
|
350
|
+
|
|
351
|
+
sig { params(path: T.nilable(String), ref: T.nilable(String)).returns(T::Array[ChangelogFile]) }
|
|
352
|
+
def github_files_at(path:, ref:)
|
|
353
|
+
options = { path: path, ref: ref }.compact
|
|
354
|
+
github_changelog_files(
|
|
355
|
+
github_client.contents(T.must(source).repo, options),
|
|
356
|
+
source_url: T.must(source).url
|
|
357
|
+
)
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
sig { returns(T::Array[ChangelogFile]) }
|
|
374
361
|
def fetch_bitbucket_file_list
|
|
375
362
|
branch = default_bitbucket_branch
|
|
376
363
|
bitbucket_client.fetch_repo_contents(T.must(source).repo).map do |file|
|
|
377
|
-
|
|
364
|
+
object_type = object_string(file, "type", "Bitbucket")
|
|
365
|
+
path = object_string(file, "path", "Bitbucket")
|
|
366
|
+
type = case object_type
|
|
378
367
|
when "commit_file" then "file"
|
|
379
368
|
when "commit_directory" then "dir"
|
|
380
|
-
else
|
|
369
|
+
else object_type
|
|
381
370
|
end
|
|
382
371
|
ChangelogFile.new(
|
|
383
|
-
name:
|
|
372
|
+
name: T.must(path.split("/").last),
|
|
384
373
|
type: type,
|
|
385
|
-
size: file
|
|
386
|
-
html_url: "#{T.must(source).url}/src/#{branch}/#{
|
|
387
|
-
download_url: "#{T.must(source).url}/raw/#{branch}/#{
|
|
374
|
+
size: object_integer(file, "size", "Bitbucket", default: 100),
|
|
375
|
+
html_url: "#{T.must(source).url}/src/#{branch}/#{path}",
|
|
376
|
+
download_url: "#{T.must(source).url}/raw/#{branch}/#{path}"
|
|
388
377
|
)
|
|
389
378
|
end
|
|
390
379
|
rescue Dependabot::Clients::Bitbucket::NotFound,
|
|
@@ -393,43 +382,48 @@ module Dependabot
|
|
|
393
382
|
[]
|
|
394
383
|
end
|
|
395
384
|
|
|
396
|
-
sig { returns(T
|
|
385
|
+
sig { returns(T::Array[ChangelogFile]) }
|
|
397
386
|
def fetch_gitlab_file_list
|
|
398
387
|
branch = default_gitlab_branch
|
|
399
|
-
|
|
400
|
-
|
|
388
|
+
gitlab_client.repo_tree(T.must(source).repo).map do |file|
|
|
389
|
+
object_type = gitlab_string(file, "type")
|
|
390
|
+
type = case object_type
|
|
401
391
|
when "blob" then "file"
|
|
402
392
|
when "tree" then "dir"
|
|
403
|
-
else
|
|
393
|
+
else object_type
|
|
404
394
|
end
|
|
395
|
+
path = gitlab_string(file, "path")
|
|
405
396
|
ChangelogFile.new(
|
|
406
|
-
name: file
|
|
397
|
+
name: gitlab_string(file, "name"),
|
|
407
398
|
type: type,
|
|
408
399
|
size: 100, # GitLab doesn't return file size
|
|
409
|
-
html_url: "#{T.must(source).url}/blob/#{branch}/#{
|
|
410
|
-
download_url: "#{T.must(source).url}/raw/#{branch}/#{
|
|
400
|
+
html_url: "#{T.must(source).url}/blob/#{branch}/#{path}",
|
|
401
|
+
download_url: "#{T.must(source).url}/raw/#{branch}/#{path}",
|
|
402
|
+
path: path
|
|
411
403
|
)
|
|
412
404
|
end
|
|
413
405
|
rescue Gitlab::Error::NotFound
|
|
414
406
|
[]
|
|
415
407
|
end
|
|
416
408
|
|
|
417
|
-
sig { returns(T
|
|
409
|
+
sig { returns(T::Array[ChangelogFile]) }
|
|
418
410
|
def fetch_azure_file_list
|
|
419
411
|
azure_client.fetch_repo_contents.map do |entry|
|
|
420
|
-
|
|
412
|
+
object_type = object_string(entry, "gitObjectType", "Azure")
|
|
413
|
+
relative_path = object_string(entry, "relativePath", "Azure")
|
|
414
|
+
type = case object_type
|
|
421
415
|
when "blob" then "file"
|
|
422
416
|
when "tree" then "dir"
|
|
423
|
-
else
|
|
417
|
+
else object_type
|
|
424
418
|
end
|
|
425
419
|
|
|
426
420
|
ChangelogFile.new(
|
|
427
|
-
name: File.basename(
|
|
421
|
+
name: File.basename(relative_path),
|
|
428
422
|
type: type,
|
|
429
|
-
size: entry
|
|
430
|
-
path:
|
|
431
|
-
html_url: "#{T.must(source).url}?path=/#{
|
|
432
|
-
download_url: entry
|
|
423
|
+
size: object_integer(entry, "size", "Azure"),
|
|
424
|
+
path: relative_path,
|
|
425
|
+
html_url: "#{T.must(source).url}?path=/#{relative_path}",
|
|
426
|
+
download_url: object_string(entry, "url", "Azure")
|
|
433
427
|
)
|
|
434
428
|
end
|
|
435
429
|
rescue Dependabot::Clients::Azure::NotFound,
|
|
@@ -438,6 +432,113 @@ module Dependabot
|
|
|
438
432
|
[]
|
|
439
433
|
end
|
|
440
434
|
|
|
435
|
+
sig do
|
|
436
|
+
params(
|
|
437
|
+
response: T.any(Sawyer::Resource, T::Array[Sawyer::Resource]),
|
|
438
|
+
source_url: String
|
|
439
|
+
)
|
|
440
|
+
.returns(T::Array[ChangelogFile])
|
|
441
|
+
end
|
|
442
|
+
def github_changelog_files(response, source_url:)
|
|
443
|
+
resources = response.is_a?(Array) ? response : [response]
|
|
444
|
+
resources.filter_map do |resource|
|
|
445
|
+
type = sawyer_string(resource, :type, source_url: source_url)
|
|
446
|
+
next unless CHANGELOG_FILE_TYPES.include?(type)
|
|
447
|
+
|
|
448
|
+
api_url = sawyer_string(resource, :url, source_url: source_url)
|
|
449
|
+
ChangelogFile.new(
|
|
450
|
+
name: sawyer_string(resource, :name, source_url: source_url),
|
|
451
|
+
type: type,
|
|
452
|
+
size: sawyer_optional_integer(resource, :size, source_url: source_url) || 0,
|
|
453
|
+
html_url: sawyer_string(resource, :html_url, source_url: source_url),
|
|
454
|
+
download_url: sawyer_optional_string(resource, :download_url, source_url: source_url) || api_url,
|
|
455
|
+
path: sawyer_optional_string(resource, :path, source_url: source_url),
|
|
456
|
+
api_url: api_url
|
|
457
|
+
)
|
|
458
|
+
end
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
sig { params(resource: Sawyer::Resource, key: Symbol, source_url: String).returns(String) }
|
|
462
|
+
def sawyer_string(resource, key, source_url:)
|
|
463
|
+
value = T.cast(resource[key], Object)
|
|
464
|
+
return value if value.is_a?(String)
|
|
465
|
+
|
|
466
|
+
raise_bad_metadata_response("GitHub", "#{key} must be a string", source_url: source_url)
|
|
467
|
+
end
|
|
468
|
+
|
|
469
|
+
sig do
|
|
470
|
+
params(resource: Sawyer::Resource, key: Symbol, source_url: String)
|
|
471
|
+
.returns(T.nilable(String))
|
|
472
|
+
end
|
|
473
|
+
def sawyer_optional_string(resource, key, source_url:)
|
|
474
|
+
value = T.cast(resource[key], Object)
|
|
475
|
+
return if value.nil?
|
|
476
|
+
return value if value.is_a?(String)
|
|
477
|
+
|
|
478
|
+
raise_bad_metadata_response("GitHub", "#{key} must be a string or nil", source_url: source_url)
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
sig do
|
|
482
|
+
params(resource: Sawyer::Resource, key: Symbol, source_url: String)
|
|
483
|
+
.returns(T.nilable(Integer))
|
|
484
|
+
end
|
|
485
|
+
def sawyer_optional_integer(resource, key, source_url:)
|
|
486
|
+
value = T.cast(resource[key], Object)
|
|
487
|
+
return if value.nil?
|
|
488
|
+
return value if value.is_a?(Integer)
|
|
489
|
+
|
|
490
|
+
raise_bad_metadata_response("GitHub", "#{key} must be an integer or nil", source_url: source_url)
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
sig { params(resource: Gitlab::ObjectifiedHash, key: String).returns(String) }
|
|
494
|
+
def gitlab_string(resource, key)
|
|
495
|
+
value = T.cast(resource[key], Object)
|
|
496
|
+
return value if value.is_a?(String)
|
|
497
|
+
|
|
498
|
+
raise_bad_metadata_response("GitLab", "#{key} must be a string")
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
sig do
|
|
502
|
+
params(object: T::Hash[String, Object], key: String, provider: String)
|
|
503
|
+
.returns(String)
|
|
504
|
+
end
|
|
505
|
+
def object_string(object, key, provider)
|
|
506
|
+
value = object[key]
|
|
507
|
+
return value if value.is_a?(String)
|
|
508
|
+
|
|
509
|
+
raise_bad_metadata_response(provider, "#{key} must be a string")
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
sig do
|
|
513
|
+
params(
|
|
514
|
+
object: T::Hash[String, Object],
|
|
515
|
+
key: String,
|
|
516
|
+
provider: String,
|
|
517
|
+
default: T.nilable(Integer)
|
|
518
|
+
).returns(Integer)
|
|
519
|
+
end
|
|
520
|
+
def object_integer(object, key, provider, default: nil)
|
|
521
|
+
value = object[key]
|
|
522
|
+
return default if value.nil? && default
|
|
523
|
+
return value if value.is_a?(Integer)
|
|
524
|
+
|
|
525
|
+
raise_bad_metadata_response(provider, "#{key} must be an integer")
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
sig do
|
|
529
|
+
params(
|
|
530
|
+
provider: String,
|
|
531
|
+
message: String,
|
|
532
|
+
source_url: T.nilable(String)
|
|
533
|
+
).returns(T.noreturn)
|
|
534
|
+
end
|
|
535
|
+
def raise_bad_metadata_response(provider, message, source_url: nil)
|
|
536
|
+
raise Dependabot::PrivateSourceBadResponse.new(
|
|
537
|
+
source_url || T.must(source).url,
|
|
538
|
+
"Malformed #{provider} metadata response: #{message}"
|
|
539
|
+
)
|
|
540
|
+
end
|
|
541
|
+
|
|
441
542
|
sig { returns(T.nilable(String)) }
|
|
442
543
|
def new_version
|
|
443
544
|
return @new_version unless @new_version.nil?
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "dependabot/errors"
|
|
5
|
+
require "dependabot/clients/github_with_retries"
|
|
6
|
+
require "dependabot/clients/gitlab_with_retries"
|
|
7
|
+
require "dependabot/metadata_finders/base"
|
|
8
|
+
require "sorbet-runtime"
|
|
9
|
+
|
|
10
|
+
module Dependabot
|
|
11
|
+
module MetadataFinders
|
|
12
|
+
class Base
|
|
13
|
+
class CommitResponseParser
|
|
14
|
+
extend T::Sig
|
|
15
|
+
|
|
16
|
+
sig { params(source_url: String).void }
|
|
17
|
+
def initialize(source_url:)
|
|
18
|
+
@source_url = source_url
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
sig { params(commit: Sawyer::Resource).returns(String) }
|
|
22
|
+
def github_commit_sha(commit)
|
|
23
|
+
sawyer_string(commit, :sha, "commit")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
sig { params(commit: Sawyer::Resource).returns(String) }
|
|
27
|
+
def github_commit_message(commit)
|
|
28
|
+
details = T.cast(commit[:commit], Object)
|
|
29
|
+
raise_bad_response("GitHub", "commit details must be an object") unless details.is_a?(Sawyer::Resource)
|
|
30
|
+
|
|
31
|
+
sawyer_string(details, :message, "commit")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
sig { params(resource: Sawyer::Resource, key: Symbol, context: String).returns(String) }
|
|
35
|
+
def sawyer_string(resource, key, context)
|
|
36
|
+
value = T.cast(resource[key], Object)
|
|
37
|
+
return value if value.is_a?(String)
|
|
38
|
+
|
|
39
|
+
raise_bad_response("GitHub", "#{context} #{key} must be a string")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
sig { params(resource: Gitlab::ObjectifiedHash, key: String, context: String).returns(String) }
|
|
43
|
+
def gitlab_string(resource, key, context)
|
|
44
|
+
value = T.cast(resource[key], Object)
|
|
45
|
+
return value if value.is_a?(String)
|
|
46
|
+
|
|
47
|
+
raise_bad_response("GitLab", "#{context} #{key} must be a string")
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
sig { params(object: T::Hash[String, Object], key: String, context: String).returns(String) }
|
|
51
|
+
def object_string(object, key, context)
|
|
52
|
+
value = object[key]
|
|
53
|
+
return value if value.is_a?(String)
|
|
54
|
+
|
|
55
|
+
raise_bad_response("Azure", "#{context} #{key} must be a string")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
sig { params(provider: String, message: String).returns(T.noreturn) }
|
|
59
|
+
def raise_bad_response(provider, message)
|
|
60
|
+
raise Dependabot::PrivateSourceBadResponse.new(
|
|
61
|
+
@source_url,
|
|
62
|
+
"Malformed #{provider} commit response: #{message}"
|
|
63
|
+
)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|