dependabot-npm_and_yarn 0.274.0 → 0.275.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: 4fe1263109daa3956820bc6977b9d31f6b372d93fac8ee628d98f4f53fdcb992
4
- data.tar.gz: 9b8ce74245d5957e545fa43e2fabefb0a0987e9ea8aa0e978a97cd51c59da550
3
+ metadata.gz: fa9059df74fb7336b4718049555dedd8887c3d08add5cef44110728371612a41
4
+ data.tar.gz: 4abdcd71749994bbfd88b25e2bd33301debe86459dbe8205d30552475e7e3944
5
5
  SHA512:
6
- metadata.gz: 81ead43e58c76eed9c89dbfb0fe31c23f95dc692a079e097f540ac136a464d5eeaae7d861c2b8b81de58861bb5b7630875499e2e17154989f3617f06ac3599ed
7
- data.tar.gz: 6355efedf3c69ff07f21c1c7bb548045b318fafb0e7acabebdcc231e0564baead08b52fd862707d545b52be77d1dae26077b9ff86cb16592786ed81ebc2d5cd7
6
+ metadata.gz: a5003914050f7914b55c3d77bba2b05c8905d6959b6a470b86ed029437a703d43436e05527fdbff63ca6d7f346c4ce891f46eada96920c0478e26152aa1eadb5
7
+ data.tar.gz: 50b3c80faf71ec749c0fe84ec8dd61c387450a5be7c7f5e01c8a2732ae2a776e11f71fb2e38cbc244f75a34ac754c404b58f02e0f55bb606b73f701872652ada
@@ -98,6 +98,15 @@ module Dependabot
98
98
  /Couldn't find package "(?<pkg>.*)" required by "(?<dep>.*)" on the "(?<regis>.*)" registry./
99
99
  ].freeze, T::Array[Regexp])
100
100
 
101
+ # dependency access protocol not supported by packagemanager
102
+ UNSUPPORTED_PROTOCOL = /EUNSUPPORTEDPROTOCOL\n(.*?)Unsupported URL Type "(?<access_method>.*)"/
103
+
104
+ # Internal server error returned from registry
105
+ SERVER_ERROR_500 = /500 Internal Server Error - GET (?<regis>.*)/
106
+
107
+ # issue related when dependency url is not mentioned correctly
108
+ UNRESOLVED_REFERENCE = /Unable to resolve reference (?<deps>.*)/
109
+
101
110
  # TODO: look into fixing this in npm, seems like a bug in the git
102
111
  # downloader introduced in npm 7
103
112
  #
@@ -428,6 +437,18 @@ module Dependabot
428
437
  raise Dependabot::PrivateSourceAuthenticationFailure, url
429
438
  end
430
439
 
440
+ if error_message.match?(SERVER_ERROR_500)
441
+ url = T.must(URI.decode_www_form_component(error_message).split("https://").last).split("/").first
442
+ msg = "Server error (500) while accessing #{url}."
443
+ raise Dependabot::DependencyFileNotResolvable, msg
444
+ end
445
+
446
+ if (error_msg = error_message.match(UNRESOLVED_REFERENCE))
447
+ dep = error_msg.named_captures["deps"]
448
+ msg = "Unable to resolve reference #{dep}."
449
+ raise Dependabot::DependencyFileNotResolvable, msg
450
+ end
451
+
431
452
  if error_message.match?(MISSING_PACKAGE)
432
453
  package_name = T.must(error_message.match(MISSING_PACKAGE))
433
454
  .named_captures["package_req"]
@@ -590,6 +611,11 @@ module Dependabot
590
611
  raise Dependabot::DependencyFileNotResolvable, msg
591
612
  end
592
613
 
614
+ if (error_msg = error_message.match(UNSUPPORTED_PROTOCOL))
615
+ msg = "Unsupported protocol \"#{error_msg.named_captures.fetch('access_method')}\" while accessing dependency." # rubocop:disable Layout/LineLength
616
+ raise Dependabot::DependencyFileNotResolvable, msg
617
+ end
618
+
593
619
  raise error
594
620
  end
595
621
  # rubocop:enable Metrics/AbcSize
@@ -2,20 +2,55 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/shared_helpers"
5
+ require "dependabot/npm_and_yarn/version_selector"
5
6
 
6
7
  module Dependabot
7
8
  module NpmAndYarn
8
9
  class PackageManager
10
+ extend T::Sig
11
+ extend T::Helpers
9
12
  def initialize(package_json, lockfiles:)
10
13
  @package_json = package_json
11
14
  @lockfiles = lockfiles
12
15
  @package_manager = package_json.fetch("packageManager", nil)
