dependabot-npm_and_yarn 0.249.0 → 0.250.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,14 +1,22 @@
1
1
  # typed: true
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "dependabot/dependency"
5
+ require "dependabot/file_parsers"
6
+ require "dependabot/file_parsers/base"
7
+ require "sorbet-runtime"
8
+
4
9
  module Dependabot
5
10
  module NpmAndYarn
6
11
  module Helpers
12
+ extend T::Sig
13
+
7
14
  YARN_PATH_NOT_FOUND =
8
15
  /^.*(?<error>The "yarn-path" option has been set \(in [^)]+\), but the specified location doesn't exist)/
9
16
 
17
+ sig { params(lockfile: DependencyFile).returns(Integer) }
10
18
  def self.npm_version_numeric(lockfile)
11
- lockfile_content = lockfile.content
19
+ lockfile_content = T.must(lockfile.content)
12
20
  return 8 if JSON.parse(lockfile_content)["lockfileVersion"].to_i >= 2
13
21
 
14
22
  6
@@ -16,6 +24,7 @@ module Dependabot
16
24
  6
17
25
  end
18
26
 
27
+ sig { params(yarn_lock: DependencyFile).returns(Integer) }
19
28
  def self.yarn_version_numeric(yarn_lock)
20
29
  if yarn_berry?(yarn_lock)
21
30
  3
@@ -26,6 +35,8 @@ module Dependabot
26
35
 
27
36
  # Mapping from lockfile versions to PNPM versions is at
28
37
  # https://github.com/pnpm/spec/tree/274ff02de23376ad59773a9f25ecfedd03a41f64/lockfile, but simplify it for now.
38
+
39
+ sig { params(pnpm_lock: DependencyFile).returns(Integer) }
29
40
  def self.pnpm_version_numeric(pnpm_lock)
30
41
  if pnpm_lockfile_version(pnpm_lock).to_f >= 6.0
31
42
  8
@@ -44,19 +55,24 @@ module Dependabot
44
55
  end
45
56
  end
46
57
 
58
+ sig { params(package_lock: T.nilable(DependencyFile)).returns(T::Boolean) }
47
59
  def self.npm8?(package_lock)
48
60
  return true unless package_lock
49
61
 
50
62
  npm_version_numeric(package_lock) == 8
51
63
  end
52
64
 
65
+ sig { params(yarn_lock: T.nilable(DependencyFile)).returns(T::Boolean) }
53
66
  def self.yarn_berry?(yarn_lock)
54
- yaml = YAML.safe_load(yarn_lock.content)
67
+ return false if yarn_lock.nil? || yarn_lock.content.nil?
68
+
69
+ yaml = YAML.safe_load(T.must(yarn_lock.content))
55
70
  yaml.key?("__metadata")
56
71
  rescue StandardError
57
72
  false
58
73
  end
59
74
 
75
+ sig { returns(Integer) }
60
76
  def self.yarn_major_version
61
77
  retries = 0
62
78
  output = run_single_yarn_command("--version")
@@ -96,15 +112,18 @@ module Dependabot
96
112
  raise
97
113
  end
98
114
 
115
+ sig { returns(T::Boolean) }
99
116
  def self.yarn_zero_install?
100
117
  File.exist?(".pnp.cjs")
101
118
  end
102
119
 
120
+ sig { returns(T::Boolean) }
103
121
  def self.yarn_offline_cache?
104
122
  yarn_cache_dir = fetch_yarnrc_yml_value("cacheFolder", ".yarn/cache")
105
123
  File.exist?(yarn_cache_dir) && (fetch_yarnrc_yml_value("nodeLinker", "") == "node-modules")
106
124
  end
107
125
 
126
+ sig { returns(String) }
108
127
  def self.yarn_berry_args
109
128
  if yarn_major_version == 2
110
129
  ""
@@ -117,14 +136,17 @@ module Dependabot
117
136
  end
118
137
  end
119
138
 
139
+ sig { returns(T::Boolean) }
120
140
  def self.yarn_berry_skip_build?
121
141
  yarn_major_version >= 3 && (yarn_zero_install? || yarn_offline_cache?)
122
142
  end
123
143
 
144
+ sig { returns(T::Boolean) }
124
145
  def self.yarn_berry_disable_scripts?
125
146
  yarn_major_version == 2 || !yarn_zero_install?
126
147
  end
127
148
 
