dependabot-common 0.236.0 → 0.237.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 +3 -3
- data/lib/dependabot/config/file.rb +17 -6
- data/lib/dependabot/config/update_config.rb +23 -5
- data/lib/dependabot/dependency_file.rb +84 -14
- data/lib/dependabot/dependency_group.rb +29 -5
- data/lib/dependabot/errors.rb +101 -13
- data/lib/dependabot/file_fetchers/base.rb +227 -93
- data/lib/dependabot/metadata_finders/base/changelog_finder.rb +13 -6
- data/lib/dependabot/pull_request_creator/github.rb +11 -8
- data/lib/dependabot/pull_request_creator/message.rb +21 -2
- data/lib/dependabot/pull_request_creator/message_builder/link_and_mention_sanitizer.rb +37 -16
- data/lib/dependabot/pull_request_creator/message_builder/metadata_presenter.rb +4 -2
- data/lib/dependabot/pull_request_creator/pr_name_prefixer.rb +10 -4
- data/lib/dependabot/shared_helpers.rb +117 -33
- data/lib/dependabot/simple_instrumentor.rb +22 -3
- data/lib/dependabot/source.rb +65 -17
- data/lib/dependabot/update_checkers/version_filters.rb +12 -1
- data/lib/dependabot/utils.rb +21 -2
- data/lib/dependabot/workspace/base.rb +42 -7
- data/lib/dependabot/workspace/change_attempt.rb +31 -3
- data/lib/dependabot/workspace/git.rb +34 -4
- data/lib/dependabot/workspace.rb +16 -2
- data/lib/dependabot.rb +1 -1
- metadata +23 -9
@@ -1,7 +1,8 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "stringio"
|
5
|
+
require "sorbet-runtime"
|
5
6
|
require "dependabot/config"
|
6
7
|
require "dependabot/dependency_file"
|
7
8
|
require "dependabot/source"
|
@@ -17,15 +18,33 @@ require "dependabot/shared_helpers"
|
|
17
18
|
module Dependabot
|
18
19
|
module FileFetchers
|
19
20
|
class Base
|
20
|
-
|
21
|
+
extend T::Sig
|
22
|
+
extend T::Helpers
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
24
|
+
abstract!
|
25
|
+
|
26
|
+
sig { returns(Dependabot::Source) }
|
27
|
+
attr_reader :source
|
28
|
+
|
29
|
+
sig { returns(T::Array[T::Hash[String, String]]) }
|
30
|
+
attr_reader :credentials
|
31
|
+
|
32
|
+
sig { returns(T.nilable(String)) }
|
33
|
+
attr_reader :repo_contents_path
|
34
|
+
|
35
|
+
sig { returns(T::Hash[String, String]) }
|
36
|
+
attr_reader :options
|
37
|
+
|
38
|
+
CLIENT_NOT_FOUND_ERRORS = T.let(
|
39
|
+
[
|
40
|
+
Octokit::NotFound,
|
41
|
+
Gitlab::Error::NotFound,
|
42
|
+
Dependabot::Clients::Azure::NotFound,
|
43
|
+
Dependabot::Clients::Bitbucket::NotFound,
|
44
|
+
Dependabot::Clients::CodeCommit::NotFound
|
45
|
+
].freeze,
|
46
|
+
T::Array[T.class_of(StandardError)]
|
47
|
+
)
|
29
48
|
|
30
49
|
GIT_SUBMODULE_INACCESSIBLE_ERROR =
|
31
50
|
/^fatal: unable to access '(?<url>.*)': The requested URL returned error: (?<code>\d+)$/
|
@@ -33,13 +52,11 @@ module Dependabot
|
|
33
52
|
/^fatal: clone of '(?<url>.*)' into submodule path '.*' failed$/
|
34
53
|
GIT_SUBMODULE_ERROR_REGEX = /(#{GIT_SUBMODULE_INACCESSIBLE_ERROR})|(#{GIT_SUBMODULE_CLONE_ERROR})/
|
35
54
|
|
36
|
-
|
37
|
-
|
38
|
-
end
|
55
|
+
sig { abstract.params(filenames: T::Array[String]).returns(T::Boolean) }
|
56
|
+
def self.required_files_in?(filenames); end
|
39
57
|
|
40
|
-
|
41
|
-
|
42
|
-
end
|
58
|
+
sig { abstract.returns(String) }
|
59
|
+
def self.required_files_message; end
|
43
60
|
|
44
61
|
# Creates a new FileFetcher for retrieving `DependencyFile`s.
|
45
62
|
#
|
@@ -52,38 +69,58 @@ module Dependabot
|
|
52
69
|
# by repo_contents_path and still use an API trip.
|
53
70
|
#
|
54
71
|
# options supports custom feature enablement
|
72
|
+
sig do
|
73
|
+
params(
|
74
|
+
source: Dependabot::Source,
|
75
|
+
credentials: T::Array[T::Hash[String, String]],
|
76
|
+
repo_contents_path: T.nilable(String),
|
77
|
+
options: T::Hash[String, String]
|
78
|
+
)
|
79
|
+
.void
|
80
|
+
end
|
55
81
|
def initialize(source:, credentials:, repo_contents_path: nil, options: {})
|
56
82
|
@source = source
|
57
83
|
@credentials = credentials
|
58
84
|
@repo_contents_path = repo_contents_path
|
59
|
-
@linked_paths = {}
|
60
|
-
@submodules = []
|
85
|
+
@linked_paths = T.let({}, T::Hash[T.untyped, T.untyped])
|
86
|
+
@submodules = T.let([], T::Array[T.untyped])
|
61
87
|
@options = options
|
62
88
|
end
|
63
89
|
|
90
|
+
sig { returns(String) }
|
64
91
|
def repo
|
65
92
|
source.repo
|
66
93
|
end
|
67
94
|
|
95
|
+
sig { returns(String) }
|
68
96
|
def directory
|
69
97
|
Pathname.new(source.directory || "/").cleanpath.to_path
|
70
98
|
end
|
71
99
|
|
100
|
+
sig { returns(T.nilable(String)) }
|
72
101
|
def target_branch
|
73
102
|
source.branch
|
74
103
|
end
|
75
104
|
|
105
|
+
sig { returns(T::Array[DependencyFile]) }
|
76
106
|
def files
|
77
|
-
@files ||=
|
107
|
+
@files ||= T.let(
|
108
|
+
fetch_files.each { |f| f.job_directory = directory },
|
109
|
+
T.nilable(T::Array[DependencyFile])
|
110
|
+
)
|
78
111
|
end
|
79
112
|
|
113
|
+
sig { abstract.returns(T::Array[DependencyFile]) }
|
114
|
+
def fetch_files; end
|
115
|
+
|
116
|
+
sig { returns(T.nilable(String)) }
|
80
117
|
def commit
|
81
|
-
return cloned_commit if cloned_commit
|
82
|
-
return source.commit if source.commit
|
118
|
+
return T.must(cloned_commit) if cloned_commit
|
119
|
+
return T.must(source.commit) if source.commit
|
83
120
|
|
84
121
|
branch = target_branch || default_branch_for_repo
|
85
122
|
|
86
|
-
@commit ||= client_for_provider.fetch_commit(repo, branch)
|
123
|
+
@commit ||= T.let(T.unsafe(client_for_provider).fetch_commit(repo, branch), T.nilable(String))
|
87
124
|
rescue *CLIENT_NOT_FOUND_ERRORS
|
88
125
|
raise Dependabot::BranchNotFound, branch
|
89
126
|
rescue Octokit::Conflict => e
|
@@ -91,9 +128,12 @@ module Dependabot
|
|
91
128
|
end
|
92
129
|
|
93
130
|
# Returns the path to the cloned repo
|
131
|
+
sig { returns(String) }
|
94
132
|
def clone_repo_contents
|
95
|
-
@clone_repo_contents ||=
|
96
|
-
_clone_repo_contents(target_directory: repo_contents_path)
|
133
|
+
@clone_repo_contents ||= T.let(
|
134
|
+
_clone_repo_contents(target_directory: repo_contents_path),
|
135
|
+
T.nilable(String)
|
136
|
+
)
|
97
137
|
rescue Dependabot::SharedHelpers::HelperSubprocessFailed => e
|
98
138
|
if e.message.include?("fatal: Remote branch #{target_branch} not found in upstream origin")
|
99
139
|
raise Dependabot::BranchNotFound, target_branch
|
@@ -104,16 +144,17 @@ module Dependabot
|
|
104
144
|
raise Dependabot::RepoNotFound.new(source, e.message)
|
105
145
|
end
|
106
146
|
|
107
|
-
|
108
|
-
|
109
|
-
end
|
147
|
+
sig { overridable.returns(T.nilable(T::Hash[Symbol, T.untyped])) }
|
148
|
+
def ecosystem_versions; end
|
110
149
|
|
111
150
|
private
|
112
151
|
|
152
|
+
sig { params(name: String).returns(T.nilable(Dependabot::DependencyFile)) }
|
113
153
|
def fetch_support_file(name)
|
114
154
|
fetch_file_if_present(name)&.tap { |f| f.support_file = true }
|
115
155
|
end
|
116
156
|
|
157
|
+
sig { params(filename: String, fetch_submodules: T::Boolean).returns(T.nilable(DependencyFile)) }
|
117
158
|
def fetch_file_if_present(filename, fetch_submodules: false)
|
118
159
|
unless repo_contents_path.nil?
|
119
160
|
begin
|
@@ -137,6 +178,7 @@ module Dependabot
|
|
137
178
|
nil
|
138
179
|
end
|
139
180
|
|
181
|
+
sig { params(filename: T.any(Pathname, String)).returns(Dependabot::DependencyFile) }
|
140
182
|
def load_cloned_file_if_present(filename)
|
141
183
|
path = Pathname.new(File.join(directory, filename)).cleanpath.to_path
|
142
184
|
repo_path = File.join(clone_repo_contents, path)
|
@@ -160,6 +202,14 @@ module Dependabot
|
|
160
202
|
)
|
161
203
|
end
|
162
204
|
|
205
|
+
sig do
|
206
|
+
params(
|
207
|
+
filename: T.any(Pathname, String),
|
208
|
+
type: String,
|
209
|
+
fetch_submodules: T::Boolean
|
210
|
+
)
|
211
|
+
.returns(Dependabot::DependencyFile)
|
212
|
+
end
|
163
213
|
def fetch_file_from_host(filename, type: "file", fetch_submodules: false)
|
164
214
|
return load_cloned_file_if_present(filename) unless repo_contents_path.nil?
|
165
215
|
|
@@ -169,7 +219,7 @@ module Dependabot
|
|
169
219
|
|
170
220
|
linked_path = symlinked_subpath(clean_path)
|
171
221
|
type = "symlink" if linked_path
|
172
|
-
symlink_target = clean_path.sub(linked_path, @linked_paths.dig(linked_path, :path)) if type == "symlink"
|
222
|
+
symlink_target = clean_path.sub(T.must(linked_path), @linked_paths.dig(linked_path, :path)) if type == "symlink"
|
173
223
|
|
174
224
|
DependencyFile.new(
|
175
225
|
name: Pathname.new(filename).cleanpath.to_path,
|
@@ -183,65 +233,87 @@ module Dependabot
|
|
183
233
|
end
|
184
234
|
|
185
235
|
# Finds the first subpath in path that is a symlink
|
236
|
+
sig { params(path: String).returns(T.nilable(String)) }
|
186
237
|
def symlinked_subpath(path)
|
187
238
|
subpaths(path).find { |subpath| @linked_paths.key?(subpath) }
|
188
239
|
end
|
189
240
|
|
241
|
+
sig { params(path: String).returns(T::Boolean) }
|
190
242
|
def in_submodule?(path)
|
191
243
|
subpaths(path.delete_prefix("/")).any? { |subpath| @submodules.include?(subpath) }
|
192
244
|
end
|
193
245
|
|
194
246
|
# Given a "foo/bar/baz" path, returns ["foo", "foo/bar", "foo/bar/baz"]
|
247
|
+
sig { params(path: String).returns(T::Array[String]) }
|
195
248
|
def subpaths(path)
|
196
249
|
components = path.split("/")
|
197
|
-
components.map { |component| components[0..components.index(component)].join("/") }
|
250
|
+
components.map { |component| T.must(components[0..components.index(component)]).join("/") }
|
198
251
|
end
|
199
252
|
|
253
|
+
sig do
|
254
|
+
params(
|
255
|
+
dir: T.any(Pathname, String),
|
256
|
+
ignore_base_directory: T::Boolean,
|
257
|
+
raise_errors: T::Boolean,
|
258
|
+
fetch_submodules: T::Boolean
|
259
|
+
)
|
260
|
+
.returns(T::Array[T.untyped])
|
261
|
+
end
|
200
262
|
def repo_contents(dir: ".", ignore_base_directory: false,
|
201
263
|
raise_errors: true, fetch_submodules: false)
|
202
264
|
dir = File.join(directory, dir) unless ignore_base_directory
|
203
265
|
path = Pathname.new(dir).cleanpath.to_path.gsub(%r{^/*}, "")
|
204
266
|
|
205
|
-
@repo_contents ||= {}
|
206
|
-
@repo_contents[dir] ||= if repo_contents_path
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
267
|
+
@repo_contents ||= T.let({}, T.nilable(T::Hash[String, T::Array[T.untyped]]))
|
268
|
+
@repo_contents[dir.to_s] ||= if repo_contents_path
|
269
|
+
_cloned_repo_contents(path)
|
270
|
+
else
|
271
|
+
_fetch_repo_contents(path, raise_errors: raise_errors,
|
272
|
+
fetch_submodules: fetch_submodules)
|
273
|
+
end
|
212
274
|
end
|
213
275
|
|
276
|
+
sig { returns(T.nilable(String)) }
|
214
277
|
def cloned_commit
|
215
278
|
return if repo_contents_path.nil? || !File.directory?(File.join(repo_contents_path, ".git"))
|
216
279
|
|
217
280
|
SharedHelpers.with_git_configured(credentials: credentials) do
|
218
|
-
Dir.chdir(repo_contents_path) do
|
219
|
-
return SharedHelpers.run_shell_command("git rev-parse HEAD")
|
281
|
+
Dir.chdir(T.must(repo_contents_path)) do
|
282
|
+
return SharedHelpers.run_shell_command("git rev-parse HEAD").strip
|
220
283
|
end
|
221
284
|
end
|
222
285
|
end
|
223
286
|
|
287
|
+
sig { returns(String) }
|
224
288
|
def default_branch_for_repo
|
225
|
-
@default_branch_for_repo ||= client_for_provider
|
226
|
-
.fetch_default_branch(repo)
|
289
|
+
@default_branch_for_repo ||= T.let(T.unsafe(client_for_provider).fetch_default_branch(repo), T.nilable(String))
|
227
290
|
rescue *CLIENT_NOT_FOUND_ERRORS
|
228
291
|
raise Dependabot::RepoNotFound, source
|
229
292
|
end
|
230
293
|
|
294
|
+
sig do
|
295
|
+
params(
|
296
|
+
repo: String,
|
297
|
+
path: String,
|
298
|
+
commit: String,
|
299
|
+
github_response: Sawyer::Resource
|
300
|
+
)
|
301
|
+
.returns(T.nilable(T::Hash[String, T.untyped]))
|
302
|
+
end
|
231
303
|
def update_linked_paths(repo, path, commit, github_response)
|
232
|
-
case github_response.type
|
304
|
+
case T.unsafe(github_response).type
|
233
305
|
when "submodule"
|
234
|
-
sub_source = Source.from_url(github_response.submodule_git_url)
|
306
|
+
sub_source = Source.from_url(T.unsafe(github_response).submodule_git_url)
|
235
307
|
return unless sub_source
|
236
308
|
|
237
309
|
@linked_paths[path] = {
|
238
310
|
repo: sub_source.repo,
|
239
311
|
provider: sub_source.provider,
|
240
|
-
commit: github_response.sha,
|
312
|
+
commit: T.unsafe(github_response).sha,
|
241
313
|
path: "/"
|
242
314
|
}
|
243
315
|
when "symlink"
|
244
|
-
updated_path = File.join(File.dirname(path), github_response.target)
|
316
|
+
updated_path = File.join(File.dirname(path), T.unsafe(github_response).target)
|
245
317
|
@linked_paths[path] = {
|
246
318
|
repo: repo,
|
247
319
|
provider: "github",
|
@@ -251,10 +323,22 @@ module Dependabot
|
|
251
323
|
end
|
252
324
|
end
|
253
325
|
|
326
|
+
sig { returns(T::Boolean) }
|
254
327
|
def recurse_submodules_when_cloning?
|
255
328
|
false
|
256
329
|
end
|
257
330
|
|
331
|
+
sig do
|
332
|
+
returns(
|
333
|
+
T.any(
|
334
|
+
Dependabot::Clients::GithubWithRetries,
|
335
|
+
Dependabot::Clients::GitlabWithRetries,
|
336
|
+
Dependabot::Clients::Azure,
|
337
|
+
Dependabot::Clients::BitbucketWithRetries,
|
338
|
+
Dependabot::Clients::CodeCommit
|
339
|
+
)
|
340
|
+
)
|
341
|
+
end
|
258
342
|
def client_for_provider
|
259
343
|
case source.provider
|
260
344
|
when "github" then github_client
|
@@ -266,46 +350,75 @@ module Dependabot
|
|
266
350
|
end
|
267
351
|
end
|
268
352
|
|
353
|
+
sig { returns(Dependabot::Clients::GithubWithRetries) }
|
269
354
|
def github_client
|
270
355
|
@github_client ||=
|
271
|
-
|
272
|
-
|
273
|
-
|
356
|
+
T.let(
|
357
|
+
Dependabot::Clients::GithubWithRetries.for_source(
|
358
|
+
source: source,
|
359
|
+
credentials: credentials
|
360
|
+
),
|
361
|
+
T.nilable(Dependabot::Clients::GithubWithRetries)
|
274
362
|
)
|
275
363
|
end
|
276
364
|
|
365
|
+
sig { returns(Dependabot::Clients::GitlabWithRetries) }
|
277
366
|
def gitlab_client
|
278
367
|
@gitlab_client ||=
|
279
|
-
|
280
|
-
|
281
|
-
|
368
|
+
T.let(
|
369
|
+
Dependabot::Clients::GitlabWithRetries.for_source(
|
370
|
+
source: source,
|
371
|
+
credentials: credentials
|
372
|
+
),
|
373
|
+
T.nilable(Dependabot::Clients::GitlabWithRetries)
|
282
374
|
)
|
283
375
|
end
|
284
376
|
|
377
|
+
sig { returns(Dependabot::Clients::Azure) }
|
285
378
|
def azure_client
|
286
379
|
@azure_client ||=
|
287
|
-
|
288
|
-
|
380
|
+
T.let(
|
381
|
+
Dependabot::Clients::Azure.for_source(
|
382
|
+
source: source,
|
383
|
+
credentials: credentials
|
384
|
+
),
|
385
|
+
T.nilable(Dependabot::Clients::Azure)
|
386
|
+
)
|
289
387
|
end
|
290
388
|
|
389
|
+
sig { returns(Dependabot::Clients::BitbucketWithRetries) }
|
291
390
|
def bitbucket_client
|
292
391
|
# TODO: When self-hosted Bitbucket is supported this should use
|
293
392
|
# `Bitbucket.for_source`
|
294
393
|
@bitbucket_client ||=
|
295
|
-
|
296
|
-
|
394
|
+
T.let(
|
395
|
+
Dependabot::Clients::BitbucketWithRetries.for_bitbucket_dot_org(
|
396
|
+
credentials: credentials
|
397
|
+
),
|
398
|
+
T.nilable(Dependabot::Clients::BitbucketWithRetries)
|
399
|
+
)
|
297
400
|
end
|
298
401
|
|
402
|
+
sig { returns(Dependabot::Clients::CodeCommit) }
|
299
403
|
def codecommit_client
|
300
404
|
@codecommit_client ||=
|
301
|
-
|
302
|
-
|
405
|
+
T.let(
|
406
|
+
Dependabot::Clients::CodeCommit.for_source(
|
407
|
+
source: source,
|
408
|
+
credentials: credentials
|
409
|
+
),
|
410
|
+
T.nilable(Dependabot::Clients::CodeCommit)
|
411
|
+
)
|
303
412
|
end
|
304
413
|
|
305
414
|
#################################################
|
306
415
|
# INTERNAL METHODS (not for use by sub-classes) #
|
307
416
|
#################################################
|
308
417
|
|
418
|
+
sig do
|
419
|
+
params(path: String, fetch_submodules: T::Boolean, raise_errors: T::Boolean)
|
420
|
+
.returns(T::Array[OpenStruct])
|
421
|
+
end
|
309
422
|
def _fetch_repo_contents(path, fetch_submodules: false,
|
310
423
|
raise_errors: true)
|
311
424
|
path = path.gsub(" ", "%20")
|
@@ -337,6 +450,10 @@ module Dependabot
|
|
337
450
|
retry
|
338
451
|
end
|
339
452
|
|
453
|
+
sig do
|
454
|
+
params(provider: String, repo: String, path: String, commit: String)
|
455
|
+
.returns(T::Array[OpenStruct])
|
456
|
+
end
|
340
457
|
def _fetch_repo_contents_fully_specified(provider, repo, path, commit)
|
341
458
|
case provider
|
342
459
|
when "github"
|
@@ -353,9 +470,10 @@ module Dependabot
|
|
353
470
|
end
|
354
471
|
end
|
355
472
|
|
473
|
+
sig { params(repo: String, path: String, commit: String).returns(T::Array[OpenStruct]) }
|
356
474
|
def _github_repo_contents(repo, path, commit)
|
357
475
|
path = path.gsub(" ", "%20")
|
358
|
-
github_response = github_client.contents(repo, path: path, ref: commit)
|
476
|
+
github_response = T.unsafe(github_client).contents(repo, path: path, ref: commit)
|
359
477
|
|
360
478
|
if github_response.respond_to?(:type)
|
361
479
|
update_linked_paths(repo, path, commit, github_response)
|
@@ -365,6 +483,7 @@ module Dependabot
|
|
365
483
|
github_response.map { |f| _build_github_file_struct(f) }
|
366
484
|
end
|
367
485
|
|
486
|
+
sig { params(relative_path: String).returns(T::Array[OpenStruct]) }
|
368
487
|
def _cloned_repo_contents(relative_path)
|
369
488
|
repo_path = File.join(clone_repo_contents, relative_path)
|
370
489
|
return [] unless Dir.exist?(repo_path)
|
@@ -390,37 +509,40 @@ module Dependabot
|
|
390
509
|
end
|
391
510
|
end
|
392
511
|
|
512
|
+
sig { params(file: Sawyer::Resource).returns(OpenStruct) }
|
393
513
|
def _build_github_file_struct(file)
|
394
514
|
OpenStruct.new(
|
395
|
-
name: file.name,
|
396
|
-
path: file.path,
|
397
|
-
type: file.type,
|
398
|
-
sha: file.sha,
|
399
|
-
size: file.size
|
515
|
+
name: T.unsafe(file).name,
|
516
|
+
path: T.unsafe(file).path,
|
517
|
+
type: T.unsafe(file).type,
|
518
|
+
sha: T.unsafe(file).sha,
|
519
|
+
size: T.unsafe(file).size
|
400
520
|
)
|
401
521
|
end
|
402
522
|
|
523
|
+
sig { params(repo: String, path: String, commit: String).returns(T::Array[OpenStruct]) }
|
403
524
|
def _gitlab_repo_contents(repo, path, commit)
|
404
|
-
gitlab_client
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
525
|
+
T.unsafe(gitlab_client)
|
526
|
+
.repo_tree(repo, path: path, ref: commit, per_page: 100)
|
527
|
+
.map do |file|
|
528
|
+
# GitLab API essentially returns the output from `git ls-tree`
|
529
|
+
type = case file.type
|
530
|
+
when "blob" then "file"
|
531
|
+
when "tree" then "dir"
|
532
|
+
when "commit" then "submodule"
|
533
|
+
else file.fetch("type")
|
534
|
+
end
|
535
|
+
|
536
|
+
OpenStruct.new(
|
537
|
+
name: file.name,
|
538
|
+
path: file.path,
|
539
|
+
type: type,
|
540
|
+
size: 0 # GitLab doesn't return file size
|
541
|
+
)
|
542
|
+
end
|
422
543
|
end
|
423
544
|
|
545
|
+
sig { params(path: String, commit: String).returns(T::Array[OpenStruct]) }
|
424
546
|
def _azure_repo_contents(path, commit)
|
425
547
|
response = azure_client.fetch_repo_contents(commit, path)
|
426
548
|
|
@@ -440,12 +562,14 @@ module Dependabot
|
|
440
562
|
end
|
441
563
|
end
|
442
564
|
|
565
|
+
sig { params(repo: String, path: String, commit: String).returns(T::Array[OpenStruct]) }
|
443
566
|
def _bitbucket_repo_contents(repo, path, commit)
|
444
|
-
response =
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
567
|
+
response = T.unsafe(bitbucket_client)
|
568
|
+
.fetch_repo_contents(
|
569
|
+
repo,
|
570
|
+
commit,
|
571
|
+
path
|
572
|
+
)
|
449
573
|
|
450
574
|
response.map do |file|
|
451
575
|
type = case file.fetch("type")
|
@@ -463,6 +587,7 @@ module Dependabot
|
|
463
587
|
end
|
464
588
|
end
|
465
589
|
|
590
|
+
sig { params(repo: String, path: String, commit: String).returns(T::Array[OpenStruct]) }
|
466
591
|
def _codecommit_repo_contents(repo, path, commit)
|
467
592
|
response = codecommit_client.fetch_repo_contents(
|
468
593
|
repo,
|
@@ -480,11 +605,12 @@ module Dependabot
|
|
480
605
|
end
|
481
606
|
end
|
482
607
|
|
608
|
+
sig { params(path: String, fetch_submodules: T::Boolean).returns(T::Hash[Symbol, T.untyped]) }
|
483
609
|
def _full_specification_for(path, fetch_submodules:)
|
484
610
|
if fetch_submodules && _linked_dir_for(path)
|
485
611
|
linked_dir_details = @linked_paths[_linked_dir_for(path)]
|
486
612
|
sub_path =
|
487
|
-
path.gsub(%r{^#{Regexp.quote(_linked_dir_for(path))}(/|$)}, "")
|
613
|
+
path.gsub(%r{^#{Regexp.quote(T.must(_linked_dir_for(path)))}(/|$)}, "")
|
488
614
|
new_path =
|
489
615
|
Pathname.new(File.join(linked_dir_details.fetch(:path), sub_path))
|
490
616
|
.cleanpath.to_path
|
@@ -505,6 +631,7 @@ module Dependabot
|
|
505
631
|
end
|
506
632
|
end
|
507
633
|
|
634
|
+
sig { params(path: String, fetch_submodules: T::Boolean).returns(String) }
|
508
635
|
def _fetch_file_content(path, fetch_submodules: false)
|
509
636
|
path = path.gsub(%r{^/*}, "")
|
510
637
|
|
@@ -525,17 +652,18 @@ module Dependabot
|
|
525
652
|
retry
|
526
653
|
end
|
527
654
|
|
655
|
+
sig { params(provider: String, repo: String, path: String, commit: String).returns(String) }
|
528
656
|
def _fetch_file_content_fully_specified(provider, repo, path, commit)
|
529
657
|
case provider
|
530
658
|
when "github"
|
531
659
|
_fetch_file_content_from_github(path, repo, commit)
|
532
660
|
when "gitlab"
|
533
|
-
tmp = gitlab_client.get_file(repo, path, commit).content
|
661
|
+
tmp = T.unsafe(gitlab_client).get_file(repo, path, commit).content
|
534
662
|
decode_binary_string(tmp)
|
535
663
|
when "azure"
|
536
664
|
azure_client.fetch_file_contents(commit, path)
|
537
665
|
when "bitbucket"
|
538
|
-
bitbucket_client.fetch_file_contents(repo, commit, path)
|
666
|
+
T.unsafe(bitbucket_client).fetch_file_contents(repo, commit, path)
|
539
667
|
when "codecommit"
|
540
668
|
codecommit_client.fetch_file_contents(repo, commit, path)
|
541
669
|
else raise "Unsupported provider '#{source.provider}'."
|
@@ -543,8 +671,9 @@ module Dependabot
|
|
543
671
|
end
|
544
672
|
|
545
673
|
# rubocop:disable Metrics/AbcSize
|
674
|
+
sig { params(path: String, repo: String, commit: String).returns(String) }
|
546
675
|
def _fetch_file_content_from_github(path, repo, commit)
|
547
|
-
tmp = github_client.contents(repo, path: path, ref: commit)
|
676
|
+
tmp = T.unsafe(github_client).contents(repo, path: path, ref: commit)
|
548
677
|
|
549
678
|
raise Octokit::NotFound if tmp.is_a?(Array)
|
550
679
|
|
@@ -555,7 +684,7 @@ module Dependabot
|
|
555
684
|
commit: commit,
|
556
685
|
path: Pathname.new(tmp.target).cleanpath.to_path
|
557
686
|
}
|
558
|
-
tmp = github_client.contents(
|
687
|
+
tmp = T.unsafe(github_client).contents(
|
559
688
|
repo,
|
560
689
|
path: Pathname.new(tmp.target).cleanpath.to_path,
|
561
690
|
ref: commit
|
@@ -565,7 +694,7 @@ module Dependabot
|
|
565
694
|
if tmp.content == ""
|
566
695
|
# The file may have exceeded the 1MB limit
|
567
696
|
# see https://github.blog/changelog/2022-05-03-increased-file-size-limit-when-retrieving-file-contents-via-rest-api/
|
568
|
-
github_client.contents(repo, path: path, ref: commit, accept: "application/vnd.github.v3.raw")
|
697
|
+
T.unsafe(github_client).contents(repo, path: path, ref: commit, accept: "application/vnd.github.v3.raw")
|
569
698
|
else
|
570
699
|
decode_binary_string(tmp.content)
|
571
700
|
end
|
@@ -579,7 +708,7 @@ module Dependabot
|
|
579
708
|
file_details = repo_contents(dir: dir).find { |f| f.name == basename }
|
580
709
|
raise unless file_details
|
581
710
|
|
582
|
-
tmp = github_client.blob(repo, file_details.sha)
|
711
|
+
tmp = T.unsafe(github_client).blob(repo, file_details.sha)
|
583
712
|
return tmp.content if tmp.encoding == "utf-8"
|
584
713
|
|
585
714
|
decode_binary_string(tmp.content)
|
@@ -589,6 +718,7 @@ module Dependabot
|
|
589
718
|
# Update the @linked_paths hash by exploiting a side-effect of
|
590
719
|
# recursively calling `repo_contents` for each directory up the tree
|
591
720
|
# until a submodule or symlink is found
|
721
|
+
sig { params(path: String).returns(T.nilable(T::Array[T.untyped])) }
|
592
722
|
def _find_linked_dirs(path)
|
593
723
|
path = Pathname.new(path).cleanpath.to_path.gsub(%r{^/*}, "")
|
594
724
|
dir = File.dirname(path)
|
@@ -603,6 +733,7 @@ module Dependabot
|
|
603
733
|
)
|
604
734
|
end
|
605
735
|
|
736
|
+
sig { params(path: String).returns(T.nilable(String)) }
|
606
737
|
def _linked_dir_for(path)
|
607
738
|
linked_dirs = @linked_paths.keys
|
608
739
|
linked_dirs
|
@@ -614,6 +745,7 @@ module Dependabot
|
|
614
745
|
# rubocop:disable Metrics/MethodLength
|
615
746
|
# rubocop:disable Metrics/PerceivedComplexity
|
616
747
|
# rubocop:disable Metrics/BlockLength
|
748
|
+
sig { params(target_directory: T.nilable(String)).returns(String) }
|
617
749
|
def _clone_repo_contents(target_directory:)
|
618
750
|
SharedHelpers.with_git_configured(credentials: credentials) do
|
619
751
|
path = target_directory || File.join("tmp", source.repo)
|
@@ -645,7 +777,7 @@ module Dependabot
|
|
645
777
|
raise unless e.message.match(GIT_SUBMODULE_ERROR_REGEX) && e.message.downcase.include?("submodule")
|
646
778
|
|
647
779
|
submodule_cloning_failed = true
|
648
|
-
match = e.message.match(GIT_SUBMODULE_ERROR_REGEX)
|
780
|
+
match = T.must(e.message.match(GIT_SUBMODULE_ERROR_REGEX))
|
649
781
|
url = match.named_captures["url"]
|
650
782
|
code = match.named_captures["code"]
|
651
783
|
|
@@ -688,11 +820,13 @@ module Dependabot
|
|
688
820
|
# rubocop:enable Metrics/PerceivedComplexity
|
689
821
|
# rubocop:enable Metrics/BlockLength
|
690
822
|
|
823
|
+
sig { params(str: String).returns(String) }
|
691
824
|
def decode_binary_string(str)
|
692
825
|
bom = (+"\xEF\xBB\xBF").force_encoding(Encoding::BINARY)
|
693
826
|
Base64.decode64(str).delete_prefix(bom).force_encoding("UTF-8").encode
|
694
827
|
end
|
695
828
|
|
829
|
+
sig { params(path: String).returns(T::Array[String]) }
|
696
830
|
def find_submodules(path)
|
697
831
|
SharedHelpers.run_shell_command(
|
698
832
|
<<~CMD
|
@@ -702,7 +836,7 @@ module Dependabot
|
|
702
836
|
info = line.split
|
703
837
|
|
704
838
|
type = info.first
|
705
|
-
path = info.last
|
839
|
+
path = T.must(info.last)
|
706
840
|
|
707
841
|
next path if type == DependencyFile::Mode::SUBMODULE
|
708
842
|
end
|