16
+ @engines = package_json.fetch("engines", nil)
13
17
  end
14
18
 
19
+ # rubocop:disable Metrics/CyclomaticComplexity
20
+ # rubocop:disable Metrics/PerceivedComplexity
15
21
  def setup(name)
16
- return unless @package_manager.nil? || @package_manager.start_with?("#{name}@")
22
+ # we prioritize version mentioned in "packageManager" instead of "engines"
23
+ # i.e. if { engines : "pnpm" : "6" } and { packageManager: "pnpm@6.0.2" },
24
+ # we go for the specificity mentioned in packageManager (6.0.2)
17
25
 
18
- version = requested_version(name)
26
+ if Dependabot::Experiments.enabled?(:enable_pnpm_yarn_dynamic_engine)
27
+
28
+ unless @package_manager&.start_with?("#{name}@") || (@package_manager&.==name.to_s) || @package_manager.nil?
29
+ return
30
+ end
31
+
32
+ if @engines && @package_manager.nil?
33
+ # if "packageManager" doesn't exists in manifest file,
34
+ # we check if we can extract "engines" information
35
+ Dependabot.logger.info("No \"packageManager\" info found for \"#{name}\"")
36
+ version = check_engine_version(name)
37
+
38
+ elsif @package_manager&.==name.to_s
39
+ # if "packageManager" is found but no version is specified (i.e. pnpm@1.2.3),
40
+ # we check if we can get "engines" info to override default version
41
+ Dependabot.logger.info("Found \"packageManager\" : \"#{@package_manager}\"")
42
+ version = check_engine_version(name) if @engines
43
+
44
+ elsif @package_manager&.start_with?("#{name}@")
45
+ # if "packageManager" info has version specification i.e. yarn@3.3.1
46
+ # we go with the version in "packageManager"
47
+ Dependabot.logger.info("Found \"packageManager\" : \"#{@package_manager}\". Skipped checking \"engines\".")
48
+ end
49
+ else
50
+ return unless @package_manager.nil? || @package_manager&.start_with?("#{name}@")
51
+ end
52
+
53
+ version ||= requested_version(name)
19
54
 
20
55
  if version
21
56
  raise_if_unsupported!(name, version)
@@ -33,6 +68,8 @@ module Dependabot
33
68
 
34
69
  version
35
70
  end
71
+ # rubocop:enable Metrics/CyclomaticComplexity
72
+ # rubocop:enable Metrics/PerceivedComplexity
36
73
 
37
74
  private
38
75
 
@@ -44,6 +81,8 @@ module Dependabot
44
81
  end
45
82
 
46
83
  def install(name, version)
84
+ Dependabot.logger.info("Installing \"#{name}@#{version}\"")
85
+
47
86
  SharedHelpers.run_shell_command(
48
87
  "corepack install #{name}@#{version} --global --cache-only",
49
88
  fingerprint: "corepack install <name>@<version> --global --cache-only"
@@ -53,9 +92,10 @@ module Dependabot
53
92
  def requested_version(name)
54
93
  return unless @package_manager
55
94
 
56
- match = @package_manager.match(/#{name}@(?<version>\d+.\d+.\d+)/)
95
+ match = @package_manager.match(/^#{name}@(?<version>\d+.\d+.\d+)/)
57
96
  return unless match
58
97
 
98
+ Dependabot.logger.info("Requested version #{match['version']}")
59
99
  match["version"]
60
100
  end
61
101
 
@@ -63,8 +103,24 @@ module Dependabot
63
103
  lockfile = @lockfiles[name.to_sym]
64
104
  return unless lockfile
65
105
 
106
+ Dependabot.logger.info("Estimating version")
66
107
  Helpers.send(:"#{name}_version_numeric", lockfile)
67
108
  end
109
+
110
+ sig { params(name: T.untyped).returns(T.nilable(String)) }
111
+ def check_engine_version(name)
112
+ version_selector = VersionSelector.new
113
+ engine_versions = version_selector.setup(@package_json, name)
114
+
115
+ if engine_versions.empty?
116
+ Dependabot.logger.info("No relevant (engines) info for \"#{name}\"")
117
+ return
118
+ end
119
+
120
+ version = engine_versions[name]
121
+ Dependabot.logger.info("Returned (engines) info \"#{name}\" : \"#{version}\"")
122
+ version
123
+ end
68
124
  end
69
125
  end
70
126
  end
@@ -329,6 +329,8 @@ module Dependabot
329
329
  password: password
330
330
  }
331
331
  )
332
+ rescue URI::InvalidURIError => e
333
+ raise DependencyFileNotResolvable, e.message
332
334
  end
333
335
 
334
336
  def check_npm_response(npm_response)
@@ -90,6 +90,8 @@ module Dependabot
90
90
  Excon::Error::Socket,
91
91
  JSON::ParserError
92
92
  nil
93
+ rescue URI::InvalidURIError => e
94
+ raise DependencyFileNotResolvable, e.message
93
95
  end&.fetch("registry")
94
96
 
95
97
  @first_registry_with_dependency_details ||= global_registry.sub(%r{/+$}, "").sub(%r{^.*?//}, "")
@@ -0,0 +1,45 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require "dependabot/shared_helpers"
5
+
6
+ module Dependabot
7
+ module NpmAndYarn
8
+ class VersionSelector
9
+ extend T::Sig
10
+ extend T::Helpers
11
+
12
+ # For limited testing, allowing only specific versions defined in engines in package.json
13
+ # such as "20.8.7", "8.1.2", "8.21.2",
14
+ NODE_ENGINE_SUPPORTED_REGEX = /^\d+(?:\.\d+)*$/
15
+
16
+ sig { params(manifest_json: T::Hash[String, T.untyped], name: String).returns(T::Hash[Symbol, T.untyped]) }
17
+ def setup(manifest_json, name)
18
+ engine_versions = manifest_json["engines"]
19
+
20
+ if engine_versions.nil?
21
+ Dependabot.logger.info("No info (engines) found")
22
+ return {}
23
+ end
24
+
25
+ # logs entries for analysis purposes
26
+ log = engine_versions.select do |engine, _value|
27
+ engine.to_s.match(name)
28
+ end
29
+ Dependabot.logger.info("Found engine info #{log}") unless log.empty?
30
+
31
+ # Only keep matching specs versions i.e. "20.21.2", "7.1.2",
32
+ # Additional specs can be added later
33
+ engine_versions.delete_if { |_key, value| !valid_extracted_version?(value) }
34
+ version = engine_versions.select { |engine, _value| engine.to_s.match(name) }
35
+
36
+ version
37
+ end
38
+
39
+ sig { params(version: String).returns(T::Boolean) }
40
+ def valid_extracted_version?(version)
41
+ version.match?(NODE_ENGINE_SUPPORTED_REGEX)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -160,6 +160,11 @@ module Dependabot
160
160
  AUTH_ERROR: /YN0001:*.*Fatal Error: could not read Username for '(?<url>.*)': terminal prompts disabled/
161
161
  }.freeze, T::Hash[String, Regexp])
162
162
 
163
+ YN0001_REQ_NOT_FOUND_CODES = T.let({
164
+ REQUIREMENT_NOT_SATISFIED: /provides (?<dep>.*)(.*?)with version (?<ver>.*), which doesn't satisfy what (?<pkg>.*) requests/, # rubocop:disable Layout/LineLength
165
+ REQUIREMENT_NOT_PROVIDED: /(?<dep>.*)(.*?)doesn't provide (?<pkg>.*)(.*?), requested by (?<parent>.*)/
166
+ }.freeze, T::Hash[String, Regexp])
167
+
163
168
  class Utils
164
169
  extend T::Sig
165
170
 
@@ -212,6 +217,13 @@ module Dependabot
212
217
  return Dependabot::PrivateSourceAuthenticationFailure.new(url)
213
218
  end
214
219
  end
220
+
221
+ YN0001_REQ_NOT_FOUND_CODES.each do |(_yn0001_key, yn0001_regex)|
222
+ if (msg = message.match(yn0001_regex))
223
+ return Dependabot::DependencyFileNotResolvable.new(msg)
224
+ end
225
+ end
226
+
215
227
  Dependabot::DependabotError.new(message)
216
228
  }
217
229
  },
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.274.0
4
+ version: 0.275.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-09-05 00:00:00.000000000 Z
11
+ date: 2024-09-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.274.0
19
+ version: 0.275.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.274.0
26
+ version: 0.275.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: debug
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -340,12 +340,13 @@ files:
340
340
  - lib/dependabot/npm_and_yarn/update_checker/version_resolver.rb
341
341
  - lib/dependabot/npm_and_yarn/update_checker/vulnerability_auditor.rb
342
342
  - lib/dependabot/npm_and_yarn/version.rb
343
+ - lib/dependabot/npm_and_yarn/version_selector.rb
343
344
  homepage: https://github.com/dependabot/dependabot-core
344
345
  licenses:
345
346
  - MIT
346
347
  metadata:
347
348
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
348
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.274.0
349
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.275.0
349
350
  post_install_message:
350
351
  rdoc_options: []
351
352
  require_paths: