dependabot-npm_and_yarn 0.238.0 → 0.240.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/helpers/build +1 -1
- data/helpers/test/npm6/conflicting-dependency-parser.test.js +1 -1
- data/lib/dependabot/npm_and_yarn/file_fetcher/path_dependency_builder.rb +3 -3
- data/lib/dependabot/npm_and_yarn/file_fetcher.rb +20 -34
- data/lib/dependabot/npm_and_yarn/file_parser/json_lock.rb +1 -1
- data/lib/dependabot/npm_and_yarn/file_updater/npm_lockfile_updater.rb +2 -4
- data/lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb +9 -3
- data/lib/dependabot/npm_and_yarn/file_updater/package_json_preparer.rb +1 -1
- data/lib/dependabot/npm_and_yarn/file_updater/pnpm_lockfile_updater.rb +5 -5
- data/lib/dependabot/npm_and_yarn/file_updater/yarn_lockfile_updater.rb +6 -6
- data/lib/dependabot/npm_and_yarn/helpers.rb +43 -19
- data/lib/dependabot/npm_and_yarn/native_helpers.rb +1 -3
- data/lib/dependabot/npm_and_yarn/package_manager.rb +55 -5
- data/lib/dependabot/npm_and_yarn/requirement.rb +8 -2
- data/lib/dependabot/npm_and_yarn/update_checker/dependency_files_builder.rb +2 -2
- data/lib/dependabot/npm_and_yarn/update_checker/subdependency_version_resolver.rb +24 -19
- data/lib/dependabot/npm_and_yarn/update_checker/version_resolver.rb +7 -8
- data/lib/dependabot/npm_and_yarn/version.rb +48 -6
- metadata +21 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 412a69f034c9d3dc831b0c2d1abb43c555ee9295aca15c9143996954a9866e8f
|
4
|
+
data.tar.gz: a9e16bbab7d0f9a16a5f862077ff8d0b24ee403bff695d441c2c10750d1028b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c1557876e3fd5fa7ca9a224c9672304f7ee858d6a21ba62328270b9e9bcdadc98d3ce83d72f7a61fe53f71ef9a67b84ac7bfd08a9b9c3c1c7343163c03586574
|
7
|
+
data.tar.gz: d3f6f5edb69513acf55cc6356d61da0d47bbf50b85671fd57c1d6286b405966df1726f2f79968c83c15c6d74a8eca9236947004942a04bb96e9c2e82e0c8499f
|
data/helpers/build
CHANGED
@@ -11,7 +11,7 @@ describe("findConflictingDependencies", () => {
|
|
11
11
|
beforeEach(() => {
|
12
12
|
tempDir = fs.mkdtempSync(os.tmpdir() + path.sep);
|
13
13
|
});
|
14
|
-
afterEach(() => fs.
|
14
|
+
afterEach(() => fs.rm(tempDir, { recursive: true }, () => {}));
|
15
15
|
|
16
16
|
it("finds conflicting dependencies", async () => {
|
17
17
|
helpers.copyDependencies("conflicting-dependency-parser/simple", tempDir);
|
@@ -64,11 +64,11 @@ module Dependabot
|
|
64
64
|
name: dependency_name,
|
65
65
|
version: details_from_yarn_lock["version"] || "0.0.1",
|
66
66
|
dependencies:
|
67
|
-
|
67
|
+
replace_yarn_lockfile_paths(
|
68
68
|
details_from_yarn_lock["dependencies"]
|
69
69
|
),
|
70
70
|
optionalDependencies:
|
71
|
-
|
71
|
+
replace_yarn_lockfile_paths(
|
72
72
|
details_from_yarn_lock["optionalDependencies"]
|
73
73
|
)
|
74
74
|
}.compact.to_json
|
@@ -86,7 +86,7 @@ module Dependabot
|
|
86
86
|
# relative. Worse, they may point to the user's local cache.
|
87
87
|
# We work around this by constructing a relative path to the
|
88
88
|
# (second-level) path dependencies.
|
89
|
-
def
|
89
|
+
def replace_yarn_lockfile_paths(dependencies_hash)
|
90
90
|
return unless dependencies_hash
|
91
91
|
|
92
92
|
dependencies_hash.each_with_object({}) do |(name, value), obj|
|
@@ -60,10 +60,9 @@ module Dependabot
|
|
60
60
|
def ecosystem_versions
|
61
61
|
package_managers = {}
|
62
62
|
|
63
|
-
package_managers["npm"] = npm_version if
|
63
|
+
package_managers["npm"] = npm_version if npm_version
|
64
64
|
package_managers["yarn"] = yarn_version if yarn_version
|
65
65
|
package_managers["pnpm"] = pnpm_version if pnpm_version
|
66
|
-
package_managers["shrinkwrap"] = 1 if shrinkwrap
|
67
66
|
package_managers["unknown"] = 1 if package_managers.empty?
|
68
67
|
|
69
68
|
{
|
@@ -75,9 +74,10 @@ module Dependabot
|
|
75
74
|
def fetch_files
|
76
75
|
fetched_files = []
|
77
76
|
fetched_files << package_json
|
78
|
-
fetched_files
|
79
|
-
fetched_files +=
|
80
|
-
fetched_files +=
|
77
|
+
fetched_files << npmrc if npmrc
|
78
|
+
fetched_files += npm_files if npm_version
|
79
|
+
fetched_files += yarn_files if yarn_version
|
80
|
+
fetched_files += pnpm_files if pnpm_version
|
81
81
|
fetched_files += lerna_files
|
82
82
|
fetched_files += workspace_package_jsons
|
83
83
|
fetched_files += path_dependencies(fetched_files)
|
@@ -93,9 +93,8 @@ module Dependabot
|
|
93
93
|
|
94
94
|
def npm_files
|
95
95
|
fetched_npm_files = []
|
96
|
-
fetched_npm_files << package_lock if package_lock
|
96
|
+
fetched_npm_files << package_lock if package_lock && !skip_package_lock?
|
97
97
|
fetched_npm_files << shrinkwrap if shrinkwrap
|
98
|
-
fetched_npm_files << npmrc if npmrc
|
99
98
|
fetched_npm_files << inferred_npmrc if inferred_npmrc
|
100
99
|
fetched_npm_files
|
101
100
|
end
|
@@ -110,7 +109,7 @@ module Dependabot
|
|
110
109
|
|
111
110
|
def pnpm_files
|
112
111
|
fetched_pnpm_files = []
|
113
|
-
fetched_pnpm_files << pnpm_lock if pnpm_lock
|
112
|
+
fetched_pnpm_files << pnpm_lock if pnpm_lock && !skip_pnpm_lock?
|
114
113
|
fetched_pnpm_files << pnpm_workspace_yaml if pnpm_workspace_yaml
|
115
114
|
fetched_pnpm_files += pnpm_workspace_package_jsons
|
116
115
|
fetched_pnpm_files
|
@@ -131,7 +130,7 @@ module Dependabot
|
|
131
130
|
return @inferred_npmrc = nil unless npmrc.nil? && package_lock
|
132
131
|
|
133
132
|
known_registries = []
|
134
|
-
|
133
|
+
FileParser::JsonLock.new(package_lock).parsed.fetch("dependencies", {}).each do |dependency_name, details|
|
135
134
|
resolved = details.fetch("resolved", DEFAULT_NPM_REGISTRY)
|
136
135
|
|
137
136
|
begin
|
@@ -171,41 +170,28 @@ module Dependabot
|
|
171
170
|
end
|
172
171
|
|
173
172
|
def npm_version
|
174
|
-
|
173
|
+
return @npm_version if defined?(@npm_version)
|
174
|
+
|
175
|
+
@npm_version = package_manager.setup("npm")
|
175
176
|
end
|
176
177
|
|
177
178
|
def yarn_version
|
178
179
|
return @yarn_version if defined?(@yarn_version)
|
179
180
|
|
180
|
-
@yarn_version = package_manager.
|
181
|
-
end
|
182
|
-
|
183
|
-
def guess_yarn_version
|
184
|
-
return unless yarn_lock
|
185
|
-
|
186
|
-
Helpers.yarn_version_numeric(yarn_lock)
|
181
|
+
@yarn_version = package_manager.setup("yarn")
|
187
182
|
end
|
188
183
|
|
189
184
|
def pnpm_version
|
190
185
|
return @pnpm_version if defined?(@pnpm_version)
|
191
186
|
|
192
|
-
|
193
|
-
|
194
|
-
if version && Version.new(version.to_s) < Version.new("7")
|
195
|
-
raise ToolVersionNotSupported.new("PNPM", version.to_s, "7.*, 8.*")
|
196
|
-
end
|
197
|
-
|
198
|
-
@pnpm_version = version
|
199
|
-
end
|
200
|
-
|
201
|
-
def guess_pnpm_version
|
202
|
-
return unless pnpm_lock
|
203
|
-
|
204
|
-
Helpers.pnpm_version_numeric(pnpm_lock)
|
187
|
+
@pnpm_version = package_manager.setup("pnpm")
|
205
188
|
end
|
206
189
|
|
207
190
|
def package_manager
|
208
|
-
@package_manager ||= PackageManager.new(
|
191
|
+
@package_manager ||= PackageManager.new(
|
192
|
+
parsed_package_json,
|
193
|
+
lockfiles: { npm: package_lock || shrinkwrap, yarn: yarn_lock, pnpm: pnpm_lock }
|
194
|
+
)
|
209
195
|
end
|
210
196
|
|
211
197
|
def package_json
|
@@ -215,7 +201,7 @@ module Dependabot
|
|
215
201
|
def package_lock
|
216
202
|
return @package_lock if defined?(@package_lock)
|
217
203
|
|
218
|
-
@package_lock = fetch_file_if_present("package-lock.json")
|
204
|
+
@package_lock = fetch_file_if_present("package-lock.json")
|
219
205
|
end
|
220
206
|
|
221
207
|
def yarn_lock
|
@@ -227,7 +213,7 @@ module Dependabot
|
|
227
213
|
def pnpm_lock
|
228
214
|
return @pnpm_lock if defined?(@pnpm_lock)
|
229
215
|
|
230
|
-
@pnpm_lock = fetch_file_if_present("pnpm-lock.yaml")
|
216
|
+
@pnpm_lock = fetch_file_if_present("pnpm-lock.yaml")
|
231
217
|
end
|
232
218
|
|
233
219
|
def shrinkwrap
|
@@ -379,7 +365,7 @@ module Dependabot
|
|
379
365
|
current_depth = File.join(directory, file.name).split("/").count { |path| !path.empty? }
|
380
366
|
path_to_directory = "../" * current_depth
|
381
367
|
|
382
|
-
dep_types =
|
368
|
+
dep_types = FileParser::DEPENDENCY_TYPES
|
383
369
|
parsed_manifest = JSON.parse(file.content)
|
384
370
|
dependency_objects = parsed_manifest.values_at(*dep_types).compact
|
385
371
|
# Fetch yarn "file:" path "resolutions" so the lockfile can be resolved
|
@@ -24,7 +24,7 @@ module Dependabot
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def details(dependency_name, _requirement, manifest_name)
|
27
|
-
if Helpers.
|
27
|
+
if Helpers.npm8?(@dependency_file)
|
28
28
|
# NOTE: npm 8 sometimes doesn't install workspace dependencies in the
|
29
29
|
# workspace folder so we need to fallback to checking top-level
|
30
30
|
nested_details = parsed.dig("packages", node_modules_path(manifest_name, dependency_name))
|
@@ -248,7 +248,6 @@ module Dependabot
|
|
248
248
|
# run when installing git dependencies
|
249
249
|
def run_npm_install_lockfile_only(*install_args)
|
250
250
|
command = [
|
251
|
-
"npm",
|
252
251
|
"install",
|
253
252
|
*install_args,
|
254
253
|
"--force",
|
@@ -259,7 +258,6 @@ module Dependabot
|
|
259
258
|
].join(" ")
|
260
259
|
|
261
260
|
fingerprint = [
|
262
|
-
"npm",
|
263
261
|
"install",
|
264
262
|
install_args.empty? ? "" : "<install_args>",
|
265
263
|
"--force",
|
@@ -269,7 +267,7 @@ module Dependabot
|
|
269
267
|
"--package-lock-only"
|
270
268
|
].join(" ")
|
271
269
|
|
272
|
-
|
270
|
+
Helpers.run_npm_command(command, fingerprint: fingerprint)
|
273
271
|
end
|
274
272
|
|
275
273
|
def npm_install_args(dependency)
|
@@ -830,7 +828,7 @@ module Dependabot
|
|
830
828
|
def npm8?
|
831
829
|
return @npm8 if defined?(@npm8)
|
832
830
|
|
833
|
-
@npm8 = Dependabot::NpmAndYarn::Helpers.
|
831
|
+
@npm8 = Dependabot::NpmAndYarn::Helpers.npm8?(lockfile)
|
834
832
|
end
|
835
833
|
|
836
834
|
def sanitize_package_name(package_name)
|
@@ -64,7 +64,7 @@ module Dependabot
|
|
64
64
|
attr_reader :dependency_files, :credentials, :dependencies
|
65
65
|
|
66
66
|
def build_npmrc_content_from_lockfile
|
67
|
-
return unless yarn_lock || package_lock
|
67
|
+
return unless yarn_lock || package_lock || shrinkwrap
|
68
68
|
return unless global_registry
|
69
69
|
|
70
70
|
registry = global_registry["registry"]
|
@@ -149,9 +149,10 @@ module Dependabot
|
|
149
149
|
return @dependency_urls
|
150
150
|
end
|
151
151
|
|
152
|
-
|
152
|
+
npm_lockfile = package_lock || shrinkwrap
|
153
|
+
if npm_lockfile
|
153
154
|
@dependency_urls +=
|
154
|
-
|
155
|
+
npm_lockfile.content.scan(/"resolved"\s*:\s*"(.*)"/)
|
155
156
|
.flatten
|
156
157
|
.select { |url| url.is_a?(String) }
|
157
158
|
.reject { |url| url.start_with?("git") }
|
@@ -334,6 +335,11 @@ module Dependabot
|
|
334
335
|
@package_lock ||=
|
335
336
|
dependency_files.find { |f| f.name == "package-lock.json" }
|
336
337
|
end
|
338
|
+
|
339
|
+
def shrinkwrap
|
340
|
+
@shrinkwrap ||=
|
341
|
+
dependency_files.find { |f| f.name == "npm-shrinkwrap.json" }
|
342
|
+
end
|
337
343
|
end
|
338
344
|
end
|
339
345
|
end
|
@@ -56,7 +56,7 @@ module Dependabot
|
|
56
56
|
content
|
57
57
|
.gsub(/\{\{[^\}]*?\}\}/, "something") # {{ nm }} syntax not allowed
|
58
58
|
.gsub(/(?<!\\)\\ /, " ") # escaped whitespace not allowed
|
59
|
-
.gsub(%r{^\s*//.*}, " ")
|
59
|
+
.gsub(%r{^\s*//.*}, " ") # comments are not allowed
|
60
60
|
end
|
61
61
|
|
62
62
|
def swapped_ssh_requirements
|
@@ -62,15 +62,15 @@ module Dependabot
|
|
62
62
|
"#{d.name}@#{d.version}"
|
63
63
|
end.join(" ")
|
64
64
|
|
65
|
-
|
66
|
-
"
|
67
|
-
fingerprint: "
|
65
|
+
Helpers.run_pnpm_command(
|
66
|
+
"install #{dependency_updates} --lockfile-only --ignore-workspace-root-check",
|
67
|
+
fingerprint: "install <dependency_updates> --lockfile-only --ignore-workspace-root-check"
|
68
68
|
)
|
69
69
|
end
|
70
70
|
|
71
71
|
def run_pnpm_install
|
72
|
-
|
73
|
-
"
|
72
|
+
Helpers.run_pnpm_command(
|
73
|
+
"install --lockfile-only"
|
74
74
|
)
|
75
75
|
end
|
76
76
|
|
@@ -152,15 +152,15 @@ module Dependabot
|
|
152
152
|
# the lockfile.
|
153
153
|
|
154
154
|
if top_level_dependency_updates.all? { |dep| requirements_changed?(dep[:name]) }
|
155
|
-
Helpers.run_yarn_command("
|
155
|
+
Helpers.run_yarn_command("install #{yarn_berry_args}".strip)
|
156
156
|
else
|
157
157
|
updates = top_level_dependency_updates.collect do |dep|
|
158
158
|
dep[:name]
|
159
159
|
end
|
160
160
|
|
161
161
|
Helpers.run_yarn_command(
|
162
|
-
"
|
163
|
-
fingerprint: "
|
162
|
+
"up -R #{updates.join(' ')} #{yarn_berry_args}".strip,
|
163
|
+
fingerprint: "up -R <dependency_names> #{yarn_berry_args}".strip
|
164
164
|
)
|
165
165
|
end
|
166
166
|
{ yarn_lock.name => File.read(yarn_lock.name) }
|
@@ -176,9 +176,9 @@ module Dependabot
|
|
176
176
|
update = "#{dep.name}@#{dep.version}"
|
177
177
|
|
178
178
|
commands = [
|
179
|
-
["
|
180
|
-
["
|
181
|
-
["
|
179
|
+
["add #{update} #{yarn_berry_args}".strip, "add <update> #{yarn_berry_args}".strip],
|
180
|
+
["dedupe #{dep.name} #{yarn_berry_args}".strip, "dedupe <dep_name> #{yarn_berry_args}".strip],
|
181
|
+
["remove #{dep.name} #{yarn_berry_args}".strip, "remove <dep_name> #{yarn_berry_args}".strip]
|
182
182
|
]
|
183
183
|
|
184
184
|
Helpers.run_yarn_commands(*commands)
|
@@ -7,13 +7,9 @@ module Dependabot
|
|
7
7
|
YARN_PATH_NOT_FOUND =
|
8
8
|
/^.*(?<error>The "yarn-path" option has been set \(in [^)]+\), but the specified location doesn't exist)/
|
9
9
|
|
10
|
-
def self.
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
def self.npm_version_numeric(lockfile_content)
|
15
|
-
return 8 unless lockfile_content
|
16
|
-
return 8 if JSON.parse(lockfile_content)["lockfileVersion"] >= 2
|
10
|
+
def self.npm_version_numeric(lockfile)
|
11
|
+
lockfile_content = lockfile.content
|
12
|
+
return 8 if JSON.parse(lockfile_content)["lockfileVersion"].to_i >= 2
|
17
13
|
|
18
14
|
6
|
19
15
|
rescue JSON::ParserError
|
@@ -31,8 +27,10 @@ module Dependabot
|
|
31
27
|
# Mapping from lockfile versions to PNPM versions is at
|
32
28
|
# https://github.com/pnpm/spec/tree/274ff02de23376ad59773a9f25ecfedd03a41f64/lockfile, but simplify it for now.
|
33
29
|
def self.pnpm_version_numeric(pnpm_lock)
|
34
|
-
if pnpm_lockfile_version(pnpm_lock).to_f >=
|
30
|
+
if pnpm_lockfile_version(pnpm_lock).to_f >= 6.0
|
35
31
|
8
|
32
|
+
elsif pnpm_lockfile_version(pnpm_lock).to_f >= 5.4
|
33
|
+
7
|
36
34
|
else
|
37
35
|
6
|
38
36
|
end
|
@@ -46,6 +44,12 @@ module Dependabot
|
|
46
44
|
end
|
47
45
|
end
|
48
46
|
|
47
|
+
def self.npm8?(package_lock)
|
48
|
+
return true unless package_lock
|
49
|
+
|
50
|
+
npm_version_numeric(package_lock) == 8
|
51
|
+
end
|
52
|
+
|
49
53
|
def self.yarn_berry?(yarn_lock)
|
50
54
|
yaml = YAML.safe_load(yarn_lock.content)
|
51
55
|
yaml.key?("__metadata")
|
@@ -55,7 +59,7 @@ module Dependabot
|
|
55
59
|
|
56
60
|
def self.yarn_major_version
|
57
61
|
retries = 0
|
58
|
-
output =
|
62
|
+
output = run_single_yarn_command("--version")
|
59
63
|
Version.new(output).major
|
60
64
|
rescue Dependabot::SharedHelpers::HelperSubprocessFailed => e
|
61
65
|
# Should never happen, can probably be removed once this settles
|
@@ -118,23 +122,23 @@ module Dependabot
|
|
118
122
|
|
119
123
|
def self.setup_yarn_berry
|
120
124
|
# Always disable immutable installs so yarn's CI detection doesn't prevent updates.
|
121
|
-
|
125
|
+
run_single_yarn_command("config set enableImmutableInstalls false")
|
122
126
|
# Do not generate a cache if offline cache disabled. Otherwise side effects may confuse further checks
|
123
|
-
|
127
|
+
run_single_yarn_command("config set enableGlobalCache true") unless yarn_berry_skip_build?
|
124
128
|
# We never want to execute postinstall scripts, either set this config or mode=skip-build must be set
|
125
|
-
|
129
|
+
run_single_yarn_command("config set enableScripts false") if yarn_berry_disable_scripts?
|
126
130
|
if (http_proxy = ENV.fetch("HTTP_PROXY", false))
|
127
|
-
|
131
|
+
run_single_yarn_command("config set httpProxy #{http_proxy}", fingerprint: "config set httpProxy <proxy>")
|
128
132
|
end
|
129
133
|
if (https_proxy = ENV.fetch("HTTPS_PROXY", false))
|
130
|
-
|
134
|
+
run_single_yarn_command("config set httpsProxy #{https_proxy}", fingerprint: "config set httpsProxy <proxy>")
|
131
135
|
end
|
132
136
|
return unless (ca_file_path = ENV.fetch("NODE_EXTRA_CA_CERTS", false))
|
133
137
|
|
134
138
|
if yarn_4_or_higher?
|
135
|
-
|
139
|
+
run_single_yarn_command("config set httpsCaFilePath #{ca_file_path}")
|
136
140
|
else
|
137
|
-
|
141
|
+
run_single_yarn_command("config set caFilePath #{ca_file_path}")
|
138
142
|
end
|
139
143
|
end
|
140
144
|
|
@@ -144,14 +148,34 @@ module Dependabot
|
|
144
148
|
# contain malicious code.
|
145
149
|
def self.run_yarn_commands(*commands)
|
146
150
|
setup_yarn_berry
|
147
|
-
commands.each { |cmd, fingerprint|
|
151
|
+
commands.each { |cmd, fingerprint| run_single_yarn_command(cmd, fingerprint: fingerprint) }
|
148
152
|
end
|
149
153
|
|
150
|
-
# Run
|
154
|
+
# Run single npm command returning stdout/stderr.
|
155
|
+
#
|
156
|
+
# NOTE: Needs to be explicitly run through corepack to respect the
|
157
|
+
# `packageManager` setting in `package.json`, because corepack does not
|
158
|
+
# add shims for NPM.
|
159
|
+
def self.run_npm_command(command, fingerprint: command)
|
160
|
+
SharedHelpers.run_shell_command("corepack npm #{command}", fingerprint: "corepack npm #{fingerprint}")
|
161
|
+
end
|
162
|
+
|
163
|
+
# Setup yarn and run a single yarn command returning stdout/stderr
|
151
164
|
def self.run_yarn_command(command, fingerprint: nil)
|
152
165
|
setup_yarn_berry
|
153
|
-
|
166
|
+
run_single_yarn_command(command, fingerprint: fingerprint)
|
167
|
+
end
|
168
|
+
|
169
|
+
# Run single pnpm command returning stdout/stderr
|
170
|
+
def self.run_pnpm_command(command, fingerprint: nil)
|
171
|
+
SharedHelpers.run_shell_command("pnpm #{command}", fingerprint: "pnpm #{fingerprint || command}")
|
172
|
+
end
|
173
|
+
|
174
|
+
# Run single yarn command returning stdout/stderr
|
175
|
+
def self.run_single_yarn_command(command, fingerprint: nil)
|
176
|
+
SharedHelpers.run_shell_command("yarn #{command}", fingerprint: "yarn #{fingerprint || command}")
|
154
177
|
end
|
178
|
+
private_class_method :run_single_yarn_command
|
155
179
|
|
156
180
|
def self.pnpm_lockfile_version(pnpm_lock)
|
157
181
|
pnpm_lock.content.match(/^lockfileVersion: ['"]?(?<version>[\d.]+)/)[:version]
|
@@ -23,7 +23,6 @@ module Dependabot
|
|
23
23
|
# - `--ignore-scripts` disables prepare and prepack scripts which are run
|
24
24
|
# when installing git dependencies
|
25
25
|
command = [
|
26
|
-
"npm",
|
27
26
|
"update",
|
28
27
|
*dependency_names,
|
29
28
|
"--force",
|
@@ -34,7 +33,6 @@ module Dependabot
|
|
34
33
|
].join(" ")
|
35
34
|
|
36
35
|
fingerprint = [
|
37
|
-
"npm",
|
38
36
|
"update",
|
39
37
|
"<dependency_names>",
|
40
38
|
"--force",
|
@@ -44,7 +42,7 @@ module Dependabot
|
|
44
42
|
"--package-lock-only"
|
45
43
|
].join(" ")
|
46
44
|
|
47
|
-
|
45
|
+
Helpers.run_npm_command(command, fingerprint: fingerprint)
|
48
46
|
end
|
49
47
|
end
|
50
48
|
end
|
@@ -1,19 +1,69 @@
|
|
1
1
|
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "dependabot/shared_helpers"
|
5
|
+
|
4
6
|
module Dependabot
|
5
7
|
module NpmAndYarn
|
6
8
|
class PackageManager
|
7
|
-
def initialize(package_json)
|
9
|
+
def initialize(package_json, lockfiles:)
|
8
10
|
@package_json = package_json
|
11
|
+
@lockfiles = lockfiles
|
12
|
+
@package_manager = package_json.fetch("packageManager", nil)
|
13
|
+
end
|
14
|
+
|
15
|
+
def setup(name)
|
16
|
+
return unless @package_manager.nil? || @package_manager.start_with?("#{name}@")
|
17
|
+
|
18
|
+
version = requested_version(name)
|
19
|
+
|
20
|
+
if version
|
21
|
+
raise_if_unsupported!(name, version)
|
22
|
+
|
23
|
+
install(name, version)
|
24
|
+
else
|
25
|
+
version = guessed_version(name)
|
26
|
+
|
27
|
+
if version
|
28
|
+
raise_if_unsupported!(name, version.to_s)
|
29
|
+
|
30
|
+
install(name, version) if name == "pnpm"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
version
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def raise_if_unsupported!(name, version)
|
40
|
+
return unless name == "pnpm"
|
41
|
+
return unless Version.new(version) < Version.new("7")
|
42
|
+
|
43
|
+
raise ToolVersionNotSupported.new("PNPM", version, "7.*, 8.*")
|
44
|
+
end
|
45
|
+
|
46
|
+
def install(name, version)
|
47
|
+
SharedHelpers.run_shell_command(
|
48
|
+
"corepack install #{name}@#{version} --global --cache-only",
|
49
|
+
fingerprint: "corepack install <name>@<version> --global --cache-only"
|
50
|
+
)
|
9
51
|
end
|
10
52
|
|
11
53
|
def requested_version(name)
|
12
|
-
|
13
|
-
|
54
|
+
return unless @package_manager
|
55
|
+
|
56
|
+
match = @package_manager.match(/#{name}@(?<version>\d+.\d+.\d+)/)
|
57
|
+
return unless match
|
58
|
+
|
59
|
+
match["version"]
|
60
|
+
end
|
61
|
+
|
62
|
+
def guessed_version(name)
|
63
|
+
lockfile = @lockfiles[name.to_sym]
|
64
|
+
return unless lockfile
|
14
65
|
|
15
|
-
|
16
|
-
version_match&.named_captures&.fetch("version", nil)
|
66
|
+
Helpers.send(:"#{name}_version_numeric", lockfile)
|
17
67
|
end
|
18
68
|
end
|
19
69
|
end
|
@@ -1,12 +1,17 @@
|
|
1
1
|
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
+
require "sorbet-runtime"
|
5
|
+
|
6
|
+
require "dependabot/requirement"
|
4
7
|
require "dependabot/utils"
|
5
8
|
require "dependabot/npm_and_yarn/version"
|
6
9
|
|
7
10
|
module Dependabot
|
8
11
|
module NpmAndYarn
|
9
|
-
class Requirement <
|
12
|
+
class Requirement < Dependabot::Requirement
|
13
|
+
extend T::Sig
|
14
|
+
|
10
15
|
AND_SEPARATOR = /(?<=[a-zA-Z0-9*])\s+(?:&+\s+)?(?!\s*[|-])/
|
11
16
|
OR_SEPARATOR = /(?<=[a-zA-Z0-9*])\s*\|+/
|
12
17
|
LATEST_REQUIREMENT = "latest"
|
@@ -29,11 +34,12 @@ module Dependabot
|
|
29
34
|
|
30
35
|
return DefaultRequirement if matches[1] == ">=" && matches[2] == "0"
|
31
36
|
|
32
|
-
[matches[1] || "=", NpmAndYarn::Version.new(matches[2])]
|
37
|
+
[matches[1] || "=", NpmAndYarn::Version.new(T.must(matches[2]))]
|
33
38
|
end
|
34
39
|
|
35
40
|
# Returns an array of requirements. At least one requirement from the
|
36
41
|
# returned array must be satisfied for a version to be valid.
|
42
|
+
sig { override.params(requirement_string: T.nilable(String)).returns(T::Array[Requirement]) }
|
37
43
|
def self.requirements_array(requirement_string)
|
38
44
|
return [new(nil)] if requirement_string.nil?
|
39
45
|
|
@@ -15,7 +15,7 @@ module Dependabot
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def write_temporary_dependency_files
|
18
|
-
|
18
|
+
write_lockfiles
|
19
19
|
|
20
20
|
if Helpers.yarn_berry?(yarn_locks.first)
|
21
21
|
File.write(".yarnrc.yml", yarnrc_yml_content) if yarnrc_yml_file
|
@@ -81,7 +81,7 @@ module Dependabot
|
|
81
81
|
|
82
82
|
attr_reader :dependency, :dependency_files, :credentials
|
83
83
|
|
84
|
-
def
|
84
|
+
def write_lockfiles
|
85
85
|
yarn_locks.each do |f|
|
86
86
|
FileUtils.mkdir_p(Pathname.new(f.name).dirname)
|
87
87
|
File.write(f.name, prepared_yarn_lockfile_content(f.content))
|
@@ -66,8 +66,10 @@ module Dependabot
|
|
66
66
|
run_yarn_updater(path, lockfile_name)
|
67
67
|
elsif lockfile.name.end_with?("pnpm-lock.yaml")
|
68
68
|
run_pnpm_updater(path, lockfile_name)
|
69
|
+
elsif Helpers.npm8?(lockfile)
|
70
|
+
run_npm8_updater(path, lockfile_name)
|
69
71
|
else
|
70
|
-
run_npm_updater(path, lockfile_name
|
72
|
+
run_npm_updater(path, lockfile_name)
|
71
73
|
end
|
72
74
|
|
73
75
|
updated_files.fetch(lockfile_name)
|
@@ -116,8 +118,8 @@ module Dependabot
|
|
116
118
|
SharedHelpers.with_git_configured(credentials: credentials) do
|
117
119
|
Dir.chdir(path) do
|
118
120
|
Helpers.run_yarn_command(
|
119
|
-
"
|
120
|
-
fingerprint: "
|
121
|
+
"up -R #{dependency.name} #{Helpers.yarn_berry_args}".strip,
|
122
|
+
fingerprint: "up -R <dependency_name> #{Helpers.yarn_berry_args}".strip
|
121
123
|
)
|
122
124
|
{ lockfile_name => File.read(lockfile_name) }
|
123
125
|
end
|
@@ -127,30 +129,33 @@ module Dependabot
|
|
127
129
|
def run_pnpm_updater(path, lockfile_name)
|
128
130
|
SharedHelpers.with_git_configured(credentials: credentials) do
|
129
131
|
Dir.chdir(path) do
|
130
|
-
|
131
|
-
"
|
132
|
-
fingerprint: "
|
132
|
+
Helpers.run_pnpm_command(
|
133
|
+
"update #{dependency.name} --lockfile-only",
|
134
|
+
fingerprint: "update <dependency_name> --lockfile-only"
|
133
135
|
)
|
134
136
|
{ lockfile_name => File.read(lockfile_name) }
|
135
137
|
end
|
136
138
|
end
|
137
139
|
end
|
138
140
|
|
139
|
-
def
|
141
|
+
def run_npm8_updater(path, lockfile_name)
|
140
142
|
SharedHelpers.with_git_configured(credentials: credentials) do
|
141
143
|
Dir.chdir(path) do
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
144
|
+
NativeHelpers.run_npm8_subdependency_update_command([dependency.name])
|
145
|
+
|
146
|
+
{ lockfile_name => File.read(lockfile_name) }
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def run_npm_updater(path, lockfile_name)
|
152
|
+
SharedHelpers.with_git_configured(credentials: credentials) do
|
153
|
+
Dir.chdir(path) do
|
154
|
+
SharedHelpers.run_helper_subprocess(
|
155
|
+
command: NativeHelpers.helper_path,
|
156
|
+
function: "npm6:updateSubdependency",
|
157
|
+
args: [Dir.pwd, lockfile_name, [dependency.to_h]]
|
158
|
+
)
|
154
159
|
end
|
155
160
|
end
|
156
161
|
end
|
@@ -539,9 +539,9 @@ module Dependabot
|
|
539
539
|
def run_pnpm_checker(path:, version:)
|
540
540
|
SharedHelpers.with_git_configured(credentials: credentials) do
|
541
541
|
Dir.chdir(path) do
|
542
|
-
output =
|
543
|
-
"
|
544
|
-
fingerprint: "
|
542
|
+
output = Helpers.run_pnpm_command(
|
543
|
+
"update #{dependency.name}@#{version} --lockfile-only",
|
544
|
+
fingerprint: "update <dependency_name>@<version> --lockfile-only"
|
545
545
|
)
|
546
546
|
if PNPM_PEER_DEP_ERROR_REGEX.match?(output)
|
547
547
|
raise SharedHelpers::HelperSubprocessFailed.new(
|
@@ -562,7 +562,7 @@ module Dependabot
|
|
562
562
|
SharedHelpers.with_git_configured(credentials: credentials) do
|
563
563
|
Dir.chdir(path) do
|
564
564
|
output = Helpers.run_yarn_command(
|
565
|
-
"
|
565
|
+
"add #{dependency.name}@#{version} #{Helpers.yarn_berry_args}".strip
|
566
566
|
)
|
567
567
|
if output.include?("YN0060")
|
568
568
|
raise SharedHelpers::HelperSubprocessFailed.new(
|
@@ -598,9 +598,8 @@ module Dependabot
|
|
598
598
|
# Find the lockfile that's in the current directory
|
599
599
|
f.name == [path, "package-lock.json"].join("/").sub(%r{\A.?\/}, "")
|
600
600
|
end
|
601
|
-
npm_version = Dependabot::NpmAndYarn::Helpers.npm_version(package_lock&.content)
|
602
601
|
|
603
|
-
return run_npm8_checker(version: version) if
|
602
|
+
return run_npm8_checker(version: version) if Dependabot::NpmAndYarn::Helpers.npm8?(package_lock)
|
604
603
|
|
605
604
|
SharedHelpers.run_helper_subprocess(
|
606
605
|
command: NativeHelpers.helper_path,
|
@@ -619,8 +618,8 @@ module Dependabot
|
|
619
618
|
|
620
619
|
def run_npm8_checker(version:)
|
621
620
|
cmd =
|
622
|
-
"
|
623
|
-
output =
|
621
|
+
"install #{version_install_arg(version: version)} --package-lock-only --dry-run=true --ignore-scripts"
|
622
|
+
output = Helpers.run_npm_command(cmd)
|
624
623
|
if output.match?(NPM8_PEER_DEP_ERROR_REGEX)
|
625
624
|
error_context = { command: cmd, process_exit_value: 1 }
|
626
625
|
raise SharedHelpers::HelperSubprocessFailed.new(message: output, error_context: error_context)
|
@@ -21,7 +21,20 @@ module Dependabot
|
|
21
21
|
VERSION_PATTERN = T.let(Gem::Version::VERSION_PATTERN + '(\+[0-9a-zA-Z\-.]+)?', String)
|
22
22
|
ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})?\s*\z/
|
23
23
|
|
24
|
-
sig
|
24
|
+
sig do
|
25
|
+
override
|
26
|
+
.overridable
|
27
|
+
.params(
|
28
|
+
version: T.any(
|
29
|
+
String,
|
30
|
+
Integer,
|
31
|
+
Float,
|
32
|
+
Gem::Version,
|
33
|
+
NilClass
|
34
|
+
)
|
35
|
+
)
|
36
|
+
.returns(T::Boolean)
|
37
|
+
end
|
25
38
|
def self.correct?(version)
|
26
39
|
version = version.gsub(/^v/, "") if version.is_a?(String)
|
27
40
|
|
@@ -42,29 +55,58 @@ module Dependabot
|
|
42
55
|
version
|
43
56
|
end
|
44
57
|
|
45
|
-
sig
|
58
|
+
sig do
|
59
|
+
override
|
60
|
+
.params(
|
61
|
+
version: T.any(
|
62
|
+
String,
|
63
|
+
Integer,
|
64
|
+
Float,
|
65
|
+
Gem::Version,
|
66
|
+
NilClass
|
67
|
+
)
|
68
|
+
)
|
69
|
+
.void
|
70
|
+
end
|
46
71
|
def initialize(version)
|
47
72
|
@version_string = T.let(version.to_s, String)
|
48
73
|
version = version.gsub(/^v/, "") if version.is_a?(String)
|
49
74
|
|
50
75
|
version, @build_info = version.to_s.split("+") if version.to_s.include?("+")
|
51
76
|
|
52
|
-
super
|
77
|
+
super(T.must(version))
|
78
|
+
end
|
79
|
+
|
80
|
+
sig do
|
81
|
+
override
|
82
|
+
.params(
|
83
|
+
version: T.any(
|
84
|
+
String,
|
85
|
+
Integer,
|
86
|
+
Float,
|
87
|
+
Gem::Version,
|
88
|
+
NilClass
|
89
|
+
)
|
90
|
+
)
|
91
|
+
.returns(Dependabot::NpmAndYarn::Version)
|
92
|
+
end
|
93
|
+
def self.new(version)
|
94
|
+
T.cast(super, Dependabot::NpmAndYarn::Version)
|
53
95
|
end
|
54
96
|
|
55
97
|
sig { returns(Integer) }
|
56
98
|
def major
|
57
|
-
@major ||= T.let(segments[0]
|
99
|
+
@major ||= T.let(segments[0].to_i, T.nilable(Integer))
|
58
100
|
end
|
59
101
|
|
60
102
|
sig { returns(Integer) }
|
61
103
|
def minor
|
62
|
-
@minor ||= T.let(segments[1]
|
104
|
+
@minor ||= T.let(segments[1].to_i, T.nilable(Integer))
|
63
105
|
end
|
64
106
|
|
65
107
|
sig { returns(Integer) }
|
66
108
|
def patch
|
67
|
-
@patch ||= T.let(segments[2]
|
109
|
+
@patch ||= T.let(segments[2].to_i, T.nilable(Integer))
|
68
110
|
end
|
69
111
|
|
70
112
|
sig { params(other: Dependabot::NpmAndYarn::Version).returns(T::Boolean) }
|
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.240.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dependabot
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-12 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.240.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.240.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: debug
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,14 +114,14 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 1.
|
117
|
+
version: 1.58.0
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 1.
|
124
|
+
version: 1.58.0
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: rubocop-performance
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -206,6 +206,20 @@ dependencies:
|
|
206
206
|
- - "~>"
|
207
207
|
- !ruby/object:Gem::Version
|
208
208
|
version: '3.18'
|
209
|
+
- !ruby/object:Gem::Dependency
|
210
|
+
name: webrick
|
211
|
+
requirement: !ruby/object:Gem::Requirement
|
212
|
+
requirements:
|
213
|
+
- - ">="
|
214
|
+
- !ruby/object:Gem::Version
|
215
|
+
version: '1.7'
|
216
|
+
type: :development
|
217
|
+
prerelease: false
|
218
|
+
version_requirements: !ruby/object:Gem::Requirement
|
219
|
+
requirements:
|
220
|
+
- - ">="
|
221
|
+
- !ruby/object:Gem::Version
|
222
|
+
version: '1.7'
|
209
223
|
description: Dependabot-NPM_And_Yarn provides support for bumping Javascript (npm
|
210
224
|
and yarn) libraries via Dependabot. If you want support for multiple package managers,
|
211
225
|
you probably want the meta-gem dependabot-omnibus.
|
@@ -310,7 +324,7 @@ licenses:
|
|
310
324
|
- Nonstandard
|
311
325
|
metadata:
|
312
326
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
313
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
327
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.240.0
|
314
328
|
post_install_message:
|
315
329
|
rdoc_options: []
|
316
330
|
require_paths:
|