dependabot-npm_and_yarn 0.216.2 → 0.218.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/helpers/lib/pnpm/index.js +5 -0
- data/helpers/lib/pnpm/lockfile-parser.js +77 -0
- data/helpers/package-lock.json +827 -207
- data/helpers/package.json +4 -2
- data/lib/dependabot/npm_and_yarn/dependency_files_filterer.rb +33 -2
- data/lib/dependabot/npm_and_yarn/file_fetcher.rb +129 -55
- data/lib/dependabot/npm_and_yarn/file_parser/lockfile_parser.rb +13 -4
- data/lib/dependabot/npm_and_yarn/file_parser/pnpm_lock.rb +68 -0
- data/lib/dependabot/npm_and_yarn/file_updater/npm_lockfile_updater.rb +6 -0
- data/lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb +6 -4
- data/lib/dependabot/npm_and_yarn/file_updater/package_json_updater.rb +3 -2
- data/lib/dependabot/npm_and_yarn/file_updater/pnpm_lockfile_updater.rb +145 -0
- data/lib/dependabot/npm_and_yarn/file_updater/yarn_lockfile_updater.rb +1 -1
- data/lib/dependabot/npm_and_yarn/file_updater.rb +38 -1
- data/lib/dependabot/npm_and_yarn/helpers.rb +13 -0
- data/lib/dependabot/npm_and_yarn/package_manager.rb +19 -0
- data/lib/dependabot/npm_and_yarn/sub_dependency_files_filterer.rb +2 -1
- data/lib/dependabot/npm_and_yarn/update_checker/dependency_files_builder.rb +19 -2
- data/lib/dependabot/npm_and_yarn/update_checker/requirements_updater.rb +3 -1
- data/lib/dependabot/npm_and_yarn/update_checker/subdependency_version_resolver.rb +15 -5
- data/lib/dependabot/npm_and_yarn/update_checker/version_resolver.rb +56 -21
- data/lib/dependabot/npm_and_yarn/update_checker.rb +4 -0
- metadata +11 -6
@@ -0,0 +1,145 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dependabot/npm_and_yarn/helpers"
|
4
|
+
require "dependabot/npm_and_yarn/update_checker/registry_finder"
|
5
|
+
require "dependabot/shared_helpers"
|
6
|
+
|
7
|
+
module Dependabot
|
8
|
+
module NpmAndYarn
|
9
|
+
class FileUpdater
|
10
|
+
class PnpmLockfileUpdater
|
11
|
+
require_relative "package_json_updater"
|
12
|
+
|
13
|
+
def initialize(dependencies:, dependency_files:, repo_contents_path:, credentials:)
|
14
|
+
@dependencies = dependencies
|
15
|
+
@dependency_files = dependency_files
|
16
|
+
@repo_contents_path = repo_contents_path
|
17
|
+
@credentials = credentials
|
18
|
+
end
|
19
|
+
|
20
|
+
def updated_pnpm_lock_content(pnpm_lock)
|
21
|
+
@updated_pnpm_lock_content ||= {}
|
22
|
+
return @updated_pnpm_lock_content[pnpm_lock.name] if @updated_pnpm_lock_content[pnpm_lock.name]
|
23
|
+
|
24
|
+
new_content = run_pnpm_update(pnpm_lock: pnpm_lock)
|
25
|
+
@updated_pnpm_lock_content[pnpm_lock.name] = new_content
|
26
|
+
rescue SharedHelpers::HelperSubprocessFailed => e
|
27
|
+
handle_pnpm_lock_updater_error(e, pnpm_lock)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_reader :dependencies, :dependency_files, :repo_contents_path, :credentials
|
33
|
+
|
34
|
+
IRRESOLVABLE_PACKAGE = "ERR_PNPM_NO_MATCHING_VERSION"
|
35
|
+
INVALID_REQUIREMENT = "ERR_PNPM_SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER"
|
36
|
+
MISSING_PACKAGE = /(?<package_req>.*?) is not in the npm registry, or you have no permission to fetch it/
|
37
|
+
|
38
|
+
def run_pnpm_update(pnpm_lock:)
|
39
|
+
SharedHelpers.in_a_temporary_repo_directory(base_dir, repo_contents_path) do
|
40
|
+
SharedHelpers.with_git_configured(credentials: credentials) do
|
41
|
+
run_pnpm_updater
|
42
|
+
|
43
|
+
write_final_package_json_files
|
44
|
+
|
45
|
+
run_pnpm_install
|
46
|
+
|
47
|
+
File.read(pnpm_lock.name)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def run_pnpm_updater
|
53
|
+
dependency_updates = dependencies.map do |d|
|
54
|
+
"#{d.name}@#{d.version}"
|
55
|
+
end.join(" ")
|
56
|
+
|
57
|
+
SharedHelpers.run_shell_command(
|
58
|
+
"pnpm install #{dependency_updates} --lockfile-only --ignore-workspace-root-check",
|
59
|
+
fingerprint: "pnpm install <dependency_updates> --lockfile-only --ignore-workspace-root-check"
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
def run_pnpm_install
|
64
|
+
SharedHelpers.run_shell_command(
|
65
|
+
"pnpm install --lockfile-only"
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
def lockfile_dependencies(lockfile)
|
70
|
+
@lockfile_dependencies ||= {}
|
71
|
+
@lockfile_dependencies[lockfile.name] ||=
|
72
|
+
NpmAndYarn::FileParser.new(
|
73
|
+
dependency_files: [lockfile, *package_files],
|
74
|
+
source: nil,
|
75
|
+
credentials: credentials
|
76
|
+
).parse
|
77
|
+
end
|
78
|
+
|
79
|
+
def handle_pnpm_lock_updater_error(error, pnpm_lock)
|
80
|
+
error_message = error.message
|
81
|
+
|
82
|
+
if error_message.include?(IRRESOLVABLE_PACKAGE) || error_message.include?(INVALID_REQUIREMENT)
|
83
|
+
raise_resolvability_error(error_message, pnpm_lock)
|
84
|
+
end
|
85
|
+
|
86
|
+
raise unless error_message.match?(MISSING_PACKAGE)
|
87
|
+
|
88
|
+
package_name = error_message.match(MISSING_PACKAGE).
|
89
|
+
named_captures["package_req"].
|
90
|
+
split(/(?<=\w)\@/).first
|
91
|
+
raise_missing_package_error(package_name, error_message, pnpm_lock)
|
92
|
+
end
|
93
|
+
|
94
|
+
def raise_resolvability_error(error_message, pnpm_lock)
|
95
|
+
dependency_names = dependencies.map(&:name).join(", ")
|
96
|
+
msg = "Error whilst updating #{dependency_names} in " \
|
97
|
+
"#{pnpm_lock.path}:\n#{error_message}"
|
98
|
+
raise Dependabot::DependencyFileNotResolvable, msg
|
99
|
+
end
|
100
|
+
|
101
|
+
def raise_missing_package_error(package_name, _error_message, pnpm_lock)
|
102
|
+
missing_dep = lockfile_dependencies(pnpm_lock).
|
103
|
+
find { |dep| dep.name == package_name }
|
104
|
+
|
105
|
+
reg = NpmAndYarn::UpdateChecker::RegistryFinder.new(
|
106
|
+
dependency: missing_dep,
|
107
|
+
credentials: credentials,
|
108
|
+
npmrc_file: npmrc_file
|
109
|
+
).registry
|
110
|
+
|
111
|
+
raise PrivateSourceAuthenticationFailure, reg
|
112
|
+
end
|
113
|
+
|
114
|
+
def write_final_package_json_files
|
115
|
+
package_files.each do |file|
|
116
|
+
path = file.name
|
117
|
+
FileUtils.mkdir_p(Pathname.new(path).dirname)
|
118
|
+
File.write(path, updated_package_json_content(file))
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def updated_package_json_content(file)
|
123
|
+
@updated_package_json_content ||= {}
|
124
|
+
@updated_package_json_content[file.name] ||=
|
125
|
+
PackageJsonUpdater.new(
|
126
|
+
package_json: file,
|
127
|
+
dependencies: dependencies
|
128
|
+
).updated_package_json.content
|
129
|
+
end
|
130
|
+
|
131
|
+
def package_files
|
132
|
+
@package_files ||= dependency_files.select { |f| f.name.end_with?("package.json") }
|
133
|
+
end
|
134
|
+
|
135
|
+
def base_dir
|
136
|
+
dependency_files.first.directory
|
137
|
+
end
|
138
|
+
|
139
|
+
def npmrc_file
|
140
|
+
dependency_files.find { |f| f.name == ".npmrc" }
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -342,7 +342,7 @@ module Dependabot
|
|
342
342
|
if Helpers.yarn_berry?(yarn_lock)
|
343
343
|
File.write(".yarnrc.yml", yarnrc_yml_content) if yarnrc_yml_file
|
344
344
|
else
|
345
|
-
File.write(".npmrc", npmrc_content)
|
345
|
+
File.write(".npmrc", npmrc_content)
|
346
346
|
File.write(".yarnrc", yarnrc_content) if yarnrc_specifies_private_reg?
|
347
347
|
end
|
348
348
|
|
@@ -12,6 +12,7 @@ module Dependabot
|
|
12
12
|
require_relative "file_updater/package_json_updater"
|
13
13
|
require_relative "file_updater/npm_lockfile_updater"
|
14
14
|
require_relative "file_updater/yarn_lockfile_updater"
|
15
|
+
require_relative "file_updater/pnpm_lockfile_updater"
|
15
16
|
|
16
17
|
class NoChangeError < StandardError
|
17
18
|
def initialize(message:, error_context:)
|
@@ -29,7 +30,8 @@ module Dependabot
|
|
29
30
|
/^package\.json$/,
|
30
31
|
/^package-lock\.json$/,
|
31
32
|
/^npm-shrinkwrap\.json$/,
|
32
|
-
/^yarn\.lock
|
33
|
+
/^yarn\.lock$/,
|
34
|
+
/^pnpm-lock\.yaml$/
|
33
35
|
]
|
34
36
|
end
|
35
37
|
|
@@ -145,6 +147,12 @@ module Dependabot
|
|
145
147
|
select { |f| f.name.end_with?("yarn.lock") }
|
146
148
|
end
|
147
149
|
|
150
|
+
def pnpm_locks
|
151
|
+
@pnpm_locks ||=
|
152
|
+
filtered_dependency_files.
|
153
|
+
select { |f| f.name.end_with?("pnpm-lock.yaml") }
|
154
|
+
end
|
155
|
+
|
148
156
|
def shrinkwraps
|
149
157
|
@shrinkwraps ||=
|
150
158
|
filtered_dependency_files.
|
@@ -162,6 +170,10 @@ module Dependabot
|
|
162
170
|
yarn_lock.content != updated_yarn_lock_content(yarn_lock)
|
163
171
|
end
|
164
172
|
|
173
|
+
def pnpm_lock_changed?(pnpm_lock)
|
174
|
+
pnpm_lock.content != updated_pnpm_lock_content(pnpm_lock)
|
175
|
+
end
|
176
|
+
|
165
177
|
def package_lock_changed?(package_lock)
|
166
178
|
package_lock.content != updated_lockfile_content(package_lock)
|
167
179
|
end
|
@@ -191,6 +203,15 @@ module Dependabot
|
|
191
203
|
)
|
192
204
|
end
|
193
205
|
|
206
|
+
pnpm_locks.each do |pnpm_lock|
|
207
|
+
next unless pnpm_lock_changed?(pnpm_lock)
|
208
|
+
|
209
|
+
updated_files << updated_file(
|
210
|
+
file: pnpm_lock,
|
211
|
+
content: updated_pnpm_lock_content(pnpm_lock)
|
212
|
+
)
|
213
|
+
end
|
214
|
+
|
194
215
|
package_locks.each do |package_lock|
|
195
216
|
next unless package_lock_changed?(package_lock)
|
196
217
|
|
@@ -218,6 +239,12 @@ module Dependabot
|
|
218
239
|
yarn_lockfile_updater.updated_yarn_lock_content(yarn_lock)
|
219
240
|
end
|
220
241
|
|
242
|
+
def updated_pnpm_lock_content(pnpm_lock)
|
243
|
+
@updated_pnpm_lock_content ||= {}
|
244
|
+
@updated_pnpm_lock_content[pnpm_lock.name] ||=
|
245
|
+
pnpm_lockfile_updater.updated_pnpm_lock_content(pnpm_lock)
|
246
|
+
end
|
247
|
+
|
221
248
|
def yarn_lockfile_updater
|
222
249
|
@yarn_lockfile_updater ||=
|
223
250
|
YarnLockfileUpdater.new(
|
@@ -228,6 +255,16 @@ module Dependabot
|
|
228
255
|
)
|
229
256
|
end
|
230
257
|
|
258
|
+
def pnpm_lockfile_updater
|
259
|
+
@pnpm_lockfile_updater ||=
|
260
|
+
PnpmLockfileUpdater.new(
|
261
|
+
dependencies: dependencies,
|
262
|
+
dependency_files: dependency_files,
|
263
|
+
repo_contents_path: repo_contents_path,
|
264
|
+
credentials: credentials
|
265
|
+
)
|
266
|
+
end
|
267
|
+
|
231
268
|
def updated_lockfile_content(file)
|
232
269
|
@updated_lockfile_content ||= {}
|
233
270
|
@updated_lockfile_content[file.name] ||=
|
@@ -40,10 +40,23 @@ module Dependabot
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def self.yarn_major_version
|
43
|
+
@yarn_major_version ||= fetch_yarn_major_version
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.pnpm_major_version
|
47
|
+
@pnpm_major_version ||= fetch_pnpm_major_version
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.fetch_yarn_major_version
|
43
51
|
output = SharedHelpers.run_shell_command("yarn --version")
|
44
52
|
Version.new(output).major
|
45
53
|
end
|
46
54
|
|
55
|
+
def self.fetch_pnpm_major_version
|
56
|
+
output = SharedHelpers.run_shell_command("pnpm --version")
|
57
|
+
Version.new(output).major
|
58
|
+
end
|
59
|
+
|
47
60
|
def self.yarn_zero_install?
|
48
61
|
File.exist?(".pnp.cjs")
|
49
62
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dependabot
|
4
|
+
module NpmAndYarn
|
5
|
+
class PackageManager
|
6
|
+
def initialize(package_json)
|
7
|
+
@package_json = package_json
|
8
|
+
end
|
9
|
+
|
10
|
+
def locked_version(name)
|
11
|
+
locked = @package_json.fetch("packageManager", nil)
|
12
|
+
return unless locked
|
13
|
+
|
14
|
+
version_match = locked.match(/#{name}@(?<version>\d+.\d+.\d+)/)
|
15
|
+
version_match&.named_captures&.fetch("version", nil)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -19,7 +19,7 @@ module Dependabot
|
|
19
19
|
if Helpers.yarn_berry?(yarn_locks.first)
|
20
20
|
File.write(".yarnrc.yml", yarnrc_yml_content) if yarnrc_yml_file
|
21
21
|
else
|
22
|
-
File.write(".npmrc", npmrc_content)
|
22
|
+
File.write(".npmrc", npmrc_content)
|
23
23
|
File.write(".yarnrc", yarnrc_content) if yarnrc_specifies_private_reg?
|
24
24
|
end
|
25
25
|
|
@@ -42,12 +42,24 @@ module Dependabot
|
|
42
42
|
select { |f| f.name.end_with?("yarn.lock") }
|
43
43
|
end
|
44
44
|
|
45
|
+
def pnpm_locks
|
46
|
+
@pnpm_locks ||=
|
47
|
+
dependency_files.
|
48
|
+
select { |f| f.name.end_with?("pnpm-lock.yaml") }
|
49
|
+
end
|
50
|
+
|
45
51
|
def root_yarn_lock
|
46
52
|
@root_yarn_lock ||=
|
47
53
|
dependency_files.
|
48
54
|
find { |f| f.name == "yarn.lock" }
|
49
55
|
end
|
50
56
|
|
57
|
+
def root_pnpm_lock
|
58
|
+
@root_pnpm_lock ||=
|
59
|
+
dependency_files.
|
60
|
+
find { |f| f.name == "pnpm-lock.yaml" }
|
61
|
+
end
|
62
|
+
|
51
63
|
def shrinkwraps
|
52
64
|
@shrinkwraps ||=
|
53
65
|
dependency_files.
|
@@ -55,7 +67,7 @@ module Dependabot
|
|
55
67
|
end
|
56
68
|
|
57
69
|
def lockfiles
|
58
|
-
[*package_locks, *shrinkwraps, *yarn_locks]
|
70
|
+
[*package_locks, *shrinkwraps, *yarn_locks, *pnpm_locks]
|
59
71
|
end
|
60
72
|
|
61
73
|
def package_files
|
@@ -74,6 +86,11 @@ module Dependabot
|
|
74
86
|
File.write(f.name, prepared_yarn_lockfile_content(f.content))
|
75
87
|
end
|
76
88
|
|
89
|
+
pnpm_locks.each do |f|
|
90
|
+
FileUtils.mkdir_p(Pathname.new(f.name).dirname)
|
91
|
+
File.write(f.name, f.content)
|
92
|
+
end
|
93
|
+
|
77
94
|
[*package_locks, *shrinkwraps].each do |f|
|
78
95
|
FileUtils.mkdir_p(Pathname.new(f.name).dirname)
|
79
96
|
File.write(f.name, f.content)
|
@@ -15,7 +15,7 @@ module Dependabot
|
|
15
15
|
class RequirementsUpdater
|
16
16
|
VERSION_REGEX = /[0-9]+(?:\.[A-Za-z0-9\-_]+)*/
|
17
17
|
SEPARATOR = /(?<=[a-zA-Z0-9*])[\s|]+(?![\s|-])/
|
18
|
-
ALLOWED_UPDATE_STRATEGIES = %i(widen_ranges bump_versions bump_versions_if_necessary).freeze
|
18
|
+
ALLOWED_UPDATE_STRATEGIES = %i(lockfile_only widen_ranges bump_versions bump_versions_if_necessary).freeze
|
19
19
|
|
20
20
|
def initialize(requirements:, updated_source:, update_strategy:,
|
21
21
|
latest_resolvable_version:)
|
@@ -32,6 +32,8 @@ module Dependabot
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def updated_requirements
|
35
|
+
return requirements if update_strategy == :lockfile_only
|
36
|
+
|
35
37
|
requirements.map do |req|
|
36
38
|
req = req.merge(source: updated_source)
|
37
39
|
next req unless latest_resolvable_version
|
@@ -4,8 +4,6 @@ require "dependabot/dependency"
|
|
4
4
|
require "dependabot/errors"
|
5
5
|
require "dependabot/logger"
|
6
6
|
require "dependabot/npm_and_yarn/file_parser"
|
7
|
-
require "dependabot/npm_and_yarn/file_updater/npmrc_builder"
|
8
|
-
require "dependabot/npm_and_yarn/file_updater/package_json_preparer"
|
9
7
|
require "dependabot/npm_and_yarn/helpers"
|
10
8
|
require "dependabot/npm_and_yarn/native_helpers"
|
11
9
|
require "dependabot/npm_and_yarn/sub_dependency_files_filterer"
|
@@ -65,6 +63,8 @@ module Dependabot
|
|
65
63
|
run_yarn_berry_updater(path, lockfile_name)
|
66
64
|
elsif lockfile.name.end_with?("yarn.lock")
|
67
65
|
run_yarn_updater(path, lockfile_name)
|
66
|
+
elsif lockfile.name.end_with?("pnpm-lock.yaml")
|
67
|
+
run_pnpm_updater(path, lockfile_name)
|
68
68
|
else
|
69
69
|
run_npm_updater(path, lockfile_name, lockfile.content)
|
70
70
|
end
|
@@ -74,9 +74,7 @@ module Dependabot
|
|
74
74
|
|
75
75
|
def version_from_updated_lockfiles(updated_lockfiles)
|
76
76
|
updated_files = dependency_files -
|
77
|
-
dependency_files_builder.
|
78
|
-
dependency_files_builder.package_locks -
|
79
|
-
dependency_files_builder.shrinkwraps +
|
77
|
+
dependency_files_builder.lockfiles +
|
80
78
|
updated_lockfiles
|
81
79
|
|
82
80
|
updated_version = NpmAndYarn::FileParser.new(
|
@@ -125,6 +123,18 @@ module Dependabot
|
|
125
123
|
end
|
126
124
|
end
|
127
125
|
|
126
|
+
def run_pnpm_updater(path, lockfile_name)
|
127
|
+
SharedHelpers.with_git_configured(credentials: credentials) do
|
128
|
+
Dir.chdir(path) do
|
129
|
+
SharedHelpers.run_shell_command(
|
130
|
+
"pnpm update #{dependency.name} --lockfile-only",
|
131
|
+
fingerprint: "pnpm update <dependency_name> --lockfile-only"
|
132
|
+
)
|
133
|
+
{ lockfile_name => File.read(lockfile_name) }
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
128
138
|
def run_npm_updater(path, lockfile_name, lockfile_content)
|
129
139
|
SharedHelpers.with_git_configured(credentials: credentials) do
|
130
140
|
Dir.chdir(path) do
|
@@ -26,7 +26,7 @@ module Dependabot
|
|
26
26
|
"vue" => %w(vue vue-template-compiler)
|
27
27
|
}.freeze
|
28
28
|
|
29
|
-
# Error message
|
29
|
+
# Error message returned by `yarn add` (for Yarn classic):
|
30
30
|
# " > @reach/router@1.2.1" has incorrect peer dependency "react@15.x || 16.x || 16.4.0-alpha.0911da3"
|
31
31
|
# "workspace-aggregator-<random-string> > test > react-dom@15.6.2" has incorrect peer dependency "react@^15.6.2"
|
32
32
|
# " > react-burger-menu@1.9.9" has unmet peer dependency "react@>=0.14.0 <16.0.0"
|
@@ -37,7 +37,7 @@ module Dependabot
|
|
37
37
|
"(?<required_dep>[^"]+)"
|
38
38
|
/x
|
39
39
|
|
40
|
-
# Error message
|
40
|
+
# Error message returned by `yarn add` (for Yarn berry):
|
41
41
|
# YN0060: │ eve-roster@workspace:. provides jest (p8d618) \
|
42
42
|
# with version 29.3.0, which doesn't satisfy \
|
43
43
|
# what ts-jest requests\n
|
@@ -46,7 +46,16 @@ module Dependabot
|
|
46
46
|
YN0060:\s|\s.+\sprovides\s(?<required_dep>.+?)\s\((?<info_hash>\w+)\).+what\s(?<requiring_dep>.+?)\srequests
|
47
47
|
/x
|
48
48
|
|
49
|
-
# Error message
|
49
|
+
# Error message returned by `pnpm update`:
|
50
|
+
# └─┬ react-dom 15.7.0
|
51
|
+
# └── ✕ unmet peer react@^15.7.0: found 16.3.1
|
52
|
+
PNPM_PEER_DEP_ERROR_REGEX =
|
53
|
+
/
|
54
|
+
┬\s(?<requiring_dep>[^\n]+)\n
|
55
|
+
[^\n]*✕\sunmet\speer\s(?<required_dep>[^:]+):
|
56
|
+
/mx
|
57
|
+
|
58
|
+
# Error message returned by `npm install` (for NPM 6):
|
50
59
|
# react-dom@15.2.0 requires a peer of react@^15.2.0 \
|
51
60
|
# but none is installed. You must install peer dependencies yourself.
|
52
61
|
NPM6_PEER_DEP_ERROR_REGEX =
|
@@ -56,7 +65,7 @@ module Dependabot
|
|
56
65
|
(?<required_dep>.+?)\sbut\snone\sis\sinstalled.
|
57
66
|
/x
|
58
67
|
|
59
|
-
# Error message
|
68
|
+
# Error message returned by `npm install` (for NPM 8):
|
60
69
|
# npm ERR! Could not resolve dependency:
|
61
70
|
# npm ERR! peer react@"^16.14.0" from react-dom@16.14.0
|
62
71
|
#
|
@@ -320,8 +329,7 @@ module Dependabot
|
|
320
329
|
SharedHelpers.in_a_temporary_repo_directory(base_dir, repo_contents_path) do
|
321
330
|
dependency_files_builder.write_temporary_dependency_files
|
322
331
|
|
323
|
-
|
324
|
-
path = Pathname.new(file.name).dirname
|
332
|
+
paths_requiring_update_check.flat_map do |path|
|
325
333
|
run_checker(path: path, version: version)
|
326
334
|
end.compact
|
327
335
|
end
|
@@ -332,24 +340,30 @@ module Dependabot
|
|
332
340
|
[]
|
333
341
|
end
|
334
342
|
|
335
|
-
def handle_peer_dependency_errors(
|
343
|
+
def handle_peer_dependency_errors(message)
|
336
344
|
errors = []
|
337
|
-
if
|
338
|
-
|
345
|
+
if message.match?(NPM6_PEER_DEP_ERROR_REGEX)
|
346
|
+
message.scan(NPM6_PEER_DEP_ERROR_REGEX) do
|
339
347
|
errors << Regexp.last_match.named_captures
|
340
348
|
end
|
341
|
-
elsif
|
342
|
-
|
349
|
+
elsif message.match?(NPM8_PEER_DEP_ERROR_REGEX)
|
350
|
+
message.scan(NPM8_PEER_DEP_ERROR_REGEX) do
|
343
351
|
errors << Regexp.last_match.named_captures
|
344
352
|
end
|
345
|
-
elsif
|
346
|
-
|
353
|
+
elsif message.match?(YARN_PEER_DEP_ERROR_REGEX)
|
354
|
+
message.scan(YARN_PEER_DEP_ERROR_REGEX) do
|
347
355
|
errors << Regexp.last_match.named_captures
|
348
356
|
end
|
349
|
-
elsif
|
350
|
-
|
357
|
+
elsif message.match?(YARN_BERRY_PEER_DEP_ERROR_REGEX)
|
358
|
+
message.scan(YARN_BERRY_PEER_DEP_ERROR_REGEX) do
|
351
359
|
errors << Regexp.last_match.named_captures
|
352
360
|
end
|
361
|
+
elsif message.match?(PNPM_PEER_DEP_ERROR_REGEX)
|
362
|
+
message.scan(PNPM_PEER_DEP_ERROR_REGEX) do
|
363
|
+
captures = Regexp.last_match.named_captures
|
364
|
+
captures["requiring_dep"].tr!(" ", "@")
|
365
|
+
errors << captures
|
366
|
+
end
|
353
367
|
else
|
354
368
|
raise
|
355
369
|
end
|
@@ -483,20 +497,24 @@ module Dependabot
|
|
483
497
|
end
|
484
498
|
|
485
499
|
def run_checker(path:, version:)
|
486
|
-
# If there are both yarn lockfiles and npm lockfiles only run the
|
487
|
-
# yarn updater
|
488
500
|
yarn_lockfiles = lockfiles_for_path(lockfiles: dependency_files_builder.yarn_locks, path: path)
|
489
501
|
return run_yarn_checker(path: path, version: version, lockfile: yarn_lockfiles.first) if yarn_lockfiles.any?
|
490
502
|
|
503
|
+
pnpm_lockfiles = lockfiles_for_path(lockfiles: dependency_files_builder.pnpm_locks, path: path)
|
504
|
+
return run_pnpm_checker(path: path, version: version) if pnpm_lockfiles.any?
|
505
|
+
|
491
506
|
npm_lockfiles = lockfiles_for_path(lockfiles: dependency_files_builder.package_locks, path: path)
|
492
507
|
return run_npm_checker(path: path, version: version) if npm_lockfiles.any?
|
493
508
|
|
494
509
|
root_yarn_lock = dependency_files_builder.root_yarn_lock
|
495
510
|
return run_yarn_checker(path: path, version: version, lockfile: root_yarn_lock) if root_yarn_lock
|
496
511
|
|
512
|
+
root_pnpm_lock = dependency_files_builder.root_pnpm_lock
|
513
|
+
return run_pnpm_checker(path: path, version: version) if root_pnpm_lock
|
514
|
+
|
497
515
|
run_npm_checker(path: path, version: version)
|
498
516
|
rescue SharedHelpers::HelperSubprocessFailed => e
|
499
|
-
handle_peer_dependency_errors(e)
|
517
|
+
handle_peer_dependency_errors(e.message)
|
500
518
|
end
|
501
519
|
|
502
520
|
def run_yarn_checker(path:, version:, lockfile:)
|
@@ -505,6 +523,23 @@ module Dependabot
|
|
505
523
|
run_yarn_classic_checker(path: path, version: version)
|
506
524
|
end
|
507
525
|
|
526
|
+
def run_pnpm_checker(path:, version:)
|
527
|
+
SharedHelpers.with_git_configured(credentials: credentials) do
|
528
|
+
Dir.chdir(path) do
|
529
|
+
output = SharedHelpers.run_shell_command(
|
530
|
+
"pnpm update #{dependency.name}@#{version} --lockfile-only",
|
531
|
+
fingerprint: "pnpm update <dependency_name>@<version> --lockfile-only"
|
532
|
+
)
|
533
|
+
if PNPM_PEER_DEP_ERROR_REGEX.match?(output)
|
534
|
+
raise SharedHelpers::HelperSubprocessFailed.new(
|
535
|
+
message: output,
|
536
|
+
error_context: {}
|
537
|
+
)
|
538
|
+
end
|
539
|
+
end
|
540
|
+
end
|
541
|
+
end
|
542
|
+
|
508
543
|
def run_yarn_berry_checker(path:, version:)
|
509
544
|
# This method mimics calling a native helper in order to comply with the caller's expectations
|
510
545
|
# Specifically we add the dependency at the specified updated version
|
@@ -612,12 +647,12 @@ module Dependabot
|
|
612
647
|
).parse.select(&:top_level?)
|
613
648
|
end
|
614
649
|
|
615
|
-
def
|
616
|
-
@
|
650
|
+
def paths_requiring_update_check
|
651
|
+
@paths_requiring_update_check ||=
|
617
652
|
DependencyFilesFilterer.new(
|
618
653
|
dependency_files: dependency_files,
|
619
654
|
updated_dependencies: [dependency]
|
620
|
-
).
|
655
|
+
).paths_requiring_update_check
|
621
656
|
end
|
622
657
|
|
623
658
|
def dependency_files_builder
|
@@ -102,6 +102,10 @@ module Dependabot
|
|
102
102
|
).updated_requirements
|
103
103
|
end
|
104
104
|
|
105
|
+
def requirements_unlocked_or_can_be?
|
106
|
+
requirements_update_strategy != :lockfile_only
|
107
|
+
end
|
108
|
+
|
105
109
|
def requirements_update_strategy
|
106
110
|
# If passed in as an option (in the base class) honour that option
|
107
111
|
return @requirements_update_strategy.to_sym if @requirements_update_strategy
|
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.218.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dependabot
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-05-22 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.218.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.218.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: debug
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -227,6 +227,8 @@ files:
|
|
227
227
|
- helpers/lib/npm6/remove-dependencies-from-lockfile.js
|
228
228
|
- helpers/lib/npm6/subdependency-updater.js
|
229
229
|
- helpers/lib/npm6/updater.js
|
230
|
+
- helpers/lib/pnpm/index.js
|
231
|
+
- helpers/lib/pnpm/lockfile-parser.js
|
230
232
|
- helpers/lib/yarn/conflicting-dependency-parser.js
|
231
233
|
- helpers/lib/yarn/fix-duplicates.js
|
232
234
|
- helpers/lib/yarn/helpers.js
|
@@ -274,16 +276,19 @@ files:
|
|
274
276
|
- lib/dependabot/npm_and_yarn/file_parser.rb
|
275
277
|
- lib/dependabot/npm_and_yarn/file_parser/json_lock.rb
|
276
278
|
- lib/dependabot/npm_and_yarn/file_parser/lockfile_parser.rb
|
279
|
+
- lib/dependabot/npm_and_yarn/file_parser/pnpm_lock.rb
|
277
280
|
- lib/dependabot/npm_and_yarn/file_parser/yarn_lock.rb
|
278
281
|
- lib/dependabot/npm_and_yarn/file_updater.rb
|
279
282
|
- lib/dependabot/npm_and_yarn/file_updater/npm_lockfile_updater.rb
|
280
283
|
- lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb
|
281
284
|
- lib/dependabot/npm_and_yarn/file_updater/package_json_preparer.rb
|
282
285
|
- lib/dependabot/npm_and_yarn/file_updater/package_json_updater.rb
|
286
|
+
- lib/dependabot/npm_and_yarn/file_updater/pnpm_lockfile_updater.rb
|
283
287
|
- lib/dependabot/npm_and_yarn/file_updater/yarn_lockfile_updater.rb
|
284
288
|
- lib/dependabot/npm_and_yarn/helpers.rb
|
285
289
|
- lib/dependabot/npm_and_yarn/metadata_finder.rb
|
286
290
|
- lib/dependabot/npm_and_yarn/native_helpers.rb
|
291
|
+
- lib/dependabot/npm_and_yarn/package_manager.rb
|
287
292
|
- lib/dependabot/npm_and_yarn/package_name.rb
|
288
293
|
- lib/dependabot/npm_and_yarn/requirement.rb
|
289
294
|
- lib/dependabot/npm_and_yarn/sub_dependency_files_filterer.rb
|
@@ -302,8 +307,8 @@ homepage: https://github.com/dependabot/dependabot-core
|
|
302
307
|
licenses:
|
303
308
|
- Nonstandard
|
304
309
|
metadata:
|
305
|
-
|
306
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/
|
310
|
+
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
311
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.218.0
|
307
312
|
post_install_message:
|
308
313
|
rdoc_options: []
|
309
314
|
require_paths:
|