dependabot-npm_and_yarn 0.237.0 → 0.238.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/helpers/package-lock.json +206 -923
- data/helpers/package.json +4 -4
- data/lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb +35 -26
- data/lib/dependabot/npm_and_yarn/file_updater/pnpm_lockfile_updater.rb +13 -8
- data/lib/dependabot/npm_and_yarn/file_updater/yarn_lockfile_updater.rb +5 -4
- data/lib/dependabot/npm_and_yarn/helpers.rb +38 -8
- data/lib/dependabot/npm_and_yarn/registry_parser.rb +2 -2
- data/lib/dependabot/npm_and_yarn/update_checker/latest_version_finder.rb +15 -8
- data/lib/dependabot/npm_and_yarn/update_checker/registry_finder.rb +24 -8
- metadata +5 -5
data/helpers/package.json
CHANGED
@@ -11,9 +11,9 @@
|
|
11
11
|
},
|
12
12
|
"dependencies": {
|
13
13
|
"@dependabot/yarn-lib": "^1.22.19",
|
14
|
-
"@npmcli/arborist": "^7.2.
|
14
|
+
"@npmcli/arborist": "^7.2.1",
|
15
15
|
"detect-indent": "^6.1.0",
|
16
|
-
"nock": "^13.3.
|
16
|
+
"nock": "^13.3.8",
|
17
17
|
"npm": "6.14.18",
|
18
18
|
"@pnpm/lockfile-file": "^8.1.4",
|
19
19
|
"@pnpm/dependency-path": "^2.1.1",
|
@@ -21,9 +21,9 @@
|
|
21
21
|
"patch-package": "^8.0.0"
|
22
22
|
},
|
23
23
|
"devDependencies": {
|
24
|
-
"eslint": "^8.
|
24
|
+
"eslint": "^8.54.0",
|
25
25
|
"eslint-config-prettier": "^9.0.0",
|
26
26
|
"jest": "^29.7.0",
|
27
|
-
"prettier": "^3.0
|
27
|
+
"prettier": "^3.1.0"
|
28
28
|
}
|
29
29
|
}
|
@@ -32,9 +32,17 @@ module Dependabot
|
|
32
32
|
build_npmrc_content_from_lockfile
|
33
33
|
end
|
34
34
|
|
35
|
-
|
35
|
+
final_content = initial_content || ""
|
36
36
|
|
37
|
-
|
37
|
+
return final_content unless registry_credentials.any?
|
38
|
+
|
39
|
+
credential_lines_for_npmrc.each do |credential_line|
|
40
|
+
next if final_content.include?(credential_line)
|
41
|
+
|
42
|
+
final_content = [final_content, credential_line].reject(&:empty?).join("\n")
|
43
|
+
end
|
44
|
+
|
45
|
+
final_content
|
38
46
|
end
|
39
47
|
|
40
48
|
# PROXY WORK
|
@@ -105,15 +113,7 @@ module Dependabot
|
|
105
113
|
token = global_registry.fetch("token", nil)
|
106
114
|
return "" unless token
|
107
115
|
|
108
|
-
|
109
|
-
encoded_token = Base64.encode64(token).delete("\n")
|
110
|
-
"_auth = #{encoded_token}\n"
|
111
|
-
elsif Base64.decode64(token).ascii_only? &&
|
112
|
-
Base64.decode64(token).include?(":")
|
113
|
-
"_auth = #{token.delete("\n")}\n"
|
114
|
-
else
|
115
|
-
"_authToken = #{token}\n"
|
116
|
-
end
|
116
|
+
auth_line(token, global_registry.fetch("registry")) + "\n"
|
117
117
|
end
|
118
118
|
|
119
119
|
def yarnrc_global_registry_auth_line
|
@@ -122,12 +122,12 @@ module Dependabot
|
|
122
122
|
|
123
123
|
if token.include?(":")
|
124
124
|
encoded_token = Base64.encode64(token).delete("\n")
|
125
|
-
"npmAuthIdent: \"#{encoded_token}\"
|
125
|
+
"npmAuthIdent: \"#{encoded_token}\""
|
126
126
|
elsif Base64.decode64(token).ascii_only? &&
|
127
127
|
Base64.decode64(token).include?(":")
|
128
|
-
"npmAuthIdent: \"#{token.delete("\n")}\"
|
128
|
+
"npmAuthIdent: \"#{token.delete("\n")}\""
|
129
129
|
else
|
130
|
-
"npmAuthToken: \"#{token}\"
|
130
|
+
"npmAuthToken: \"#{token}\""
|
131
131
|
end
|
132
132
|
end
|
133
133
|
|
@@ -230,18 +230,7 @@ module Dependabot
|
|
230
230
|
token = cred.fetch("token", nil)
|
231
231
|
next unless token
|
232
232
|
|
233
|
-
|
234
|
-
# but we do not want to add one if it already exists
|
235
|
-
registry_with_trailing_slash = registry.sub(%r{\/?$}, "/")
|
236
|
-
if token.include?(":")
|
237
|
-
encoded_token = Base64.encode64(token).delete("\n")
|
238
|
-
lines << "//#{registry_with_trailing_slash}:_auth=#{encoded_token}"
|
239
|
-
elsif Base64.decode64(token).ascii_only? &&
|
240
|
-
Base64.decode64(token).include?(":")
|
241
|
-
lines << %(//#{registry_with_trailing_slash}:_auth=#{token.delete("\n")})
|
242
|
-
else
|
243
|
-
lines << "//#{registry_with_trailing_slash}:_authToken=#{token}"
|
244
|
-
end
|
233
|
+
lines << auth_line(token, registry)
|
245
234
|
end
|
246
235
|
|
247
236
|
return lines unless lines.any? { |str| str.include?("auth=") }
|
@@ -250,6 +239,26 @@ module Dependabot
|
|
250
239
|
["always-auth = true"] + lines
|
251
240
|
end
|
252
241
|
|
242
|
+
def auth_line(token, registry = nil)
|
243
|
+
auth = if token.include?(":")
|
244
|
+
encoded_token = Base64.encode64(token).delete("\n")
|
245
|
+
"_auth=#{encoded_token}"
|
246
|
+
elsif Base64.decode64(token).ascii_only? &&
|
247
|
+
Base64.decode64(token).include?(":")
|
248
|
+
"_auth=#{token.delete("\n")}"
|
249
|
+
else
|
250
|
+
"_authToken=#{token}"
|
251
|
+
end
|
252
|
+
|
253
|
+
return auth unless registry
|
254
|
+
|
255
|
+
# We need to ensure the registry uri ends with a trailing slash in the npmrc file
|
256
|
+
# but we do not want to add one if it already exists
|
257
|
+
registry_with_trailing_slash = registry.sub(%r{\/?$}, "/")
|
258
|
+
|
259
|
+
"//#{registry_with_trailing_slash}:#{auth}"
|
260
|
+
end
|
261
|
+
|
253
262
|
def npmrc_scoped_registries
|
254
263
|
return [] unless npmrc_file
|
255
264
|
|
@@ -37,7 +37,9 @@ module Dependabot
|
|
37
37
|
IRRESOLVABLE_PACKAGE = "ERR_PNPM_NO_MATCHING_VERSION"
|
38
38
|
INVALID_REQUIREMENT = "ERR_PNPM_SPEC_NOT_SUPPORTED_BY_ANY_RESOLVER"
|
39
39
|
UNREACHABLE_GIT = %r{ERR_PNPM_FETCH_404[ [^:print:]]+GET (?<url>https://codeload\.github\.com/[^/]+/[^/]+)/}
|
40
|
+
FORBIDDEN_PACKAGE = /ERR_PNPM_FETCH_403[ [^:print:]]+GET (?<dependency_url>.*): Forbidden - 403/
|
40
41
|
MISSING_PACKAGE = /ERR_PNPM_FETCH_404[ [^:print:]]+GET (?<dependency_url>.*): Not Found - 404/
|
42
|
+
UNAUTHORIZED_PACKAGE = /ERR_PNPM_FETCH_401[ [^:print:]]+GET (?<dependency_url>.*): Unauthorized - 401/
|
41
43
|
|
42
44
|
def run_pnpm_update(pnpm_lock:)
|
43
45
|
SharedHelpers.in_a_temporary_repo_directory(base_dir, repo_contents_path) do
|
@@ -90,18 +92,20 @@ module Dependabot
|
|
90
92
|
end
|
91
93
|
|
92
94
|
if error_message.match?(UNREACHABLE_GIT)
|
93
|
-
|
95
|
+
url = error_message.match(UNREACHABLE_GIT).named_captures.fetch("url")
|
94
96
|
|
95
|
-
raise Dependabot::GitDependenciesNotReachable,
|
97
|
+
raise Dependabot::GitDependenciesNotReachable, url
|
96
98
|
end
|
97
99
|
|
98
|
-
|
100
|
+
[FORBIDDEN_PACKAGE, MISSING_PACKAGE, UNAUTHORIZED_PACKAGE].each do |regexp|
|
101
|
+
next unless error_message.match?(regexp)
|
99
102
|
|
100
|
-
|
101
|
-
.named_captures["dependency_url"]
|
103
|
+
dependency_url = error_message.match(regexp).named_captures["dependency_url"]
|
102
104
|
|
103
|
-
|
104
|
-
|
105
|
+
raise_package_access_error(dependency_url, pnpm_lock)
|
106
|
+
end
|
107
|
+
|
108
|
+
raise
|
105
109
|
end
|
106
110
|
|
107
111
|
def raise_resolvability_error(error_message, pnpm_lock)
|
@@ -111,7 +115,8 @@ module Dependabot
|
|
111
115
|
raise Dependabot::DependencyFileNotResolvable, msg
|
112
116
|
end
|
113
117
|
|
114
|
-
def
|
118
|
+
def raise_package_access_error(dependency_url, pnpm_lock)
|
119
|
+
package_name = RegistryParser.new(resolved_url: dependency_url, credentials: credentials).dependency_name
|
115
120
|
missing_dep = lockfile_dependencies(pnpm_lock)
|
116
121
|
.find { |dep| dep.name == package_name }
|
117
122
|
|
@@ -186,7 +186,7 @@ module Dependabot
|
|
186
186
|
end
|
187
187
|
|
188
188
|
def yarn_berry_args
|
189
|
-
Helpers.yarn_berry_args
|
189
|
+
@yarn_berry_args ||= Helpers.yarn_berry_args
|
190
190
|
end
|
191
191
|
|
192
192
|
def run_yarn_top_level_updater(top_level_dependency_updates:)
|
@@ -228,9 +228,9 @@ module Dependabot
|
|
228
228
|
# Local path error: When installing a git dependency which
|
229
229
|
# is using local file paths for sub-dependencies (e.g. unbuilt yarn
|
230
230
|
# workspace project)
|
231
|
-
sub_dep_local_path_err =
|
231
|
+
sub_dep_local_path_err = "refers to a non-existing file"
|
232
232
|
if error_message.match?(INVALID_PACKAGE) ||
|
233
|
-
error_message.
|
233
|
+
error_message.include?(sub_dep_local_path_err)
|
234
234
|
raise_resolvability_error(error_message, yarn_lock)
|
235
235
|
end
|
236
236
|
|
@@ -295,7 +295,8 @@ module Dependabot
|
|
295
295
|
handle_timeout(error_message, yarn_lock) if error_message.match?(TIMEOUT_FETCHING_PACKAGE)
|
296
296
|
|
297
297
|
if error_message.start_with?("Couldn't find any versions") ||
|
298
|
-
error_message.include?(": Not found")
|
298
|
+
error_message.include?(": Not found") ||
|
299
|
+
error_message.include?("Couldn't find match for")
|
299
300
|
|
300
301
|
raise_resolvability_error(error_message, yarn_lock) unless resolvable_before_update?(yarn_lock)
|
301
302
|
|
@@ -4,6 +4,9 @@
|
|
4
4
|
module Dependabot
|
5
5
|
module NpmAndYarn
|
6
6
|
module Helpers
|
7
|
+
YARN_PATH_NOT_FOUND =
|
8
|
+
/^.*(?<error>The "yarn-path" option has been set \(in [^)]+\), but the specified location doesn't exist)/
|
9
|
+
|
7
10
|
def self.npm_version(lockfile_content)
|
8
11
|
"npm#{npm_version_numeric(lockfile_content)}"
|
9
12
|
end
|
@@ -51,12 +54,33 @@ module Dependabot
|
|
51
54
|
end
|
52
55
|
|
53
56
|
def self.yarn_major_version
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.fetch_yarn_major_version
|
57
|
+
retries = 0
|
58
58
|
output = SharedHelpers.run_shell_command("yarn --version")
|
59
59
|
Version.new(output).major
|
60
|
+
rescue Dependabot::SharedHelpers::HelperSubprocessFailed => e
|
61
|
+
# Should never happen, can probably be removed once this settles
|
62
|
+
raise "Failed to replace ENV, not sure why" if T.must(retries).positive?
|
63
|
+
|
64
|
+
message = e.message
|
65
|
+
|
66
|
+
missing_env_var_regex = %r{Environment variable not found \((?:[^)]+)\) in #{Dir.pwd}/(?<path>\S+)}
|
67
|
+
|
68
|
+
if message.match?(missing_env_var_regex)
|
69
|
+
match = T.must(message.match(missing_env_var_regex))
|
70
|
+
path = T.must(match.named_captures["path"])
|
71
|
+
|
72
|
+
File.write(path, File.read(path).gsub(/\$\{[^}-]+\}/, ""))
|
73
|
+
retries = T.must(retries) + 1
|
74
|
+
|
75
|
+
retry
|
76
|
+
end
|
77
|
+
|
78
|
+
if YARN_PATH_NOT_FOUND.match?(message)
|
79
|
+
error = T.must(T.must(YARN_PATH_NOT_FOUND.match(message))[:error]).sub(Dir.pwd, ".")
|
80
|
+
raise MisconfiguredTooling.new("Yarn", error)
|
81
|
+
end
|
82
|
+
|
83
|
+
raise
|
60
84
|
end
|
61
85
|
|
62
86
|
def self.yarn_zero_install?
|
@@ -84,15 +108,21 @@ module Dependabot
|
|
84
108
|
yarn_major_version >= 3 && (yarn_zero_install? || yarn_offline_cache?)
|
85
109
|
end
|
86
110
|
|
111
|
+
def self.yarn_berry_disable_scripts?
|
112
|
+
yarn_major_version == 2 || !yarn_zero_install?
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.yarn_4_or_higher?
|
116
|
+
yarn_major_version >= 4
|
117
|
+
end
|
118
|
+
|
87
119
|
def self.setup_yarn_berry
|
88
120
|
# Always disable immutable installs so yarn's CI detection doesn't prevent updates.
|
89
121
|
SharedHelpers.run_shell_command("yarn config set enableImmutableInstalls false")
|
90
122
|
# Do not generate a cache if offline cache disabled. Otherwise side effects may confuse further checks
|
91
123
|
SharedHelpers.run_shell_command("yarn config set enableGlobalCache true") unless yarn_berry_skip_build?
|
92
124
|
# We never want to execute postinstall scripts, either set this config or mode=skip-build must be set
|
93
|
-
|
94
|
-
SharedHelpers.run_shell_command("yarn config set enableScripts false")
|
95
|
-
end
|
125
|
+
SharedHelpers.run_shell_command("yarn config set enableScripts false") if yarn_berry_disable_scripts?
|
96
126
|
if (http_proxy = ENV.fetch("HTTP_PROXY", false))
|
97
127
|
SharedHelpers.run_shell_command("yarn config set httpProxy #{http_proxy}")
|
98
128
|
end
|
@@ -101,7 +131,7 @@ module Dependabot
|
|
101
131
|
end
|
102
132
|
return unless (ca_file_path = ENV.fetch("NODE_EXTRA_CA_CERTS", false))
|
103
133
|
|
104
|
-
if
|
134
|
+
if yarn_4_or_higher?
|
105
135
|
SharedHelpers.run_shell_command("yarn config set httpsCaFilePath #{ca_file_path}")
|
106
136
|
else
|
107
137
|
SharedHelpers.run_shell_command("yarn config set caFilePath #{ca_file_path}")
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module Dependabot
|
@@ -38,7 +38,7 @@ module Dependabot
|
|
38
38
|
resolved_url
|
39
39
|
end
|
40
40
|
|
41
|
-
url_base.
|
41
|
+
url_base[/@.*/].gsub("%2F", "/").split("/")[0..1].join("/")
|
42
42
|
end
|
43
43
|
|
44
44
|
private
|
@@ -225,17 +225,24 @@ module Dependabot
|
|
225
225
|
|
226
226
|
@yanked[version] =
|
227
227
|
begin
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
# Some registries don't handle escaped package names properly
|
228
|
+
if dependency_registry == "registry.npmjs.org"
|
229
|
+
status = Dependabot::RegistryClient.head(
|
230
|
+
url: registry_finder.tarball_url(version),
|
231
|
+
headers: registry_auth_headers
|
232
|
+
).status
|
233
|
+
else
|
235
234
|
status = Dependabot::RegistryClient.get(
|
236
|
-
url: dependency_url
|
235
|
+
url: dependency_url + "/#{version}",
|
237
236
|
headers: registry_auth_headers
|
238
237
|
).status
|
238
|
+
|
239
|
+
if status == 404
|
240
|
+
# Some registries don't handle escaped package names properly
|
241
|
+
status = Dependabot::RegistryClient.get(
|
242
|
+
url: dependency_url.gsub("%2F", "/") + "/#{version}",
|
243
|
+
headers: registry_auth_headers
|
244
|
+
).status
|
245
|
+
end
|
239
246
|
end
|
240
247
|
|
241
248
|
version_not_found = status == 404
|
@@ -39,7 +39,14 @@ module Dependabot
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def dependency_url
|
42
|
-
"#{registry_url
|
42
|
+
"#{registry_url}/#{escaped_dependency_name}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def tarball_url(version)
|
46
|
+
version_without_build_metadata = version.to_s.gsub(/\+.*/, "")
|
47
|
+
|
48
|
+
# Dependency name needs to be unescaped since tarball URLs don't always work with escaped slashes
|
49
|
+
"#{registry_url}/#{dependency.name}/-/#{scopeless_name}-#{version_without_build_metadata}.tgz"
|
43
50
|
end
|
44
51
|
|
45
52
|
def self.central_registry?(registry)
|
@@ -85,16 +92,21 @@ module Dependabot
|
|
85
92
|
end
|
86
93
|
|
87
94
|
def registry_url
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
if registry_source_url
|
92
|
-
registry_source_url.split("://").first
|
95
|
+
url =
|
96
|
+
if registry.start_with?("http")
|
97
|
+
registry
|
93
98
|
else
|
94
|
-
|
99
|
+
protocol =
|
100
|
+
if registry_source_url
|
101
|
+
registry_source_url.split("://").first
|
102
|
+
else
|
103
|
+
"https"
|
104
|
+
end
|
105
|
+
|
106
|
+
"#{protocol}://#{registry}"
|
95
107
|
end
|
96
108
|
|
97
|
-
|
109
|
+
url.gsub(%r{/+$}, "")
|
98
110
|
end
|
99
111
|
|
100
112
|
def auth_header_for(token)
|
@@ -274,6 +286,10 @@ module Dependabot
|
|
274
286
|
dependency.name.gsub("/", "%2F")
|
275
287
|
end
|
276
288
|
|
289
|
+
def scopeless_name
|
290
|
+
dependency.name.split("/").last
|
291
|
+
end
|
292
|
+
|
277
293
|
def registry_source_url
|
278
294
|
sources = dependency.requirements
|
279
295
|
.map { |r| r.fetch(:source) }.uniq.compact
|
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.238.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-12-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.238.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.238.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: debug
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -310,7 +310,7 @@ licenses:
|
|
310
310
|
- Nonstandard
|
311
311
|
metadata:
|
312
312
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
313
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
313
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.238.0
|
314
314
|
post_install_message:
|
315
315
|
rdoc_options: []
|
316
316
|
require_paths:
|