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.
- checksums.yaml +4 -4
- data/lib/dependabot/npm_and_yarn/dependency_files_filterer.rb +45 -18
- data/lib/dependabot/npm_and_yarn/file_fetcher/path_dependency_builder.rb +49 -18
- data/lib/dependabot/npm_and_yarn/file_fetcher.rb +105 -58
- data/lib/dependabot/npm_and_yarn/file_parser/json_lock.rb +20 -2
- data/lib/dependabot/npm_and_yarn/file_parser/lockfile_parser.rb +35 -16
- data/lib/dependabot/npm_and_yarn/file_parser/yarn_lock.rb +3 -2
- data/lib/dependabot/npm_and_yarn/file_parser.rb +94 -31
- data/lib/dependabot/npm_and_yarn/file_updater.rb +23 -6
- data/lib/dependabot/npm_and_yarn/helpers.rb +25 -2
- data/lib/dependabot/npm_and_yarn/package_name.rb +24 -7
- data/lib/dependabot/npm_and_yarn/registry_parser.rb +21 -10
- data/lib/dependabot/npm_and_yarn/sub_dependency_files_filterer.rb +19 -3
- data/lib/dependabot/npm_and_yarn/version.rb +4 -2
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9720ff3635c00dcd1ea68e9f898b8e5a716f0379f19ffd345605df678f0626a2
|
4
|
+
data.tar.gz: a5a3aaa35195696fc1016dae1d6eefb374a8a4e017a3278f17162a337fe00551
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2accb24fcb1bcb4032641a3ff5dd8b8dcb817f1727f380dc686fa0e4f95221ad4c1c271a33b1709e70aa355ec2f4f1348e9e5c501369be49e0620ce56d1f72b9
|
7
|
+
data.tar.gz: 7e1dfeb34efcf438d6dab402fa678eca690f9631df8efbbf1cc0efdab8e95bbacff814fe714bcf614dafaf0281cbc32d97b67d0187744994991ae70de57b1d89
|
@@ -1,8 +1,9 @@
|
|
1
|
-
# typed:
|
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,52 +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
|
|
49
|
+
sig { returns(T::Array[DependencyFile]) }
|
40
50
|
attr_reader :dependency_files
|
51
|
+
|
52
|
+
sig { returns(T::Array[Dependency]) }
|
41
53
|
attr_reader :updated_dependencies
|
42
54
|
|
55
|
+
sig { returns(T::Array[String]) }
|
43
56
|
def fetch_paths_requiring_update_check
|
44
57
|
# if only a root lockfile exists, it tracks all dependencies
|
45
|
-
return [File.dirname(root_lockfile.name)] if lockfiles == [root_lockfile]
|
58
|
+
return [File.dirname(T.must(root_lockfile).name)] if lockfiles == [root_lockfile]
|
46
59
|
|
47
60
|
package_files_requiring_update.map do |file|
|
48
61
|
File.dirname(file.name)
|
49
62
|
end
|
50
63
|
end
|
51
64
|
|
65
|
+
sig { returns(T::Array[String]) }
|
52
66
|
def dependency_manifest_requirements
|
53
|
-
@dependency_manifest_requirements ||=
|
67
|
+
@dependency_manifest_requirements ||= T.let(
|
54
68
|
updated_dependencies.flat_map do |dep|
|
55
69
|
dep.requirements.map { |requirement| requirement[:file] }
|
56
|
-
end
|
70
|
+
end, T.nilable(T::Array[String])
|
71
|
+
)
|
57
72
|
end
|
58
73
|
|
74
|
+
sig { params(lockfile: DependencyFile).returns(T::Boolean) }
|
59
75
|
def package_required_lockfile?(lockfile)
|
60
76
|
return false unless lockfile?(lockfile)
|
61
77
|
|
@@ -64,6 +80,7 @@ module Dependabot
|
|
64
80
|
end
|
65
81
|
end
|
66
82
|
|
83
|
+
sig { params(lockfile: DependencyFile).returns(T::Boolean) }
|
67
84
|
def workspaces_lockfile?(lockfile)
|
68
85
|
return false unless ["yarn.lock", "package-lock.json", "pnpm-lock.yaml"].include?(lockfile.name)
|
69
86
|
|
@@ -74,28 +91,35 @@ module Dependabot
|
|
74
91
|
updated_dependencies_in_lockfile?(lockfile)
|
75
92
|
end
|
76
93
|
|
94
|
+
sig { returns(T.nilable(DependencyFile)) }
|
77
95
|
def root_lockfile
|
78
|
-
@root_lockfile ||=
|
96
|
+
@root_lockfile ||= T.let(
|
79
97
|
lockfiles.find do |file|
|
80
98
|
File.dirname(file.name) == "."
|
81
|
-
end
|
99
|
+
end, T.nilable(DependencyFile)
|
100
|
+
)
|
82
101
|
end
|
83
102
|
|
103
|
+
sig { returns(T::Array[DependencyFile]) }
|
84
104
|
def lockfiles
|
85
|
-
@lockfiles ||=
|
105
|
+
@lockfiles ||= T.let(
|
86
106
|
dependency_files.select do |file|
|
87
107
|
lockfile?(file)
|
88
|
-
end
|
108
|
+
end, T.nilable(T::Array[DependencyFile])
|
109
|
+
)
|
89
110
|
end
|
90
111
|
|
112
|
+
sig { returns(T::Hash[String, T.untyped]) }
|
91
113
|
def parsed_root_package_json
|
92
|
-
@parsed_root_package_json ||=
|
114
|
+
@parsed_root_package_json ||= T.let(
|
93
115
|
begin
|
94
|
-
package = dependency_files.find { |f| f.name == "package.json" }
|
95
|
-
JSON.parse(package.content)
|
96
|
-
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
|
+
)
|
97
120
|
end
|
98
121
|
|
122
|
+
sig { params(lockfile: Dependabot::DependencyFile).returns(T::Boolean) }
|
99
123
|
def updated_dependencies_in_lockfile?(lockfile)
|
100
124
|
lockfile_dependencies(lockfile).any? do |sub_dep|
|
101
125
|
updated_dependencies.any? do |updated_dep|
|
@@ -104,18 +128,21 @@ module Dependabot
|
|
104
128
|
end
|
105
129
|
end
|
106
130
|
|
131
|
+
sig { params(lockfile: DependencyFile).returns(T::Array[Dependency]) }
|
107
132
|
def lockfile_dependencies(lockfile)
|
108
|
-
@lockfile_dependencies ||= {}
|
133
|
+
@lockfile_dependencies ||= T.let({}, T.nilable(T::Hash[String, T::Array[Dependency]]))
|
109
134
|
@lockfile_dependencies[lockfile.name] ||=
|
110
135
|
NpmAndYarn::FileParser::LockfileParser.new(
|
111
136
|
dependency_files: [lockfile]
|
112
137
|
).parse
|
113
138
|
end
|
114
139
|
|
140
|
+
sig { params(file: DependencyFile).returns(T::Boolean) }
|
115
141
|
def manifest?(file)
|
116
142
|
file.name.end_with?("package.json")
|
117
143
|
end
|
118
144
|
|
145
|
+
sig { params(file: DependencyFile).returns(T::Boolean) }
|
119
146
|
def lockfile?(file)
|
120
147
|
file.name.end_with?(
|
121
148
|
"package-lock.json",
|
@@ -1,15 +1,28 @@
|
|
1
|
-
# typed:
|
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,22 +46,33 @@ module Dependabot
|
|
32
46
|
|
33
47
|
private
|
34
48
|
|
49
|
+
sig { returns(String) }
|
35
50
|
attr_reader :dependency_name
|
51
|
+
|
52
|
+
sig { returns(String) }
|
36
53
|
attr_reader :path
|
54
|
+
|
55
|
+
sig { returns(T.nilable(DependencyFile)) }
|
37
56
|
attr_reader :package_lock
|
57
|
+
|
58
|
+
sig { returns(T.nilable(DependencyFile)) }
|
38
59
|
attr_reader :yarn_lock
|
60
|
+
|
61
|
+
sig { returns(String) }
|
39
62
|
attr_reader :directory
|
40
63
|
|
64
|
+
sig { returns(T.untyped) }
|
41
65
|
def details_from_yarn_lock
|
42
66
|
path_starts = FileFetcher::PATH_DEPENDENCY_STARTS
|
43
67
|
parsed_yarn_lock.to_a
|
44
68
|
.find do |n, _|
|
45
69
|
next false unless n.split(/(?<=\w)\@/).first == dependency_name
|
46
70
|
|
47
|
-
n.split(/(?<=\w)\@/).last.start_with?(*path_starts)
|
71
|
+
T.must(n.split(/(?<=\w)\@/).last).start_with?(*path_starts)
|
48
72
|
end&.last
|
49
73
|
end
|
50
74
|
|
75
|
+
sig { returns(T.untyped) }
|
51
76
|
def details_from_npm_lock
|
52
77
|
path_starts = FileFetcher::NPM_PATH_DEPENDENCY_STARTS
|
53
78
|
path_deps = parsed_package_lock.fetch("dependencies", []).to_a
|
@@ -57,6 +82,7 @@ module Dependabot
|
|
57
82
|
path_deps.find { |n, _| n == dependency_name }&.last
|
58
83
|
end
|
59
84
|
|
85
|
+
sig { params(dependency_name: String).returns(String) }
|
60
86
|
def build_path_dep_content(dependency_name)
|
61
87
|
unless details_from_yarn_lock || details_from_npm_lock
|
62
88
|
raise Dependabot::PathDependenciesNotReachable, [dependency_name]
|
@@ -89,6 +115,7 @@ module Dependabot
|
|
89
115
|
# relative. Worse, they may point to the user's local cache.
|
90
116
|
# We work around this by constructing a relative path to the
|
91
117
|
# (second-level) path dependencies.
|
118
|
+
sig { params(dependencies_hash: T.nilable(T::Hash[String, T.untyped])).returns(T.untyped) }
|
92
119
|
def replace_yarn_lockfile_paths(dependencies_hash)
|
93
120
|
return unless dependencies_hash
|
94
121
|
|
@@ -101,7 +128,7 @@ module Dependabot
|
|
101
128
|
.find do |n, _|
|
102
129
|
next false unless n.split(/(?<=\w)\@/).first == name
|
103
130
|
|
104
|
-
n.split(/(?<=\w)\@/).last
|
131
|
+
T.must(n.split(/(?<=\w)\@/).last)
|
105
132
|
.start_with?(*FileFetcher::PATH_DEPENDENCY_STARTS)
|
106
133
|
end&.first&.split(/(?<=\w)\@/)&.last
|
107
134
|
|
@@ -113,32 +140,36 @@ module Dependabot
|
|
113
140
|
end
|
114
141
|
end
|
115
142
|
|
143
|
+
sig { returns(T.untyped) }
|
116
144
|
def parsed_package_lock
|
117
145
|
return {} unless package_lock
|
118
146
|
|
119
|
-
JSON.parse(package_lock.content)
|
147
|
+
JSON.parse(T.must(T.must(package_lock).content))
|
120
148
|
rescue JSON::ParserError
|
121
149
|
{}
|
122
150
|
end
|
123
151
|
|
152
|
+
sig { returns(T.nilable(T::Hash[String, T.untyped])) }
|
124
153
|
def parsed_yarn_lock
|
125
|
-
return
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
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]))
|
139
169
|
end
|
140
170
|
|
141
171
|
# The path back to the root lockfile
|
172
|
+
sig { returns(String) }
|
142
173
|
def inverted_path
|
143
174
|
path.split("/").map do |part|
|
144
175
|
next part if part == "."
|