dependabot-npm_and_yarn 0.284.0 → 0.285.0
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf3271285f39bf1e7f91fad3995676126cf0b580184e741e1fe10b5d295a5f4e
|
4
|
+
data.tar.gz: 91d70c4bb5a9454ffb50e38fdcb92957649a8211a1a27349b023d9a2a104ac26
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c3f3efeb4f22bfaad116b86ec6dcede6dfd378c2e669e9293f521ff9d285b54b7a072ce888c2eb0d44ef64605f144d9deb5f5ce9b723ee44c00366147f065474
|
7
|
+
data.tar.gz: 9426fe3a37b2b6af1c86dc79e7f596406a59329a0bc0429065387d7fe3a6cff987b69865f49c21df3bf90c8e46687dd291fc2a1a12f65fe8621487c7e8e56433
|
@@ -182,71 +182,93 @@ module Dependabot
|
|
182
182
|
|
183
183
|
sig { returns(T.nilable(T.any(Integer, String))) }
|
184
184
|
def npm_version
|
185
|
-
@npm_version ||= T.let(
|
185
|
+
@npm_version ||= T.let(package_manager_helper.setup(NpmPackageManager::NAME), T.nilable(T.any(Integer, String)))
|
186
186
|
end
|
187
187
|
|
188
188
|
sig { returns(T.nilable(T.any(Integer, String))) }
|
189
189
|
def yarn_version
|
190
|
-
@yarn_version ||= T.let(
|
190
|
+
@yarn_version ||= T.let(
|
191
|
+
package_manager_helper.setup(YarnPackageManager::NAME),
|
192
|
+
T.nilable(T.any(Integer, String))
|
193
|
+
)
|
191
194
|
end
|
192
195
|
|
193
196
|
sig { returns(T.nilable(T.any(Integer, String))) }
|
194
197
|
def pnpm_version
|
195
|
-
@pnpm_version ||= T.let(
|
198
|
+
@pnpm_version ||= T.let(
|
199
|
+
package_manager_helper.setup(PNPMPackageManager::NAME),
|
200
|
+
T.nilable(T.any(Integer, String))
|
201
|
+
)
|
196
202
|
end
|
197
203
|
|
198
|
-
sig { returns(
|
199
|
-
def
|
200
|
-
@
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
+
sig { returns(PackageManagerHelper) }
|
205
|
+
def package_manager_helper
|
206
|
+
@package_manager_helper ||= T.let(
|
207
|
+
PackageManagerHelper.new(
|
208
|
+
parsed_package_json,
|
209
|
+
lockfiles: lockfiles
|
210
|
+
), T.nilable(PackageManagerHelper)
|
211
|
+
)
|
212
|
+
end
|
213
|
+
|
214
|
+
sig { returns(T::Hash[Symbol, T.nilable(Dependabot::DependencyFile)]) }
|
215
|
+
def lockfiles
|
216
|
+
{
|
217
|
+
npm: package_lock || shrinkwrap,
|
218
|
+
yarn: yarn_lock,
|
219
|
+
pnpm: pnpm_lock
|
220
|
+
}
|
204
221
|
end
|
205
222
|
|
206
223
|
sig { returns(DependencyFile) }
|
207
224
|
def package_json
|
208
|
-
@package_json ||= T.let(fetch_file_from_host(
|
225
|
+
@package_json ||= T.let(fetch_file_from_host(MANIFEST_FILENAME), T.nilable(DependencyFile))
|
209
226
|
end
|
210
227
|
|
211
228
|
sig { returns(T.nilable(DependencyFile)) }
|
212
229
|
def package_lock
|
213
230
|
return @package_lock if defined?(@package_lock)
|
214
231
|
|
215
|
-
@package_lock ||= T.let(fetch_file_if_present(
|
232
|
+
@package_lock ||= T.let(fetch_file_if_present(NpmPackageManager::LOCKFILE_NAME), T.nilable(DependencyFile))
|
216
233
|
end
|
217
234
|
|
218
235
|
sig { returns(T.nilable(DependencyFile)) }
|
219
236
|
def yarn_lock
|
220
237
|
return @yarn_lock if defined?(@yarn_lock)
|
221
238
|
|
222
|
-
@yarn_lock ||= T.let(fetch_file_if_present(
|
239
|
+
@yarn_lock ||= T.let(fetch_file_if_present(YarnPackageManager::LOCKFILE_NAME), T.nilable(DependencyFile))
|
223
240
|
end
|
224
241
|
|
225
242
|
sig { returns(T.nilable(DependencyFile)) }
|
226
243
|
def pnpm_lock
|
227
244
|
return @pnpm_lock if defined?(@pnpm_lock)
|
228
245
|
|
229
|
-
@pnpm_lock ||= T.let(fetch_file_if_present(
|
246
|
+
@pnpm_lock ||= T.let(fetch_file_if_present(PNPMPackageManager::LOCKFILE_NAME), T.nilable(DependencyFile))
|
230
247
|
end
|
231
248
|
|
232
249
|
sig { returns(T.nilable(DependencyFile)) }
|
233
250
|
def shrinkwrap
|
234
251
|
return @shrinkwrap if defined?(@shrinkwrap)
|
235
252
|
|
236
|
-
@shrinkwrap ||= T.let(
|
253
|
+
@shrinkwrap ||= T.let(
|
254
|
+
fetch_file_if_present(
|
255
|
+
NpmPackageManager::SHRINKWRAP_LOCKFILE_NAME
|
256
|
+
),
|
257
|
+
T.nilable(DependencyFile)
|
258
|
+
)
|
237
259
|
end
|
238
260
|
|
239
261
|
sig { returns(T.nilable(DependencyFile)) }
|
240
262
|
def npmrc
|
241
263
|
return @npmrc if defined?(@npmrc)
|
242
264
|
|
243
|
-
@npmrc ||= T.let(fetch_support_file(
|
265
|
+
@npmrc ||= T.let(fetch_support_file(NpmPackageManager::RC_FILENAME), T.nilable(DependencyFile))
|
244
266
|
|
245
267
|
return @npmrc if @npmrc || directory == "/"
|
246
268
|
|
247
269
|
# Loop through parent directories looking for an npmrc
|
248
270
|
(1..directory.split("/").count).each do |i|
|
249
|
-
@npmrc = fetch_file_from_host(("../" * i) +
|
271
|
+
@npmrc = fetch_file_from_host(("../" * i) + NpmPackageManager::RC_FILENAME)
|
250
272
|
.tap { |f| f.support_file = true }
|
251
273
|
break if @npmrc
|
252
274
|
rescue Dependabot::DependencyFileNotFound
|
@@ -261,13 +283,13 @@ module Dependabot
|
|
261
283
|
def yarnrc
|
262
284
|
return @yarnrc if defined?(@yarnrc)
|
263
285
|
|
264
|
-
@yarnrc ||= T.let(fetch_support_file(
|
286
|
+
@yarnrc ||= T.let(fetch_support_file(YarnPackageManager::RC_FILENAME), T.nilable(DependencyFile))
|
265
287
|
|
266
288
|
return @yarnrc if @yarnrc || directory == "/"
|
267
289
|
|
268
290
|
# Loop through parent directories looking for an yarnrc
|
269
291
|
(1..directory.split("/").count).each do |i|
|
270
|
-
@yarnrc = fetch_file_from_host(("../" * i) +
|
292
|
+
@yarnrc = fetch_file_from_host(("../" * i) + YarnPackageManager::RC_FILENAME)
|
271
293
|
.tap { |f| f.support_file = true }
|
272
294
|
break if @yarnrc
|
273
295
|
rescue Dependabot::DependencyFileNotFound
|
@@ -280,21 +302,24 @@ module Dependabot
|
|
280
302
|
|
281
303
|
sig { returns(T.nilable(DependencyFile)) }
|
282
304
|
def yarnrc_yml
|
283
|
-
@yarnrc_yml ||= T.let(fetch_support_file(
|
305
|
+
@yarnrc_yml ||= T.let(fetch_support_file(YarnPackageManager::RC_YML_FILENAME), T.nilable(DependencyFile))
|
284
306
|
end
|
285
307
|
|
286
308
|
sig { returns(T.nilable(DependencyFile)) }
|
287
309
|
def pnpm_workspace_yaml
|
288
310
|
return @pnpm_workspace_yaml if defined?(@pnpm_workspace_yaml)
|
289
311
|
|
290
|
-
@pnpm_workspace_yaml = T.let(
|
312
|
+
@pnpm_workspace_yaml = T.let(
|
313
|
+
fetch_support_file(PNPMPackageManager::PNPM_WS_YML_FILENAME),
|
314
|
+
T.nilable(DependencyFile)
|
315
|
+
)
|
291
316
|
end
|
292
317
|
|
293
318
|
sig { returns(T.nilable(DependencyFile)) }
|
294
319
|
def lerna_json
|
295
320
|
return @lerna_json if defined?(@lerna_json)
|
296
321
|
|
297
|
-
@lerna_json = T.let(fetch_support_file(
|
322
|
+
@lerna_json = T.let(fetch_support_file(LERNA_JSON_FILENAME), T.nilable(DependencyFile))
|
298
323
|
end
|
299
324
|
|
300
325
|
sig { returns(T::Array[DependencyFile]) }
|
@@ -329,7 +354,7 @@ module Dependabot
|
|
329
354
|
filename = path
|
330
355
|
# NPM/Yarn support loading path dependencies from tarballs:
|
331
356
|
# https://docs.npmjs.com/cli/pack.html
|
332
|
-
filename = File.join(filename,
|
357
|
+
filename = File.join(filename, MANIFEST_FILENAME) unless filename.end_with?(".tgz", ".tar", ".tar.gz")
|
333
358
|
cleaned_name = Pathname.new(filename).cleanpath.to_path
|
334
359
|
next if fetched_files.map(&:name).include?(cleaned_name)
|
335
360
|
|
@@ -380,7 +405,7 @@ module Dependabot
|
|
380
405
|
# rubocop:disable Metrics/AbcSize
|
381
406
|
sig { params(file: DependencyFile).returns(T::Array[[String, String]]) }
|
382
407
|
def path_dependency_details_from_manifest(file)
|
383
|
-
return [] unless file.name.end_with?(
|
408
|
+
return [] unless file.name.end_with?(MANIFEST_FILENAME)
|
384
409
|
|
385
410
|
current_dir = file.name.rpartition("/").first
|
386
411
|
current_dir = nil if current_dir == ""
|
@@ -471,9 +496,9 @@ module Dependabot
|
|
471
496
|
return [] unless package_json
|
472
497
|
|
473
498
|
[package_json] + [
|
474
|
-
fetch_file_if_present(File.join(path,
|
475
|
-
fetch_file_if_present(File.join(path,
|
476
|
-
fetch_file_if_present(File.join(path,
|
499
|
+
fetch_file_if_present(File.join(path, NpmPackageManager::LOCKFILE_NAME)),
|
500
|
+
fetch_file_if_present(File.join(path, YarnPackageManager::LOCKFILE_NAME)),
|
501
|
+
fetch_file_if_present(File.join(path, NpmPackageManager::SHRINKWRAP_LOCKFILE_NAME))
|
477
502
|
]
|
478
503
|
end
|
479
504
|
|
@@ -542,7 +567,7 @@ module Dependabot
|
|
542
567
|
|
543
568
|
sig { params(workspace: String).returns(T.nilable(DependencyFile)) }
|
544
569
|
def fetch_package_json_if_present(workspace)
|
545
|
-
file = File.join(workspace,
|
570
|
+
file = File.join(workspace, MANIFEST_FILENAME)
|
546
571
|
|
547
572
|
begin
|
548
573
|
fetch_file_from_host(file)
|
@@ -635,4 +660,4 @@ module Dependabot
|
|
635
660
|
end
|
636
661
|
|
637
662
|
Dependabot::FileFetchers
|
638
|
-
.register(
|
663
|
+
.register(Dependabot::NpmAndYarn::ECOSYSTEM, Dependabot::NpmAndYarn::FileFetcher)
|
@@ -19,7 +19,7 @@ require "sorbet-runtime"
|
|
19
19
|
|
20
20
|
module Dependabot
|
21
21
|
module NpmAndYarn
|
22
|
-
class FileParser < Dependabot::FileParsers::Base
|
22
|
+
class FileParser < Dependabot::FileParsers::Base # rubocop:disable Metrics/ClassLength
|
23
23
|
extend T::Sig
|
24
24
|
|
25
25
|
require "dependabot/file_parsers/base/dependency_set"
|
@@ -78,8 +78,82 @@ module Dependabot
|
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
|
+
sig { returns(Ecosystem) }
|
82
|
+
def ecosystem
|
83
|
+
@ecosystem ||= T.let(
|
84
|
+
Ecosystem.new(
|
85
|
+
name: ECOSYSTEM,
|
86
|
+
package_manager: package_manager_helper.package_manager
|
87
|
+
),
|
88
|
+
T.nilable(Ecosystem)
|
89
|
+
)
|
90
|
+
end
|
91
|
+
|
81
92
|
private
|
82
93
|
|
94
|
+
sig { returns(PackageManagerHelper) }
|
95
|
+
def package_manager_helper
|
96
|
+
@package_manager_helper ||= T.let(
|
97
|
+
PackageManagerHelper.new(
|
98
|
+
parsed_package_json,
|
99
|
+
lockfiles: lockfiles
|
100
|
+
), T.nilable(PackageManagerHelper)
|
101
|
+
)
|
102
|
+
end
|
103
|
+
|
104
|
+
sig { returns(T::Hash[Symbol, T.nilable(Dependabot::DependencyFile)]) }
|
105
|
+
def lockfiles
|
106
|
+
{
|
107
|
+
npm: package_lock || shrinkwrap,
|
108
|
+
yarn: yarn_lock,
|
109
|
+
pnpm: pnpm_lock
|
110
|
+
}
|
111
|
+
end
|
112
|
+
|
113
|
+
sig { returns(T.untyped) }
|
114
|
+
def parsed_package_json
|
115
|
+
JSON.parse(T.must(package_json.content))
|
116
|
+
rescue JSON::ParserError
|
117
|
+
raise Dependabot::DependencyFileNotParseable, package_json.path
|
118
|
+
end
|
119
|
+
|
120
|
+
sig { returns(Dependabot::DependencyFile) }
|
121
|
+
def package_json
|
122
|
+
# Declare the instance variable with T.let and the correct type
|
123
|
+
@package_json ||= T.let(
|
124
|
+
T.must(dependency_files.find { |f| f.name == MANIFEST_FILENAME }),
|
125
|
+
T.nilable(Dependabot::DependencyFile)
|
126
|
+
)
|
127
|
+
end
|
128
|
+
|
129
|
+
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
130
|
+
def shrinkwrap
|
131
|
+
@shrinkwrap ||= T.let(dependency_files.find do |f|
|
132
|
+
f.name == NpmPackageManager::SHRINKWRAP_LOCKFILE_NAME
|
133
|
+
end, T.nilable(Dependabot::DependencyFile))
|
134
|
+
end
|
135
|
+
|
136
|
+
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
137
|
+
def package_lock
|
138
|
+
@package_lock ||= T.let(dependency_files.find do |f|
|
139
|
+
f.name == NpmPackageManager::LOCKFILE_NAME
|
140
|
+
end, T.nilable(Dependabot::DependencyFile))
|
141
|
+
end
|
142
|
+
|
143
|
+
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
144
|
+
def yarn_lock
|
145
|
+
@yarn_lock ||= T.let(dependency_files.find do |f|
|
146
|
+
f.name == YarnPackageManager::LOCKFILE_NAME
|
147
|
+
end, T.nilable(Dependabot::DependencyFile))
|
148
|
+
end
|
149
|
+
|
150
|
+
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
151
|
+
def pnpm_lock
|
152
|
+
@pnpm_lock ||= T.let(dependency_files.find do |f|
|
153
|
+
f.name == PNPMPackageManager::LOCKFILE_NAME
|
154
|
+
end, T.nilable(Dependabot::DependencyFile))
|
155
|
+
end
|
156
|
+
|
83
157
|
sig { returns(Dependabot::FileParsers::Base::DependencySet) }
|
84
158
|
def manifest_dependencies
|
85
159
|
dependency_set = DependencySet.new
|
@@ -154,7 +228,7 @@ module Dependabot
|
|
154
228
|
Dependency.new(
|
155
229
|
name: name,
|
156
230
|
version: converted_version,
|
157
|
-
package_manager:
|
231
|
+
package_manager: ECOSYSTEM,
|
158
232
|
requirements: [{
|
159
233
|
requirement: requirement_for(requirement),
|
160
234
|
file: file.name,
|
@@ -166,7 +240,10 @@ module Dependabot
|
|
166
240
|
|
167
241
|
sig { override.void }
|
168
242
|
def check_required_files
|
169
|
-
|
243
|
+
return if get_original_file(MANIFEST_FILENAME)
|
244
|
+
|
245
|
+
raise DependencyFileNotFound.new(nil,
|
246
|
+
"#{MANIFEST_FILENAME} not found.")
|
170
247
|
end
|
171
248
|
|
172
249
|
sig { params(requirement: String).returns(T::Boolean) }
|
@@ -186,7 +263,7 @@ module Dependabot
|
|
186
263
|
|
187
264
|
sig { params(requirement: String).returns(T::Boolean) }
|
188
265
|
def alias_package?(requirement)
|
189
|
-
requirement.start_with?("
|
266
|
+
requirement.start_with?("#{NpmPackageManager::NAME}:")
|
190
267
|
end
|
191
268
|
|
192
269
|
sig { params(requirement: String).returns(T::Boolean) }
|
@@ -208,7 +285,7 @@ module Dependabot
|
|
208
285
|
|
209
286
|
sig { params(name: String).returns(T::Boolean) }
|
210
287
|
def aliased_package_name?(name)
|
211
|
-
name.include?("
|
288
|
+
name.include?("@#{NpmPackageManager::NAME}:")
|
212
289
|
end
|
213
290
|
|
214
291
|
sig { returns(T::Array[String]) }
|
@@ -370,8 +447,8 @@ module Dependabot
|
|
370
447
|
def sub_package_files
|
371
448
|
return T.must(@sub_package_files) if defined?(@sub_package_files)
|
372
449
|
|
373
|
-
files = dependency_files.select { |f| f.name.end_with?(
|
374
|
-
.reject { |f| f.name ==
|
450
|
+
files = dependency_files.select { |f| f.name.end_with?(MANIFEST_FILENAME) }
|
451
|
+
.reject { |f| f.name == MANIFEST_FILENAME }
|
375
452
|
.reject { |f| f.name.include?("node_modules/") }
|
376
453
|
@sub_package_files ||= T.let(files, T.nilable(T::Array[Dependabot::DependencyFile]))
|
377
454
|
end
|
@@ -380,7 +457,7 @@ module Dependabot
|
|
380
457
|
def package_files
|
381
458
|
@package_files ||= T.let(
|
382
459
|
[
|
383
|
-
dependency_files.find { |f| f.name ==
|
460
|
+
dependency_files.find { |f| f.name == MANIFEST_FILENAME },
|
384
461
|
*sub_package_files
|
385
462
|
].compact, T.nilable(T::Array[DependencyFile])
|
386
463
|
)
|
@@ -37,7 +37,7 @@ module Dependabot
|
|
37
37
|
# Determines the npm version depends to the feature flag
|
38
38
|
# If the feature flag is enabled, we are going to use the minimum version npm 8
|
39
39
|
# Otherwise, we are going to use old versionining npm 6
|
40
|
-
sig { params(lockfile: DependencyFile).returns(Integer) }
|
40
|
+
sig { params(lockfile: T.nilable(DependencyFile)).returns(Integer) }
|
41
41
|
def self.npm_version_numeric(lockfile)
|
42
42
|
fallback_version_npm8 = Dependabot::Experiments.enabled?(:npm_fallback_version_above_v6)
|
43
43
|
|
@@ -46,10 +46,15 @@ module Dependabot
|
|
46
46
|
npm_version_numeric_npm6_or_higher(lockfile)
|
47
47
|
end
|
48
48
|
|
49
|
-
sig { params(lockfile: DependencyFile).returns(Integer) }
|
49
|
+
sig { params(lockfile: T.nilable(DependencyFile)).returns(Integer) }
|
50
50
|
def self.npm_version_numeric_npm6_or_higher(lockfile)
|
51
|
-
lockfile_content =
|
52
|
-
|
51
|
+
lockfile_content = lockfile&.content
|
52
|
+
|
53
|
+
if lockfile_content.nil? ||
|
54
|
+
lockfile_content.strip.empty? ||
|
55
|
+
JSON.parse(lockfile_content)["lockfileVersion"].to_i >= 2
|
56
|
+
return NPM_V8
|
57
|
+
end
|
53
58
|
|
54
59
|
NPM_V6
|
55
60
|
rescue JSON::ParserError
|
@@ -60,9 +65,9 @@ module Dependabot
|
|
60
65
|
# - NPM 7 uses lockfileVersion 2
|
61
66
|
# - NPM 8 uses lockfileVersion 2
|
62
67
|
# - NPM 9 uses lockfileVersion 3
|
63
|
-
sig { params(lockfile: DependencyFile).returns(Integer) }
|
68
|
+
sig { params(lockfile: T.nilable(DependencyFile)).returns(Integer) }
|
64
69
|
def self.npm_version_numeric_npm8_or_higher(lockfile)
|
65
|
-
lockfile_content = lockfile
|
70
|
+
lockfile_content = lockfile&.content
|
66
71
|
|
67
72
|
# Return default NPM version if there's no lockfile or it's empty
|
68
73
|
return NPM_DEFAULT_VERSION if lockfile_content.nil? || lockfile_content.strip.empty?
|
@@ -85,8 +90,12 @@ module Dependabot
|
|
85
90
|
NPM_DEFAULT_VERSION # Fallback to default npm version if parsing fails
|
86
91
|
end
|
87
92
|
|
88
|
-
sig { params(yarn_lock: DependencyFile).returns(Integer) }
|
93
|
+
sig { params(yarn_lock: T.nilable(DependencyFile)).returns(Integer) }
|
89
94
|
def self.yarn_version_numeric(yarn_lock)
|
95
|
+
lockfile_content = yarn_lock&.content
|
96
|
+
|
97
|
+
return YARN_DEFAULT_VERSION if lockfile_content.nil? || lockfile_content.strip.empty?
|
98
|
+
|
90
99
|
if yarn_berry?(yarn_lock)
|
91
100
|
YARN_DEFAULT_VERSION
|
92
101
|
else
|
@@ -97,8 +106,12 @@ module Dependabot
|
|
97
106
|
# Mapping from lockfile versions to PNPM versions is at
|
98
107
|
# https://github.com/pnpm/spec/tree/274ff02de23376ad59773a9f25ecfedd03a41f64/lockfile, but simplify it for now.
|
99
108
|
|
100
|
-
sig { params(pnpm_lock: DependencyFile).returns(Integer) }
|
109
|
+
sig { params(pnpm_lock: T.nilable(DependencyFile)).returns(Integer) }
|
101
110
|
def self.pnpm_version_numeric(pnpm_lock)
|
111
|
+
lockfile_content = pnpm_lock&.content
|
112
|
+
|
113
|
+
return PNPM_DEFAULT_VERSION if lockfile_content.nil? || lockfile_content.strip.empty?
|
114
|
+
|
102
115
|
pnpm_lockfile_version = pnpm_lockfile_version(pnpm_lock).to_f
|
103
116
|
return PNPM_V9 if pnpm_lockfile_version >= 9.0
|
104
117
|
return PNPM_V8 if pnpm_lockfile_version >= 6.0
|
@@ -117,7 +130,7 @@ module Dependabot
|
|
117
130
|
|
118
131
|
sig { params(package_lock: T.nilable(DependencyFile)).returns(T::Boolean) }
|
119
132
|
def self.npm8?(package_lock)
|
120
|
-
return true unless package_lock
|
133
|
+
return true unless package_lock&.content
|
121
134
|
|
122
135
|
npm_version_numeric(package_lock) == NPM_V8
|
123
136
|
end
|
@@ -2,18 +2,225 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "dependabot/shared_helpers"
|
5
|
+
require "dependabot/ecosystem"
|
5
6
|
require "dependabot/npm_and_yarn/version_selector"
|
6
7
|
|
7
8
|
module Dependabot
|
8
9
|
module NpmAndYarn
|
9
|
-
|
10
|
+
ECOSYSTEM = "npm_and_yarn"
|
11
|
+
MANIFEST_FILENAME = "package.json"
|
12
|
+
LERNA_JSON_FILENAME = "lerna.json"
|
13
|
+
|
14
|
+
MANIFEST_PACKAGE_MANAGER_KEY = "packageManager"
|
15
|
+
MANIFEST_ENGINES_KEY = "engines"
|
16
|
+
|
17
|
+
class NpmPackageManager < Ecosystem::VersionManager
|
18
|
+
extend T::Sig
|
19
|
+
NAME = "npm"
|
20
|
+
RC_FILENAME = ".npmrc"
|
21
|
+
LOCKFILE_NAME = "package-lock.json"
|
22
|
+
SHRINKWRAP_LOCKFILE_NAME = "npm-shrinkwrap.json"
|
23
|
+
|
24
|
+
NPM_V6 = "6"
|
25
|
+
NPM_V7 = "7"
|
26
|
+
NPM_V8 = "8"
|
27
|
+
NPM_V9 = "9"
|
28
|
+
|
29
|
+
# Keep versions in ascending order
|
30
|
+
SUPPORTED_VERSIONS = T.let([
|
31
|
+
Version.new(NPM_V6),
|
32
|
+
Version.new(NPM_V7),
|
33
|
+
Version.new(NPM_V8),
|
34
|
+
Version.new(NPM_V9)
|
35
|
+
].freeze, T::Array[Dependabot::Version])
|
36
|
+
|
37
|
+
DEPRECATED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version])
|
38
|
+
|
39
|
+
sig { params(raw_version: String).void }
|
40
|
+
def initialize(raw_version)
|
41
|
+
super(
|
42
|
+
NAME,
|
43
|
+
Version.new(raw_version),
|
44
|
+
DEPRECATED_VERSIONS,
|
45
|
+
SUPPORTED_VERSIONS
|
46
|
+
)
|
47
|
+
end
|
48
|
+
|
49
|
+
sig { override.returns(T::Boolean) }
|
50
|
+
def deprecated?
|
51
|
+
false
|
52
|
+
end
|
53
|
+
|
54
|
+
sig { override.returns(T::Boolean) }
|
55
|
+
def unsupported?
|
56
|
+
false
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class YarnPackageManager < Ecosystem::VersionManager
|
61
|
+
extend T::Sig
|
62
|
+
NAME = "yarn"
|
63
|
+
RC_FILENAME = ".yarnrc"
|
64
|
+
RC_YML_FILENAME = ".yarnrc.yml"
|
65
|
+
LOCKFILE_NAME = "yarn.lock"
|
66
|
+
|
67
|
+
YARN_V1 = "1"
|
68
|
+
YARN_V2 = "2"
|
69
|
+
YARN_V3 = "3"
|
70
|
+
|
71
|
+
SUPPORTED_VERSIONS = T.let([
|
72
|
+
Version.new(YARN_V1),
|
73
|
+
Version.new(YARN_V2),
|
74
|
+
Version.new(YARN_V3)
|
75
|
+
].freeze, T::Array[Dependabot::Version])
|
76
|
+
|
77
|
+
DEPRECATED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version])
|
78
|
+
|
79
|
+
sig { params(raw_version: String).void }
|
80
|
+
def initialize(raw_version)
|
81
|
+
super(
|
82
|
+
NAME,
|
83
|
+
Version.new(raw_version),
|
84
|
+
DEPRECATED_VERSIONS,
|
85
|
+
SUPPORTED_VERSIONS
|
86
|
+
)
|
87
|
+
end
|
88
|
+
|
89
|
+
sig { override.returns(T::Boolean) }
|
90
|
+
def deprecated?
|
91
|
+
false
|
92
|
+
end
|
93
|
+
|
94
|
+
sig { override.returns(T::Boolean) }
|
95
|
+
def unsupported?
|
96
|
+
false
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class PNPMPackageManager < Ecosystem::VersionManager
|
101
|
+
extend T::Sig
|
102
|
+
NAME = "pnpm"
|
103
|
+
LOCKFILE_NAME = "pnpm-lock.yaml"
|
104
|
+
PNPM_WS_YML_FILENAME = "pnpm-workspace.yaml"
|
105
|
+
|
106
|
+
PNPM_V7 = "7"
|
107
|
+
PNPM_V8 = "8"
|
108
|
+
PNPM_V9 = "9"
|
109
|
+
|
110
|
+
SUPPORTED_VERSIONS = T.let([
|
111
|
+
Version.new(PNPM_V7),
|
112
|
+
Version.new(PNPM_V8),
|
113
|
+
Version.new(PNPM_V9)
|
114
|
+
].freeze, T::Array[Dependabot::Version])
|
115
|
+
|
116
|
+
DEPRECATED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version])
|
117
|
+
|
118
|
+
sig { params(raw_version: String).void }
|
119
|
+
def initialize(raw_version)
|
120
|
+
super(
|
121
|
+
NAME,
|
122
|
+
Version.new(raw_version),
|
123
|
+
DEPRECATED_VERSIONS,
|
124
|
+
SUPPORTED_VERSIONS
|
125
|
+
)
|
126
|
+
end
|
127
|
+
|
128
|
+
sig { override.returns(T::Boolean) }
|
129
|
+
def deprecated?
|
130
|
+
false
|
131
|
+
end
|
132
|
+
|
133
|
+
sig { override.returns(T::Boolean) }
|
134
|
+
def unsupported?
|
135
|
+
false
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
DEFAULT_PACKAGE_MANAGER = NpmPackageManager::NAME
|
140
|
+
|
141
|
+
PACKAGE_MANAGER_CLASSES = {
|
142
|
+
NpmPackageManager::NAME => NpmPackageManager,
|
143
|
+
YarnPackageManager::NAME => YarnPackageManager,
|
144
|
+
PNPMPackageManager::NAME => PNPMPackageManager
|
145
|
+
}.freeze
|
146
|
+
|
147
|
+
class PackageManagerDetector
|
148
|
+
extend T::Sig
|
149
|
+
extend T::Helpers
|
150
|
+
|
151
|
+
sig do
|
152
|
+
params(
|
153
|
+
lockfiles: T::Hash[Symbol, T.nilable(Dependabot::DependencyFile)],
|
154
|
+
package_json: T::Hash[String, T.untyped]
|
155
|
+
).void
|
156
|
+
end
|
157
|
+
def initialize(lockfiles, package_json)
|
158
|
+
@lockfiles = lockfiles
|
159
|
+
@package_json = package_json
|
160
|
+
@manifest_package_manager = package_json["packageManager"]
|
161
|
+
@engines = package_json.fetch(MANIFEST_ENGINES_KEY, nil)
|
162
|
+
end
|
163
|
+
|
164
|
+
# Returns npm, yarn, or pnpm based on the lockfiles, package.json, and engines
|
165
|
+
# Defaults to npm if no package manager is detected
|
166
|
+
sig { returns(String) }
|
167
|
+
def detect_package_manager
|
168
|
+
name_from_lockfiles || name_from_package_manager_attr || name_from_engines || DEFAULT_PACKAGE_MANAGER
|
169
|
+
end
|
170
|
+
|
171
|
+
private
|
172
|
+
|
173
|
+
sig { returns(T.nilable(String)) }
|
174
|
+
def name_from_lockfiles
|
175
|
+
PACKAGE_MANAGER_CLASSES.each_key do |manager_name| # iterates keys in order as defined in the hash
|
176
|
+
return manager_name.to_s if @lockfiles[manager_name.to_sym]
|
177
|
+
end
|
178
|
+
nil
|
179
|
+
end
|
180
|
+
|
181
|
+
sig { returns(T.nilable(String)) }
|
182
|
+
def name_from_package_manager_attr
|
183
|
+
return unless @manifest_package_manager
|
184
|
+
|
185
|
+
PACKAGE_MANAGER_CLASSES.each_key do |manager_name| # iterates keys in order as defined in the hash
|
186
|
+
return manager_name.to_s if @manifest_package_manager.start_with?("#{manager_name}@")
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
sig { returns(T.nilable(String)) }
|
191
|
+
def name_from_engines
|
192
|
+
return unless @engines.is_a?(Hash)
|
193
|
+
|
194
|
+
PACKAGE_MANAGER_CLASSES.each_key do |manager_name|
|
195
|
+
return manager_name if @engines[manager_name]
|
196
|
+
end
|
197
|
+
nil
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
class PackageManagerHelper
|
10
202
|
extend T::Sig
|
11
203
|
extend T::Helpers
|
204
|
+
|
205
|
+
sig do
|
206
|
+
params(
|
207
|
+
package_json: T::Hash[String, T.untyped],
|
208
|
+
lockfiles: T::Hash[Symbol, T.nilable(Dependabot::DependencyFile)]
|
209
|
+
).void
|
210
|
+
end
|
12
211
|
def initialize(package_json, lockfiles:)
|
13
212
|
@package_json = package_json
|
14
213
|
@lockfiles = lockfiles
|
15
|
-
@
|
16
|
-
@engines = package_json.fetch(
|
214
|
+
@manifest_package_manager = package_json[MANIFEST_PACKAGE_MANAGER_KEY]
|
215
|
+
@engines = package_json.fetch(MANIFEST_ENGINES_KEY, nil)
|
216
|
+
@package_manager_detector = PackageManagerDetector.new(@lockfiles, @package_json)
|
217
|
+
end
|
218
|
+
|
219
|
+
sig { returns(Ecosystem::VersionManager) }
|
220
|
+
def package_manager
|
221
|
+
package_manager_by_name(
|
222
|
+
@package_manager_detector.detect_package_manager
|
223
|
+
)
|
17
224
|
end
|
18
225
|
|
19
226
|
# rubocop:disable Metrics/CyclomaticComplexity
|
@@ -23,24 +230,29 @@ module Dependabot
|
|
23
230
|
# i.e. if { engines : "pnpm" : "6" } and { packageManager: "pnpm@6.0.2" },
|
24
231
|
# we go for the specificity mentioned in packageManager (6.0.2)
|
25
232
|
|
26
|
-
unless @
|
233
|
+
unless @manifest_package_manager&.start_with?("#{name}@") ||
|
234
|
+
(@manifest_package_manager&.==name.to_s) ||
|
235
|
+
@manifest_package_manager.nil?
|
27
236
|
return
|
28
237
|
end
|
29
238
|
|
30
|
-
if @engines && @
|
239
|
+
if @engines && @manifest_package_manager.nil?
|
31
240
|
# if "packageManager" doesn't exists in manifest file,
|
32
241
|
# we check if we can extract "engines" information
|
33
242
|
version = check_engine_version(name)
|
34
243
|
|
35
|
-
elsif @
|
244
|
+
elsif @manifest_package_manager&.==name.to_s
|
36
245
|
# if "packageManager" is found but no version is specified (i.e. pnpm@1.2.3),
|
37
246
|
# we check if we can get "engines" info to override default version
|
38
247
|
version = check_engine_version(name) if @engines
|
39
248
|
|
40
|
-
elsif @
|
249
|
+
elsif @manifest_package_manager&.start_with?("#{name}@")
|
41
250
|
# if "packageManager" info has version specification i.e. yarn@3.3.1
|
42
251
|
# we go with the version in "packageManager"
|
43
|
-
Dependabot.logger.info(
|
252
|
+
Dependabot.logger.info(
|
253
|
+
"Found \"#{MANIFEST_PACKAGE_MANAGER_KEY}\" : \"#{@manifest_package_manager}\". " \
|
254
|
+
"Skipped checking \"#{MANIFEST_ENGINES_KEY}\"."
|
255
|
+
)
|
44
256
|
end
|
45
257
|
|
46
258
|
version ||= requested_version(name)
|
@@ -55,7 +267,7 @@ module Dependabot
|
|
55
267
|
if version
|
56
268
|
raise_if_unsupported!(name, version.to_s)
|
57
269
|
|
58
|
-
install(name, version) if name ==
|
270
|
+
install(name, version) if name == PNPMPackageManager::NAME
|
59
271
|
end
|
60
272
|
end
|
61
273
|
|
@@ -66,11 +278,22 @@ module Dependabot
|
|
66
278
|
|
67
279
|
private
|
68
280
|
|
281
|
+
sig { params(name: String).returns(Ecosystem::VersionManager) }
|
282
|
+
def package_manager_by_name(name)
|
283
|
+
package_manager_class = PACKAGE_MANAGER_CLASSES[name]
|
284
|
+
|
285
|
+
package_manager_class ||= PACKAGE_MANAGER_CLASSES[DEFAULT_PACKAGE_MANAGER]
|
286
|
+
|
287
|
+
version = Helpers.send(:"#{name}_version_numeric", @lockfiles[name.to_sym])
|
288
|
+
|
289
|
+
package_manager_class.new(version.to_s)
|
290
|
+
end
|
291
|
+
|
69
292
|
def raise_if_unsupported!(name, version)
|
70
|
-
return unless name ==
|
293
|
+
return unless name == PNPMPackageManager::NAME
|
71
294
|
return unless Version.new(version) < Version.new("7")
|
72
295
|
|
73
|
-
raise ToolVersionNotSupported.new(
|
296
|
+
raise ToolVersionNotSupported.new(PNPMPackageManager::NAME.upcase, version, "7.*, 8.*")
|
74
297
|
end
|
75
298
|
|
76
299
|
def install(name, version)
|
@@ -83,9 +306,9 @@ module Dependabot
|
|
83
306
|
end
|
84
307
|
|
85
308
|
def requested_version(name)
|
86
|
-
return unless @
|
309
|
+
return unless @manifest_package_manager
|
87
310
|
|
88
|
-
match = @
|
311
|
+
match = @manifest_package_manager.match(/^#{name}@(?<version>\d+.\d+.\d+)/)
|
89
312
|
return unless match
|
90
313
|
|
91
314
|
Dependabot.logger.info("Requested version #{match['version']}")
|
@@ -111,7 +334,7 @@ module Dependabot
|
|
111
334
|
return if engine_versions.empty?
|
112
335
|
|
113
336
|
version = engine_versions[name]
|
114
|
-
Dependabot.logger.info("Returned (
|
337
|
+
Dependabot.logger.info("Returned (#{MANIFEST_ENGINES_KEY}) info \"#{name}\" : \"#{version}\"")
|
115
338
|
version
|
116
339
|
end
|
117
340
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dependabot-npm_and_yarn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.285.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dependabot
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-11-
|
11
|
+
date: 2024-11-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dependabot-common
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.285.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
26
|
+
version: 0.285.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: debug
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -346,7 +346,7 @@ licenses:
|
|
346
346
|
- MIT
|
347
347
|
metadata:
|
348
348
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
349
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
349
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.285.0
|
350
350
|
post_install_message:
|
351
351
|
rdoc_options: []
|
352
352
|
require_paths:
|