149
+ sig { returns(T::Boolean) }
128
150
  def self.yarn_4_or_higher?
129
151
  yarn_major_version >= 4
130
152
  end
@@ -190,6 +212,7 @@ module Dependabot
190
212
  pnpm_lock.content.match(/^lockfileVersion: ['"]?(?<version>[\d.]+)/)[:version]
191
213
  end
192
214
 
215
+ sig { params(dependency_set: Dependabot::FileParsers::Base::DependencySet).returns(T::Array[Dependency]) }
193
216
  def self.dependencies_with_all_versions_metadata(dependency_set)
194
217
  dependency_set.dependencies.map do |dependency|
195
218
  dependency.metadata[:all_versions] = dependency_set.all_versions_for_name(dependency.name)
@@ -1,9 +1,13 @@
1
- # typed: false
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "sorbet-runtime"
5
+
4
6
  module Dependabot
5
7
  module NpmAndYarn
6
8
  class PackageName
9
+ extend T::Sig
10
+
7
11
  # NPM package naming rules are defined by the following projects:
8
12
  # - https://github.com/npm/npm-user-validate
9
13
  # - https://github.com/npm/validate-npm-package-name
@@ -31,14 +35,16 @@ module Dependabot
31
35
 
32
36
  class InvalidPackageName < StandardError; end
33
37
 
38
+ sig { params(string: String).void }
34
39
  def initialize(string)
35
40
  match = PACKAGE_NAME_REGEX.match(string.to_s)
36
41
  raise InvalidPackageName unless match
37
42
 
38
- @scope = match[:scope]
39
- @name = match[:name]
43
+ @scope = T.let(match[:scope], T.nilable(String))
44
+ @name = T.let(match[:name], T.nilable(String))
40
45
  end
41
46
 
47
+ sig { returns(String) }
42
48
  def to_s
43
49
  if scoped?
44
50
  "@#{@scope}/#{@name}"
@@ -47,49 +53,60 @@ module Dependabot
47
53
  end
48
54
  end
49
55
 
56
+ sig { params(other: PackageName).returns(T::Boolean) }
50
57
  def eql?(other)
51
58
  self.class == other.class && to_s == other.to_s
52
59
  end
53
60
 
61
+ sig { returns(Integer) }
54
62
  def hash
55
63
  to_s.downcase.hash
56
64
  end
57
65
 
66
+ sig { params(other: PackageName).returns(T.nilable(Integer)) }
58
67
  def <=>(other)
59
68
  to_s.casecmp(other.to_s)
60
69
  end
61
70
 
71
+ sig { returns(T.nilable(PackageName)) }
62
72
  def library_name
63
73
  return unless types_package?
74
+ return @library_name if defined?(@library_name)
64
75
 
65
- @library_name ||=
76
+ lib_name =
66
77
  begin
67
- match = TYPES_PACKAGE_NAME_REGEX.match(to_s)
78
+ match = T.must(TYPES_PACKAGE_NAME_REGEX.match(to_s))
68
79
  if match[:scope]
69
80
  self.class.new("@#{match[:scope]}/#{match[:name]}")
70
81
  else
71
82
  self.class.new(match[:name].to_s)
72
83
  end
73
84
  end
85
+
86
+ @library_name ||= T.let(lib_name, T.nilable(PackageName))
74
87
  end
75
88
 
89
+ sig { returns(T.nilable(PackageName)) }
76
90
  def types_package_name
77
91
  return if types_package?
78
92
 
79
- @types_package_name ||=
93
+ @types_package_name ||= T.let(
80
94
  if scoped?
81
95
  self.class.new("@types/#{@scope}__#{@name}")
82
96
  else
83
97
  self.class.new("@types/#{@name}")
84
- end
98
+ end, T.nilable(PackageName)
99
+ )
85
100
  end
86
101
 
87
102
  private
88
103
 
104
+ sig { returns(T::Boolean) }
89
105
  def scoped?
90
106
  !@scope.nil?
91
107
  end
92
108
 
109
+ sig { returns(T.nilable(T::Boolean)) }
93
110
  def types_package?
94
111
  "types".casecmp?(@scope)
95
112
  end
@@ -1,14 +1,20 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "sorbet-runtime"
5
+
4
6
  module Dependabot
5
7
  module NpmAndYarn
6
8
  class RegistryParser
9
+ extend T::Sig
10
+
11
+ sig { params(resolved_url: String, credentials: T::Array[Dependabot::Credential]).void }
7
12
  def initialize(resolved_url:, credentials:)
8
13
  @resolved_url = resolved_url
9
14
  @credentials = credentials
10
15
  end
11
16
 
17
+ sig { params(name: String).returns(T::Hash[Symbol, T.untyped]) }
12
18
  def registry_source_for(name)
13
19
  url =
14
20
  if resolved_url.include?("/~/")
@@ -16,8 +22,8 @@ module Dependabot
16
22
  resolved_url.split("/~/").first
17
23
  elsif resolved_url.include?("/#{name}/-/#{name}")
18
24
  # MyGet / Bintray format
19
- resolved_url.split("/#{name}/-/#{name}").first
20
- .gsub("dl.bintray.com//", "api.bintray.com/npm/").
25
+ T.must(resolved_url.split("/#{name}/-/#{name}").first)
26
+ .gsub("dl.bintray.com//", "api.bintray.com/npm/").
21
27
  # GitLab format
22
28
  gsub(%r{\/projects\/\d+}, "")
23
29
  elsif resolved_url.include?("/#{name}/-/#{name.split('/').last}")
@@ -25,51 +31,56 @@ module Dependabot
25
31
  resolved_url.split("/#{name}/-/#{name.split('/').last}").first
26
32
  elsif (cred_url = url_for_relevant_cred) then cred_url
27
33
  else
28
- resolved_url.split("/")[0..2].join("/")
34
+ T.must(resolved_url.split("/")[0..2]).join("/")
29
35
  end
30
36
 
31
37
  { type: "registry", url: url }
32
38
  end
33
39
 
40
+ sig { returns(String) }
34
41
  def dependency_name
35
42
  url_base = if resolved_url.include?("/-/")
36
- resolved_url.split("/-/").first
43
+ T.must(resolved_url.split("/-/").first)
37
44
  else
38
45
  resolved_url
39
46
  end
40
47
 
41
- url_base[/@.*/].gsub("%2F", "/").split("/")[0..1].join("/")
48
+ T.must(T.must(url_base[/@.*/]).gsub("%2F", "/").split("/")[0..1]).join("/")
42
49
  end
43
50
 
44
51
  private
45
52
 
53
+ sig { returns(String) }
46
54
  attr_reader :resolved_url
55
+
56
+ sig { returns(T::Array[Dependabot::Credential]) }
47
57
  attr_reader :credentials
48
58
 
49
59
  # rubocop:disable Metrics/PerceivedComplexity
60
+ sig { returns(T.nilable(String)) }
50
61
  def url_for_relevant_cred
51
62
  resolved_url_host = URI(resolved_url).host
52
63
 
53
64
  credential_matching_url =
54
65
  credentials
55
66
  .select { |cred| cred["type"] == "npm_registry" && cred["registry"] }
56
- .sort_by { |cred| cred["registry"].length }
67
+ .sort_by { |cred| cred.fetch("registry").length }
57
68
  .find do |details|
58
69
  next true if resolved_url_host == details["registry"]
59
70
 
60
71
  uri = if details["registry"]&.include?("://")
61
- URI(details["registry"])
72
+ URI(details.fetch("registry"))
62
73
  else
63
74
  URI("https://#{details['registry']}")
64
75
  end
65
- resolved_url_host == uri.host && resolved_url.include?(details["registry"])
76
+ resolved_url_host == uri.host && resolved_url.include?(details.fetch("registry"))
66
77
  end
67
78
 
68
79
  return unless credential_matching_url
69
80
 
70
81
  # Trim the resolved URL so that it ends at the same point as the
71
82
  # credential registry
72
- reg = credential_matching_url["registry"]
83
+ reg = credential_matching_url.fetch("registry")
73
84
  resolved_url.gsub(/#{Regexp.quote(reg)}.*/, "") + reg
74
85
  end
75
86
  # rubocop:enable Metrics/PerceivedComplexity
@@ -1,9 +1,10 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/utils"
5
5
  require "dependabot/npm_and_yarn/version"
6
6
  require "dependabot/npm_and_yarn/file_parser/lockfile_parser"
7
+ require "sorbet-runtime"
7
8
 
8
9
  # Used in the sub dependency version resolver and file updater to only run
9
10
  # yarn/npm helpers on dependency files that require updates. This is useful for
@@ -12,13 +13,19 @@ require "dependabot/npm_and_yarn/file_parser/lockfile_parser"
12
13
  module Dependabot
13
14
  module NpmAndYarn
14
15
  class SubDependencyFilesFilterer
16
+ extend T::Sig
17
+
18
+ sig { params(dependency_files: T::Array[DependencyFile], updated_dependencies: T::Array[Dependency]).void }
15
19
  def initialize(dependency_files:, updated_dependencies:)
16
20
  @dependency_files = dependency_files
17
21
  @updated_dependencies = updated_dependencies
18
22
  end
19
23
 
24
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
20
25
  def files_requiring_update
21
- @files_requiring_update ||=
26
+ return T.must(@files_requiring_update) if defined? @files_requiring_update
27
+
28
+ files_requiring_update =
22
29
  lockfiles.select do |lockfile|
23
30
  lockfile_dependencies(lockfile).any? do |sub_dep|
24
31
  updated_dependencies.any? do |updated_dep|
@@ -29,25 +36,33 @@ module Dependabot
29
36
  end
30
37
  end
31
38
  end
39
+
40
+ @files_requiring_update ||= T.let(files_requiring_update, T.nilable(T::Array[DependencyFile]))
32
41
  end
33
42
 
34
43
  private
35
44
 
45
+ sig { returns(T::Array[DependencyFile]) }
36
46
  attr_reader :dependency_files
47
+
48
+ sig { returns(T::Array[Dependency]) }
37
49
  attr_reader :updated_dependencies
38
50
 
51
+ sig { params(lockfile: DependencyFile).returns(T::Array[Dependabot::Dependency]) }
39
52
  def lockfile_dependencies(lockfile)
40
- @lockfile_dependencies ||= {}
53
+ @lockfile_dependencies ||= T.let({}, T.nilable(T::Hash[String, T::Array[Dependency]]))
41
54
  @lockfile_dependencies[lockfile.name] ||=
42
55
  NpmAndYarn::FileParser::LockfileParser.new(
43
56
  dependency_files: [lockfile]
44
57
  ).parse
45
58
  end
46
59
 
60
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
47
61
  def lockfiles
48
62
  dependency_files.select { |file| lockfile?(file) }
49
63
  end
50
64
 
65
+ sig { params(file: DependencyFile).returns(T::Boolean) }
51
66
  def lockfile?(file)
52
67
  file.name.end_with?(
53
68
  "package-lock.json",
@@ -57,6 +72,7 @@ module Dependabot
57
72
  )
58
73
  end
59
74
 
75
+ sig { returns(T.class_of(Dependabot::NpmAndYarn::Version)) }
60
76
  def version_class
61
77
  NpmAndYarn::Version
62
78
  end
@@ -1,8 +1,9 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "dependabot/version"
5
5
  require "dependabot/utils"
6
+ require "sorbet-runtime"
6
7
 
7
8
  # JavaScript pre-release versions use 1.0.1-rc1 syntax, which Gem::Version
8
9
  # converts into 1.0.1.pre.rc1. We override the `to_s` method to stop that
@@ -15,7 +16,7 @@ module Dependabot
15
16
  class Version < Dependabot::Version
16
17
  extend T::Sig
17
18
 
18
- sig { returns(String) }
19
+ sig { returns(T.nilable(String)) }
19
20
  attr_reader :build_info
20
21
 
21
22
  VERSION_PATTERN = T.let(Gem::Version::VERSION_PATTERN + '(\+[0-9a-zA-Z\-.]+)?', String)
@@ -46,6 +47,7 @@ module Dependabot
46
47
  def initialize(version)
47
48
  @version_string = T.let(version.to_s, String)
48
49
  version = version.gsub(/^v/, "") if version.is_a?(String)
50
+ @build_info = T.let(nil, T.nilable(String))
49
51
 
50
52
  version, @build_info = version.to_s.split("+") if version.to_s.include?("+")
51
53
 
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.249.0
4
+ version: 0.250.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-03-28 00:00:00.000000000 Z
11
+ date: 2024-04-02 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.249.0
19
+ version: 0.250.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.249.0
26
+ version: 0.250.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: debug
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -338,7 +338,7 @@ licenses:
338
338
  - Nonstandard
339
339
  metadata:
340
340
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
341
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.249.0
341
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.250.0
342
342
  post_install_message:
343
343
  rdoc_options: []
344
344
  require_paths: