dependabot-npm_and_yarn 0.248.0 → 0.250.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/lib/dependabot/npm_and_yarn/dependency_files_filterer.rb +47 -19
  3. data/lib/dependabot/npm_and_yarn/file_fetcher/path_dependency_builder.rb +54 -20
  4. data/lib/dependabot/npm_and_yarn/file_fetcher.rb +105 -58
  5. data/lib/dependabot/npm_and_yarn/file_parser/json_lock.rb +20 -2
  6. data/lib/dependabot/npm_and_yarn/file_parser/lockfile_parser.rb +35 -16
  7. data/lib/dependabot/npm_and_yarn/file_parser/yarn_lock.rb +3 -2
  8. data/lib/dependabot/npm_and_yarn/file_parser.rb +94 -31
  9. data/lib/dependabot/npm_and_yarn/file_updater/npm_lockfile_updater.rb +4 -1
  10. data/lib/dependabot/npm_and_yarn/file_updater/npmrc_builder.rb +3 -1
  11. data/lib/dependabot/npm_and_yarn/file_updater/package_json_updater.rb +2 -1
  12. data/lib/dependabot/npm_and_yarn/file_updater/pnpm_lockfile_updater.rb +4 -1
  13. data/lib/dependabot/npm_and_yarn/file_updater/yarn_lockfile_updater.rb +12 -3
  14. data/lib/dependabot/npm_and_yarn/file_updater.rb +23 -6
  15. data/lib/dependabot/npm_and_yarn/helpers.rb +34 -2
  16. data/lib/dependabot/npm_and_yarn/package_name.rb +24 -7
  17. data/lib/dependabot/npm_and_yarn/registry_parser.rb +23 -11
  18. data/lib/dependabot/npm_and_yarn/sub_dependency_files_filterer.rb +21 -4
  19. data/lib/dependabot/npm_and_yarn/update_checker/conflicting_dependency_resolver.rb +2 -1
  20. data/lib/dependabot/npm_and_yarn/update_checker/dependency_files_builder.rb +3 -1
  21. data/lib/dependabot/npm_and_yarn/update_checker/latest_version_finder.rb +5 -2
  22. data/lib/dependabot/npm_and_yarn/update_checker/library_detector.rb +3 -1
  23. data/lib/dependabot/npm_and_yarn/update_checker/registry_finder.rb +5 -1
  24. data/lib/dependabot/npm_and_yarn/update_checker/requirements_updater.rb +4 -2
  25. data/lib/dependabot/npm_and_yarn/update_checker/subdependency_version_resolver.rb +6 -2
  26. data/lib/dependabot/npm_and_yarn/update_checker/version_resolver.rb +6 -2
  27. data/lib/dependabot/npm_and_yarn/update_checker/vulnerability_auditor.rb +2 -1
  28. data/lib/dependabot/npm_and_yarn/version.rb +4 -2
  29. metadata +5 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4d8c37418b227c06a52aa5052c75b0b072595db577f6d8d8b815bed1f883dc0c
4
- data.tar.gz: 96d4246790357bdc08b1d4dbbbd7a883421fe401717bd2ae43dc2093270c81f7
3
+ metadata.gz: 9720ff3635c00dcd1ea68e9f898b8e5a716f0379f19ffd345605df678f0626a2
4
+ data.tar.gz: a5a3aaa35195696fc1016dae1d6eefb374a8a4e017a3278f17162a337fe00551
5
5
  SHA512:
6
- metadata.gz: 40d06b38c0e9d6bb5ad257536af005567b6b51d632228e0e4605e7dd8850ed38922d2adfb9ac28ca8b54707e18c21a0822faf07378bb6f3e2a332e2df12968a4
7
- data.tar.gz: d8d19df3a8ea9ab1f7cb665d37db2f995c954668cb7f6b02d401dd62451e30d67e12bd0f2365ac8b58159bc48f83f8c7fd7930b79096aab827253366f7ca35ab
6
+ metadata.gz: 2accb24fcb1bcb4032641a3ff5dd8b8dcb817f1727f380dc686fa0e4f95221ad4c1c271a33b1709e70aa355ec2f4f1348e9e5c501369be49e0620ce56d1f72b9
7
+ data.tar.gz: 7e1dfeb34efcf438d6dab402fa678eca690f9631df8efbbf1cc0efdab8e95bbacff814fe714bcf614dafaf0281cbc32d97b67d0187744994991ae70de57b1d89
@@ -1,8 +1,9 @@
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/file_parser/lockfile_parser"
6
+ require "sorbet-runtime"
6
7
 
