dependabot-bun 0.401.0 → 0.402.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/dependabot/bun/file_updater/bun_lockfile_updater.rb +159 -9
- data/lib/dependabot/bun/helpers.rb +8 -6
- data/lib/dependabot/bun/metadata_finder.rb +17 -10
- data/lib/dependabot/bun/package/registry_finder.rb +1 -1
- data/lib/dependabot/bun/update_checker/version_resolver.rb +111 -4
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e4c9217ef3c6884ac153b6bb6e516709f0440e6d70a2c25e4f795aaf443adb47
|
|
4
|
+
data.tar.gz: 25430e72661535db6c374dee825b3dcac942f37e98853e47750061f326253602
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 97eda92117fac8f2ebeb5883f865cff280b089d8430127b0dbb4da826f2ff24ddf11949181b45ca9f320a23ed3b8f8b4fbf5d2660946a5255f646b115dad5b76
|
|
7
|
+
data.tar.gz: 9b729c7238e1f784a09500789c26c4eec54c8afe891619600312345a7902cb15feb3ae0230e56744435876b963e4dc054f06eec94974353ef4d696f7642887c8
|
|
@@ -6,6 +6,7 @@ require "sorbet-runtime"
|
|
|
6
6
|
require "dependabot/bun/helpers"
|
|
7
7
|
require "dependabot/bun/package/registry_finder"
|
|
8
8
|
require "dependabot/bun/registry_parser"
|
|
9
|
+
require "dependabot/package/npm_package_json"
|
|
9
10
|
require "dependabot/shared_helpers"
|
|
10
11
|
|
|
11
12
|
module Dependabot
|
|
@@ -69,6 +70,24 @@ module Dependabot
|
|
|
69
70
|
T::Hash[Regexp, Dependabot::DependabotError]
|
|
70
71
|
)
|
|
71
72
|
|
|
73
|
+
# A registry rejected the request for a package or its tarball. bun prints
|
|
74
|
+
# `error: failed to download <name>@<version>: <status> <reason>` with the tarball URL on the next line, or
|
|
75
|
+
# `error: GET <url> - <status>` when the request for the package metadata fails.
|
|
76
|
+
DOWNLOAD_FAILED =
|
|
77
|
+
%r{error: failed to download (?<spec>\S+): (?<status>\d{3})[^\n]*(?:\n[[:space:]]*(?<url>https?://\S+))?}
|
|
78
|
+
REQUEST_FAILED = %r{error: GET (?<url>https?://\S+) - (?<status>\d{3})\b}
|
|
79
|
+
ACCESS_DENIED_STATUSES = %w(401 403).freeze
|
|
80
|
+
NOT_FOUND_STATUS = "404"
|
|
81
|
+
|
|
82
|
+
# A workspace that bun.lock or package.json refers to is not part of the checkout
|
|
83
|
+
WORKSPACE_NOT_ON_DISK =
|
|
84
|
+
/
|
|
85
|
+
error:\s(?:the\sroot\spackage|workspace\s"[^"]+")\s
|
|
86
|
+
depends\son\sworkspace\s"(?<name>[^"]+)"\s\((?<path>[^)]*)\),\s
|
|
87
|
+
which\sis\slisted\sin\sbun\.lock\sbut\snot\son\sdisk
|
|
88
|
+
/x
|
|
89
|
+
WORKSPACE_NOT_FOUND = /error: Workspace not found "(?<path>[^"]+)"/
|
|
90
|
+
|
|
72
91
|
sig { params(bun_lock: Dependabot::DependencyFile).returns(String) }
|
|
73
92
|
def run_bun_update(bun_lock:)
|
|
74
93
|
SharedHelpers.in_a_temporary_repo_directory(base_dir, repo_contents_path) do
|
|
@@ -88,14 +107,83 @@ module Dependabot
|
|
|
88
107
|
|
|
89
108
|
sig { void }
|
|
90
109
|
def run_bun_updater
|
|
91
|
-
|
|
92
|
-
"#{d.name}@#{d.version}"
|
|
93
|
-
end.join(" ")
|
|
110
|
+
dependency_updates_by_target.each do |workspace_name, deps|
|
|
111
|
+
dependency_updates = deps.map { |d| "#{d.name}@#{d.version}" }
|
|
94
112
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
113
|
+
command = T.let(["install", *dependency_updates], T::Array[String])
|
|
114
|
+
command += ["--filter", workspace_name] if workspace_name
|
|
115
|
+
command += ["--save-text-lockfile", "--ignore-scripts"]
|
|
116
|
+
|
|
117
|
+
Helpers.run_bun_command(
|
|
118
|
+
command,
|
|
119
|
+
fingerprint: "install <dependency_updates> --save-text-lockfile --ignore-scripts"
|
|
120
|
+
)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Maps each install target (nil for the repo root, or a workspace
|
|
125
|
+
# path) to the dependencies that need installing there. A dependency
|
|
126
|
+
# declared in multiple manifests must be installed in each one, since
|
|
127
|
+
# Bun merges same-name declarations into a single Dependency.
|
|
128
|
+
sig { returns(T::Hash[T.nilable(String), T::Array[Dependabot::Dependency]]) }
|
|
129
|
+
def dependency_updates_by_target
|
|
130
|
+
dependencies
|
|
131
|
+
.flat_map { |dependency| install_targets_for(dependency).map { |target| [target, dependency] } }
|
|
132
|
+
.group_by { |target, _dependency| target }
|
|
133
|
+
.transform_values { |pairs| pairs.map { |_target, dependency| dependency } }
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Returns every install target (nil for the repo root, or a workspace
|
|
137
|
+
# path) that declares +dependency+. Falls back to an unfiltered root
|
|
138
|
+
# install if it isn't declared anywhere (e.g. a sub-dependency).
|
|
139
|
+
sig { params(dependency: Dependabot::Dependency).returns(T::Array[T.nilable(String)]) }
|
|
140
|
+
def install_targets_for(dependency)
|
|
141
|
+
root = root_package_json
|
|
142
|
+
|
|
143
|
+
workspace_targets = package_files.filter_map do |file|
|
|
144
|
+
next if file == root
|
|
145
|
+
next unless package_json_declares?(file, dependency)
|
|
146
|
+
|
|
147
|
+
workspace_filter(file)
|
|
148
|
+
end.uniq
|
|
149
|
+
|
|
150
|
+
declared_at_root = !root || package_json_declares?(root, dependency)
|
|
151
|
+
return workspace_targets if !declared_at_root && workspace_targets.any?
|
|
152
|
+
|
|
153
|
+
[nil, *workspace_targets]
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Path-based --filter target for the workspace at +file+ (e.g.
|
|
157
|
+
# "./packages/app"). Bun's --filter also accepts a package's declared
|
|
158
|
+
# "name", but names can contain glob metacharacters that would match
|
|
159
|
+
# unrelated workspaces, so a path is used instead.
|
|
160
|
+
sig { params(file: Dependabot::DependencyFile).returns(String) }
|
|
161
|
+
def workspace_filter(file)
|
|
162
|
+
unless Dependabot::Package::NpmPackageJson.from_file(file).name
|
|
163
|
+
raise Dependabot::DependencyFileNotParseable.new(
|
|
164
|
+
file.path,
|
|
165
|
+
"#{file.name} must declare a \"name\" to be targeted for a workspace-scoped update"
|
|
166
|
+
)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
"./#{File.dirname(file.name)}"
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
sig do
|
|
173
|
+
params(package_json_file: Dependabot::DependencyFile, dependency: Dependabot::Dependency)
|
|
174
|
+
.returns(T::Boolean)
|
|
175
|
+
end
|
|
176
|
+
def package_json_declares?(package_json_file, dependency)
|
|
177
|
+
declared = T.let(false, T::Boolean)
|
|
178
|
+
Dependabot::Package::NpmPackageJson.from_file(package_json_file).each_dependency do |name, _req, _type|
|
|
179
|
+
declared ||= name == dependency.name
|
|
180
|
+
end
|
|
181
|
+
declared
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
sig { returns(T.nilable(Dependabot::DependencyFile)) }
|
|
185
|
+
def root_package_json
|
|
186
|
+
package_files.find { |f| f.name == "package.json" }
|
|
99
187
|
end
|
|
100
188
|
|
|
101
189
|
sig { void }
|
|
@@ -116,10 +204,13 @@ module Dependabot
|
|
|
116
204
|
).parse
|
|
117
205
|
end
|
|
118
206
|
|
|
119
|
-
sig { params(error: Dependabot::DependabotError,
|
|
120
|
-
def handle_bun_lock_updater_error(error,
|
|
207
|
+
sig { params(error: Dependabot::DependabotError, bun_lock: Dependabot::DependencyFile).returns(T.noreturn) }
|
|
208
|
+
def handle_bun_lock_updater_error(error, bun_lock)
|
|
121
209
|
error_message = error.message
|
|
122
210
|
|
|
211
|
+
raise_registry_error(error_message)
|
|
212
|
+
raise_workspace_error(error_message, bun_lock)
|
|
213
|
+
|
|
123
214
|
ERR_PATTERNS.each do |pattern, error_class|
|
|
124
215
|
raise error_class, error_message if error_message.match?(pattern)
|
|
125
216
|
end
|
|
@@ -127,6 +218,65 @@ module Dependabot
|
|
|
127
218
|
raise error
|
|
128
219
|
end
|
|
129
220
|
|
|
221
|
+
# Reports the first registry failure bun printed that the repository has to resolve: access that was denied,
|
|
222
|
+
# or a tarball the registry does not have. A failure with any other status is skipped, so it cannot hide a
|
|
223
|
+
# later one that can be classified, and is left to the generic handling when there is none.
|
|
224
|
+
sig { params(error_message: String).void }
|
|
225
|
+
def raise_registry_error(error_message)
|
|
226
|
+
registry_failures(error_message).each do |failure|
|
|
227
|
+
status = failure[:status]
|
|
228
|
+
url = failure[:url]
|
|
229
|
+
|
|
230
|
+
if ACCESS_DENIED_STATUSES.include?(status) && url
|
|
231
|
+
raise Dependabot::PrivateSourceAuthenticationFailure, registry_origin(url)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
next unless status == NOT_FOUND_STATUS && failure.names.include?("spec")
|
|
235
|
+
|
|
236
|
+
raise Dependabot::DependencyNotFound, package_name_from(T.must(failure[:spec]))
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
# Every registry failure in the output, in the order bun printed them
|
|
241
|
+
sig { params(error_message: String).returns(T::Array[MatchData]) }
|
|
242
|
+
def registry_failures(error_message)
|
|
243
|
+
[DOWNLOAD_FAILED, REQUEST_FAILED]
|
|
244
|
+
.flat_map { |pattern| error_message.to_enum(:scan, pattern).map { T.must(Regexp.last_match) } }
|
|
245
|
+
.sort_by { |match| match.begin(0) }
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
sig { params(error_message: String, bun_lock: Dependabot::DependencyFile).void }
|
|
249
|
+
def raise_workspace_error(error_message, bun_lock)
|
|
250
|
+
if (match = error_message.match(WORKSPACE_NOT_ON_DISK))
|
|
251
|
+
raise Dependabot::DependencyFileNotResolvable,
|
|
252
|
+
"#{bun_lock.path} lists the workspace \"#{match[:name]}\" (#{match[:path]}), " \
|
|
253
|
+
"but it is not part of the repository. Every workspace in the lockfile must be present."
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
return unless (match = error_message.match(WORKSPACE_NOT_FOUND))
|
|
257
|
+
|
|
258
|
+
raise Dependabot::DependencyFileNotResolvable,
|
|
259
|
+
"package.json lists the workspace \"#{match[:path]}\", but it does not exist in the repository."
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# The scheme, host and any non-default port of the URL, so the error names the registry and not a single
|
|
263
|
+
# tarball. A registry on another port is a different endpoint.
|
|
264
|
+
sig { params(url: String).returns(String) }
|
|
265
|
+
def registry_origin(url)
|
|
266
|
+
uri = URI.parse(url)
|
|
267
|
+
default_port = T.cast(uri.default_port, T.nilable(Integer))
|
|
268
|
+
port = ":#{uri.port}" if uri.port && uri.port != default_port
|
|
269
|
+
"#{uri.scheme}://#{uri.host}#{port}"
|
|
270
|
+
rescue URI::InvalidURIError
|
|
271
|
+
url
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# "@scope/name@1.2.3" and "name@1.2.3" both end in the version
|
|
275
|
+
sig { params(spec: String).returns(String) }
|
|
276
|
+
def package_name_from(spec)
|
|
277
|
+
spec.sub(/@[^@]*\z/, "")
|
|
278
|
+
end
|
|
279
|
+
|
|
130
280
|
sig { void }
|
|
131
281
|
def write_final_package_json_files
|
|
132
282
|
package_files.each do |file|
|
|
@@ -63,21 +63,23 @@ module Dependabot
|
|
|
63
63
|
nil
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
-
sig { params(command: String, fingerprint: T.nilable(String)).returns(String) }
|
|
66
|
+
sig { params(command: T.any(String, T::Array[String]), fingerprint: T.nilable(String)).returns(String) }
|
|
67
67
|
def self.run_bun_command(command, fingerprint: nil)
|
|
68
|
-
full_command = "bun #{command}"
|
|
68
|
+
full_command = command.is_a?(Array) ? ["bun", *command] : "bun #{command}"
|
|
69
|
+
display_command = full_command.is_a?(Array) ? full_command.join(" ") : full_command
|
|
70
|
+
fingerprint_command = command.is_a?(Array) ? command.join(" ") : command
|
|
69
71
|
|
|
70
|
-
Dependabot.logger.info("Running bun command: #{
|
|
72
|
+
Dependabot.logger.info("Running bun command: #{display_command}")
|
|
71
73
|
|
|
72
74
|
result = Dependabot::SharedHelpers.run_shell_command(
|
|
73
75
|
full_command,
|
|
74
|
-
fingerprint: "bun #{fingerprint ||
|
|
76
|
+
fingerprint: "bun #{fingerprint || fingerprint_command}"
|
|
75
77
|
)
|
|
76
78
|
|
|
77
|
-
Dependabot.logger.info("Command executed successfully: #{
|
|
79
|
+
Dependabot.logger.info("Command executed successfully: #{display_command}")
|
|
78
80
|
result
|
|
79
81
|
rescue StandardError => e
|
|
80
|
-
Dependabot.logger.error("Error running bun command: #{
|
|
82
|
+
Dependabot.logger.error("Error running bun command: #{display_command}, Error: #{e.message}")
|
|
81
83
|
raise
|
|
82
84
|
end
|
|
83
85
|
|
|
@@ -178,21 +178,25 @@ module Dependabot
|
|
|
178
178
|
def latest_version_listing
|
|
179
179
|
return @latest_version_listing unless @latest_version_listing.nil?
|
|
180
180
|
|
|
181
|
+
@latest_version_listing = T.let({}, T.nilable(T::Hash[String, T.untyped]))
|
|
182
|
+
|
|
181
183
|
response = Dependabot::RegistryClient.get(
|
|
182
184
|
url: "#{dependency_url}/latest",
|
|
183
185
|
headers: registry_auth_headers
|
|
184
186
|
)
|
|
185
|
-
return @latest_version_listing
|
|
187
|
+
return T.must(@latest_version_listing) if response.status >= 500
|
|
186
188
|
|
|
187
189
|
begin
|
|
188
|
-
|
|
190
|
+
# A registry can answer a missing package with a bare JSON string such as "Not Found"
|
|
191
|
+
parsed = JSON.parse(response.body)
|
|
192
|
+
@latest_version_listing = parsed if parsed.is_a?(Hash)
|
|
189
193
|
rescue JSON::ParserError
|
|
190
194
|
raise unless non_standard_registry?
|
|
191
|
-
|
|
192
|
-
@latest_version_listing = {}
|
|
193
195
|
end
|
|
196
|
+
|
|
197
|
+
T.must(@latest_version_listing)
|
|
194
198
|
rescue JSON::ParserError, Excon::Error::Timeout
|
|
195
|
-
|
|
199
|
+
T.must(@latest_version_listing)
|
|
196
200
|
end
|
|
197
201
|
|
|
198
202
|
sig { returns(T::Array[[String, T::Hash[String, T.untyped]]]) }
|
|
@@ -209,18 +213,21 @@ module Dependabot
|
|
|
209
213
|
def npm_listing
|
|
210
214
|
return @npm_listing unless @npm_listing.nil?
|
|
211
215
|
|
|
216
|
+
@npm_listing = T.let({}, T.nilable(T::Hash[String, T.untyped]))
|
|
217
|
+
|
|
212
218
|
response = Dependabot::RegistryClient.get(url: dependency_url, headers: registry_auth_headers)
|
|
213
|
-
return @npm_listing
|
|
219
|
+
return T.must(@npm_listing) if response.status >= 500
|
|
214
220
|
|
|
215
221
|
begin
|
|
216
|
-
|
|
222
|
+
parsed = JSON.parse(response.body)
|
|
223
|
+
@npm_listing = parsed if parsed.is_a?(Hash)
|
|
217
224
|
rescue JSON::ParserError
|
|
218
225
|
raise unless non_standard_registry?
|
|
219
|
-
|
|
220
|
-
@npm_listing = {}
|
|
221
226
|
end
|
|
227
|
+
|
|
228
|
+
T.must(@npm_listing)
|
|
222
229
|
rescue Excon::Error::Timeout
|
|
223
|
-
|
|
230
|
+
T.must(@npm_listing)
|
|
224
231
|
end
|
|
225
232
|
|
|
226
233
|
sig { returns(String) }
|
|
@@ -20,7 +20,7 @@ module Dependabot
|
|
|
20
20
|
https://registry.yarnpkg.com
|
|
21
21
|
http://registry.yarnpkg.com
|
|
22
22
|
).freeze
|
|
23
|
-
NPM_AUTH_TOKEN_REGEX = %r{
|
|
23
|
+
NPM_AUTH_TOKEN_REGEX = %r{^[ \t]*//(?<registry>.*)/:_authToken=(?<token>.*)$}
|
|
24
24
|
NPM_GLOBAL_REGISTRY_REGEX = /^registry\s*=\s*['"]?(?<registry>.*?)['"]?$/
|
|
25
25
|
YARN_GLOBAL_REGISTRY_REGEX = /^(?:--)?registry\s+((['"](?<registry>.*)['"])|(?<registry>.*))/
|
|
26
26
|
NPM_SCOPED_REGISTRY_REGEX = /^(?<scope>@[^:]+)\s*:registry\s*=\s*['"]?(?<registry>.*?)['"]?$/
|
|
@@ -6,6 +6,7 @@ require "sorbet-runtime"
|
|
|
6
6
|
require "dependabot/errors"
|
|
7
7
|
require "dependabot/git_commit_checker"
|
|
8
8
|
require "dependabot/logger"
|
|
9
|
+
require "dependabot/package/npm_package_json"
|
|
9
10
|
require "dependabot/package/npm_registry_package"
|
|
10
11
|
require "dependabot/bun/dependency_files_filterer"
|
|
11
12
|
require "dependabot/bun/file_parser"
|
|
@@ -615,13 +616,119 @@ module Dependabot
|
|
|
615
616
|
def run_bun_checker(path:, version:)
|
|
616
617
|
SharedHelpers.with_git_configured(credentials: credentials) do
|
|
617
618
|
Dir.chdir(path) do
|
|
618
|
-
|
|
619
|
-
"update #{dependency.name}@#{version} --save-text-lockfile --ignore-scripts",
|
|
620
|
-
fingerprint: "update <dependency_name>@<version> --save-text-lockfile --ignore-scripts"
|
|
621
|
-
)
|
|
619
|
+
workspace_filters(path).flat_map { |filter| run_bun_update(filter: filter, version: version) }
|
|
622
620
|
end
|
|
623
621
|
end
|
|
622
|
+
end
|
|
623
|
+
|
|
624
|
+
sig do
|
|
625
|
+
params(
|
|
626
|
+
filter: T.nilable(String),
|
|
627
|
+
version: T.nilable(T.any(String, Gem::Version))
|
|
628
|
+
).returns(T::Array[PeerDependencyConflict])
|
|
629
|
+
end
|
|
630
|
+
def run_bun_update(filter:, version:)
|
|
631
|
+
command = T.let(["update", "#{dependency.name}@#{version}"], T::Array[String])
|
|
632
|
+
command += ["--filter", filter] if filter
|
|
633
|
+
command += ["--save-text-lockfile", "--ignore-scripts"]
|
|
634
|
+
|
|
635
|
+
Helpers.run_bun_command(
|
|
636
|
+
command,
|
|
637
|
+
fingerprint: "update <dependency_name>@<version> --save-text-lockfile --ignore-scripts"
|
|
638
|
+
)
|
|
624
639
|
[]
|
|
640
|
+
rescue SharedHelpers::HelperSubprocessFailed => e
|
|
641
|
+
handle_peer_dependency_errors(e.message)
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
# Returns every workspace filter (nil for the +path+ we've already
|
|
645
|
+
# chdir'd into, or a workspace path relative to it) for manifests in
|
|
646
|
+
# the project rooted at +path+ that declare +dependency+. Manifests
|
|
647
|
+
# are matched by scanning their actual dependency fields (as
|
|
648
|
+
# BunLockfileUpdater does), rather than dependency.requirements,
|
|
649
|
+
# since Bun always records catalog entries against the root
|
|
650
|
+
# package.json even when a nested workspace is the only consumer
|
|
651
|
+
# (via "catalog:"). Falls back to an unfiltered check at +path+ if
|
|
652
|
+
# it isn't declared anywhere in this project (e.g. a
|
|
653
|
+
# sub-dependency).
|
|
654
|
+
sig { params(path: String).returns(T::Array[T.nilable(String)]) }
|
|
655
|
+
def workspace_filters(path)
|
|
656
|
+
manifests = package_jsons_in_project(path)
|
|
657
|
+
root_file = manifests.find { |file| File.dirname(file.name) == path }
|
|
658
|
+
|
|
659
|
+
workspace_filters = manifests.filter_map do |file|
|
|
660
|
+
next if file == root_file
|
|
661
|
+
next unless package_json_declares?(file)
|
|
662
|
+
|
|
663
|
+
workspace_filter(file, path: path)
|
|
664
|
+
end.uniq
|
|
665
|
+
|
|
666
|
+
declared_at_root = root_file && package_json_declares?(root_file)
|
|
667
|
+
return workspace_filters if !declared_at_root && workspace_filters.any?
|
|
668
|
+
|
|
669
|
+
[nil, *workspace_filters]
|
|
670
|
+
end
|
|
671
|
+
|
|
672
|
+
# Every package.json belonging to the same Bun project as +path+:
|
|
673
|
+
# its own manifest, plus any workspace members governed by the same
|
|
674
|
+
# lockfile. Manifests under a *nested* project with its own
|
|
675
|
+
# lockfile are excluded, so that sibling nested projects (each
|
|
676
|
+
# checked separately, chdir'd into their own path) don't leak their
|
|
677
|
+
# declarations into each other's filters.
|
|
678
|
+
sig { params(path: String).returns(T::Array[Dependabot::DependencyFile]) }
|
|
679
|
+
def package_jsons_in_project(path)
|
|
680
|
+
project_lockfile_dir = lockfile_dir_for(path)
|
|
681
|
+
|
|
682
|
+
dependency_files.select do |file|
|
|
683
|
+
next false unless file.name.end_with?("package.json")
|
|
684
|
+
|
|
685
|
+
dir = File.dirname(file.name)
|
|
686
|
+
next false unless path == "." || dir == path || dir.start_with?("#{path}/")
|
|
687
|
+
|
|
688
|
+
lockfile_dir_for(dir) == project_lockfile_dir
|
|
689
|
+
end
|
|
690
|
+
end
|
|
691
|
+
|
|
692
|
+
# The directory of the bun.lock that governs +dir+: the lockfile
|
|
693
|
+
# whose own directory is the longest ancestor match, since a nested
|
|
694
|
+
# lockfile takes precedence over the root one for its own subtree.
|
|
695
|
+
sig { params(dir: String).returns(T.nilable(String)) }
|
|
696
|
+
def lockfile_dir_for(dir)
|
|
697
|
+
lockfile_dirs = dependency_files_builder.bun_locks.map { |lockfile| File.dirname(lockfile.name) }
|
|
698
|
+
lockfile_dirs.select { |lockfile_dir| lockfile_governs_dir?(lockfile_dir, dir) }.max_by(&:length)
|
|
699
|
+
end
|
|
700
|
+
|
|
701
|
+
sig { params(lockfile_dir: String, dir: String).returns(T::Boolean) }
|
|
702
|
+
def lockfile_governs_dir?(lockfile_dir, dir)
|
|
703
|
+
lockfile_dir == "." || dir == lockfile_dir || dir.start_with?("#{lockfile_dir}/")
|
|
704
|
+
end
|
|
705
|
+
|
|
706
|
+
sig { params(package_json_file: Dependabot::DependencyFile).returns(T::Boolean) }
|
|
707
|
+
def package_json_declares?(package_json_file)
|
|
708
|
+
declared = T.let(false, T::Boolean)
|
|
709
|
+
Dependabot::Package::NpmPackageJson.from_file(package_json_file).each_dependency do |name, _req, _type|
|
|
710
|
+
declared ||= name == dependency.name
|
|
711
|
+
end
|
|
712
|
+
declared
|
|
713
|
+
end
|
|
714
|
+
|
|
715
|
+
# Path-based --filter target, relative to +path+, for the workspace
|
|
716
|
+
# at +file+ (e.g. "./packages/app"). Bun's --filter also accepts a
|
|
717
|
+
# package's declared "name", but names can contain glob
|
|
718
|
+
# metacharacters that would match unrelated workspaces, so a path is
|
|
719
|
+
# used instead.
|
|
720
|
+
sig { params(file: Dependabot::DependencyFile, path: String).returns(String) }
|
|
721
|
+
def workspace_filter(file, path:)
|
|
722
|
+
unless Dependabot::Package::NpmPackageJson.from_file(file).name
|
|
723
|
+
raise Dependabot::DependencyFileNotParseable.new(
|
|
724
|
+
file.path,
|
|
725
|
+
"#{file.name} must declare a \"name\" to be targeted for a workspace-scoped check"
|
|
726
|
+
)
|
|
727
|
+
end
|
|
728
|
+
|
|
729
|
+
workspace_dir = File.dirname(file.name)
|
|
730
|
+
workspace_dir = workspace_dir.delete_prefix("#{path}/") unless path == "."
|
|
731
|
+
"./#{workspace_dir}"
|
|
625
732
|
end
|
|
626
733
|
|
|
627
734
|
sig do
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dependabot-bun
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.402.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dependabot
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - '='
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 0.
|
|
18
|
+
version: 0.402.0
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - '='
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 0.
|
|
25
|
+
version: 0.402.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: debug
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -356,7 +356,7 @@ licenses:
|
|
|
356
356
|
- MIT
|
|
357
357
|
metadata:
|
|
358
358
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
|
359
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
|
359
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.402.0
|
|
360
360
|
rdoc_options: []
|
|
361
361
|
require_paths:
|
|
362
362
|
- lib
|