7
8
  # Used in the version resolver and file updater to only run yarn/npm helpers on
8
9
  # dependency files that require updates. This is useful for large monorepos with
@@ -10,51 +11,67 @@ require "dependabot/npm_and_yarn/file_parser/lockfile_parser"
10
11
  module Dependabot
11
12
  module NpmAndYarn
12
13
  class DependencyFilesFilterer
14
+ extend T::Sig
15
+
16
+ sig { params(dependency_files: T::Array[DependencyFile], updated_dependencies: T::Array[Dependency]).void }
13
17
  def initialize(dependency_files:, updated_dependencies:)
14
18
  @dependency_files = dependency_files
15
19
  @updated_dependencies = updated_dependencies
16
20
  end
17
21
 
22
+ sig { returns(T::Array[String]) }
18
23
  def paths_requiring_update_check
19
- @paths_requiring_update_check ||= fetch_paths_requiring_update_check
24
+ @paths_requiring_update_check ||= T.let(fetch_paths_requiring_update_check, T.nilable(T::Array[String]))
20
25
  end
21
26
 
27
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
22
28
  def files_requiring_update
23
- @files_requiring_update ||=
29
+ @files_requiring_update ||= T.let(
24
30
  dependency_files.select do |file|
25
31
  package_files_requiring_update.include?(file) ||
26
32
  package_required_lockfile?(file) ||
27
33
  workspaces_lockfile?(file)
28
- end
34
+ end, T.nilable(T::Array[DependencyFile])
35
+ )
29
36
  end
30
37
 
38
+ sig { returns(T::Array[Dependabot::DependencyFile]) }
31
39
  def package_files_requiring_update
32
- @package_files_requiring_update ||=
40
+ @package_files_requiring_update ||= T.let(
33
41
  dependency_files.select do |file|
34
42
  dependency_manifest_requirements.include?(file.name)
35
- end
43
+ end, T.nilable(T::Array[DependencyFile])
44
+ )
36
45
  end
37
46
 
38
47
  private
39
48
 
40
- attr_reader :dependency_files, :updated_dependencies
49
+ sig { returns(T::Array[DependencyFile]) }
50
+ attr_reader :dependency_files
51
+
52
+ sig { returns(T::Array[Dependency]) }
53
+ attr_reader :updated_dependencies
41
54
 
55
+ sig { returns(T::Array[String]) }
42
56
  def fetch_paths_requiring_update_check
43
57
  # if only a root lockfile exists, it tracks all dependencies
44
- return [File.dirname(root_lockfile.name)] if lockfiles == [root_lockfile]
58
+ return [File.dirname(T.must(root_lockfile).name)] if lockfiles == [root_lockfile]
45
59
 
46
60
  package_files_requiring_update.map do |file|
47
61
  File.dirname(file.name)
48
62
  end
49
63
  end
50
64
 
65
+ sig { returns(T::Array[String]) }
51
66
  def dependency_manifest_requirements
52
- @dependency_manifest_requirements ||=
67
+ @dependency_manifest_requirements ||= T.let(
53
68
  updated_dependencies.flat_map do |dep|
54
69
  dep.requirements.map { |requirement| requirement[:file] }
55
- end
70
+ end, T.nilable(T::Array[String])
71
+ )
56
72
  end
57
73
 
74
+ sig { params(lockfile: DependencyFile).returns(T::Boolean) }
58
75
  def package_required_lockfile?(lockfile)
59
76
  return false unless lockfile?(lockfile)
60
77
 
@@ -63,6 +80,7 @@ module Dependabot
63
80
  end
64
81
  end
65
82
 
83
+ sig { params(lockfile: DependencyFile).returns(T::Boolean) }
66
84
  def workspaces_lockfile?(lockfile)
67
85
  return false unless ["yarn.lock", "package-lock.json", "pnpm-lock.yaml"].include?(lockfile.name)
68
86
 
@@ -73,28 +91,35 @@ module Dependabot
73
91
  updated_dependencies_in_lockfile?(lockfile)
74
92
  end
75
93
 
94
+ sig { returns(T.nilable(DependencyFile)) }
76
95
  def root_lockfile
77
- @root_lockfile ||=
96
+ @root_lockfile ||= T.let(
78
97
  lockfiles.find do |file|
79
98
  File.dirname(file.name) == "."
80
- end
99
+ end, T.nilable(DependencyFile)
100
+ )
81
101
  end
82
102
 
103
+ sig { returns(T::Array[DependencyFile]) }
83
104
  def lockfiles
84
- @lockfiles ||=
105
+ @lockfiles ||= T.let(
85
106
  dependency_files.select do |file|
86
107
  lockfile?(file)
87
- end
108
+ end, T.nilable(T::Array[DependencyFile])
109
+ )
88
110
  end
89
111
 
112
+ sig { returns(T::Hash[String, T.untyped]) }
90
113
  def parsed_root_package_json
91
- @parsed_root_package_json ||=
114
+ @parsed_root_package_json ||= T.let(
92
115
  begin
93
- package = dependency_files.find { |f| f.name == "package.json" }
94
- JSON.parse(package.content)
95
- end
116
+ package = T.must(dependency_files.find { |f| f.name == "package.json" })
117
+ JSON.parse(T.must(package.content))
118
+ end, T.nilable(T::Hash[String, T.untyped])
119
+ )
96
120
  end
97
121
 
122
+ sig { params(lockfile: Dependabot::DependencyFile).returns(T::Boolean) }
98
123
  def updated_dependencies_in_lockfile?(lockfile)
99
124
  lockfile_dependencies(lockfile).any? do |sub_dep|
100
125
  updated_dependencies.any? do |updated_dep|
@@ -103,18 +128,21 @@ module Dependabot
103
128
  end
104
129
  end
105
130
 
131
+ sig { params(lockfile: DependencyFile).returns(T::Array[Dependency]) }
106
132
  def lockfile_dependencies(lockfile)
107
- @lockfile_dependencies ||= {}
133
+ @lockfile_dependencies ||= T.let({}, T.nilable(T::Hash[String, T::Array[Dependency]]))
108
134
  @lockfile_dependencies[lockfile.name] ||=
109
135
  NpmAndYarn::FileParser::LockfileParser.new(
110
136
  dependency_files: [lockfile]
111
137
  ).parse
112
138
  end
113
139
 
140
+ sig { params(file: DependencyFile).returns(T::Boolean) }
114
141
  def manifest?(file)
115
142
  file.name.end_with?("package.json")
116
143
  end
117
144
 
145
+ sig { params(file: DependencyFile).returns(T::Boolean) }
118
146
  def lockfile?(file)
119
147
  file.name.end_with?(
120
148
  "package-lock.json",
@@ -1,15 +1,28 @@
1
- # typed: true
1
+ # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "json"
5
5
  require "dependabot/dependency_file"
6
6
  require "dependabot/errors"
7
7
  require "dependabot/npm_and_yarn/file_fetcher"
8
+ require "sorbet-runtime"
8
9
 
9
10
  module Dependabot
10
11
  module NpmAndYarn
11
12
  class FileFetcher
12
13
  class PathDependencyBuilder
14
+ extend T::Sig
15
+
16
+ sig do
17
+ params(
18
+ dependency_name: String,
19
+ path: String,
20
+ directory: String,
21
+ package_lock: T.nilable(DependencyFile),
22
+ yarn_lock: T.nilable(DependencyFile)
23
+ )
24
+ .void
25
+ end
13
26
  def initialize(dependency_name:, path:, directory:, package_lock:,
14
27
  yarn_lock:)
15
28
  @dependency_name = dependency_name
@@ -19,6 +32,7 @@ module Dependabot
19
32
  @yarn_lock = yarn_lock
20
33
  end
21
34
 
35
+ sig { returns(DependencyFile) }
22
36
  def dependency_file
23
37
  filename = File.join(path, "package.json")
24
38
 
@@ -32,19 +46,33 @@ module Dependabot
32
46
 
33
47
  private
34
48
 
35
- attr_reader :dependency_name, :path, :package_lock, :yarn_lock,
36
- :directory
49
+ sig { returns(String) }
50
+ attr_reader :dependency_name
51
+
52
+ sig { returns(String) }
53
+ attr_reader :path
54
+
55
+ sig { returns(T.nilable(DependencyFile)) }
56
+ attr_reader :package_lock
57
+
58
+ sig { returns(T.nilable(DependencyFile)) }
59
+ attr_reader :yarn_lock
60
+
61
+ sig { returns(String) }
62
+ attr_reader :directory
37
63
 
64
+ sig { returns(T.untyped) }
38
65
  def details_from_yarn_lock
39
66
  path_starts = FileFetcher::PATH_DEPENDENCY_STARTS
40
67
  parsed_yarn_lock.to_a
41
68
  .find do |n, _|
42
69
  next false unless n.split(/(?<=\w)\@/).first == dependency_name
43
70
 
44
- n.split(/(?<=\w)\@/).last.start_with?(*path_starts)
71
+ T.must(n.split(/(?<=\w)\@/).last).start_with?(*path_starts)
45
72
  end&.last
46
73
  end
47
74
 
75
+ sig { returns(T.untyped) }
48
76
  def details_from_npm_lock
49
77
  path_starts = FileFetcher::NPM_PATH_DEPENDENCY_STARTS
50
78
  path_deps = parsed_package_lock.fetch("dependencies", []).to_a
@@ -54,6 +82,7 @@ module Dependabot
54
82
  path_deps.find { |n, _| n == dependency_name }&.last
55
83
  end
56
84
 
85
+ sig { params(dependency_name: String).returns(String) }
57
86
  def build_path_dep_content(dependency_name)
58
87
  unless details_from_yarn_lock || details_from_npm_lock
59
88
  raise Dependabot::PathDependenciesNotReachable, [dependency_name]
@@ -86,6 +115,7 @@ module Dependabot
86
115
  # relative. Worse, they may point to the user's local cache.
87
116
  # We work around this by constructing a relative path to the
88
117
  # (second-level) path dependencies.
118
+ sig { params(dependencies_hash: T.nilable(T::Hash[String, T.untyped])).returns(T.untyped) }
89
119
  def replace_yarn_lockfile_paths(dependencies_hash)
90
120
  return unless dependencies_hash
91
121
 
@@ -98,7 +128,7 @@ module Dependabot
98
128
  .find do |n, _|
99
129
  next false unless n.split(/(?<=\w)\@/).first == name
100
130
 
101
- n.split(/(?<=\w)\@/).last
131
+ T.must(n.split(/(?<=\w)\@/).last)
102
132
  .start_with?(*FileFetcher::PATH_DEPENDENCY_STARTS)
103
133
  end&.first&.split(/(?<=\w)\@/)&.last
104
134
 
@@ -110,32 +140,36 @@ module Dependabot
110
140
  end
111
141
  end
112
142
 
143
+ sig { returns(T.untyped) }
113
144
  def parsed_package_lock
114
145
  return {} unless package_lock
115
146
 
116
- JSON.parse(package_lock.content)
147
+ JSON.parse(T.must(T.must(package_lock).content))
117
148
  rescue JSON::ParserError
118
149
  {}
119
150
  end
120
151
 
152
+ sig { returns(T.nilable(T::Hash[String, T.untyped])) }
121
153
  def parsed_yarn_lock
122
- return {} unless yarn_lock
123
-
124
- @parsed_yarn_lock ||=
125
- SharedHelpers.in_a_temporary_directory do
126
- File.write("yarn.lock", yarn_lock.content)
127
-
128
- SharedHelpers.run_helper_subprocess(
129
- command: NativeHelpers.helper_path,
130
- function: "yarn:parseLockfile",
131
- args: [Dir.pwd]
132
- )
133
- rescue SharedHelpers::HelperSubprocessFailed
134
- raise Dependabot::DependencyFileNotParseable, yarn_lock.path
135
- end
154
+ return unless yarn_lock
155
+ return @parsed_yarn_lock if defined?(@parsed_yarn_lock)
156
+
157
+ parsed = T.cast(SharedHelpers.in_a_temporary_directory do
158
+ File.write("yarn.lock", T.must(yarn_lock).content)
159
+
160
+ SharedHelpers.run_helper_subprocess(
161
+ command: NativeHelpers.helper_path,
162
+ function: "yarn:parseLockfile",
163
+ args: [Dir.pwd]
164
+ )
165
+ rescue SharedHelpers::HelperSubprocessFailed
166
+ raise Dependabot::DependencyFileNotParseable, T.must(yarn_lock).path
167
+ end, T::Hash[String, T.untyped])
168
+ @parsed_yarn_lock = T.let(parsed, T.nilable(T::Hash[String, T.untyped]))
136
169
  end
137
170
 
138
171
  # The path back to the root lockfile
172
+ sig { returns(String) }
139
173
  def inverted_path
140
174
  path.split("/").map do |part|
141
175
  next part if part == "."