dependabot-pub 0.398.0 → 0.399.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/pub/dependency_services_result.rb +167 -0
- data/lib/dependabot/pub/file_parser.rb +2 -2
- data/lib/dependabot/pub/helpers.rb +99 -94
- data/lib/dependabot/pub/json_value_parser.rb +65 -0
- data/lib/dependabot/pub/metadata_finder.rb +5 -8
- data/lib/dependabot/pub/package/package_details_fetcher.rb +8 -32
- data/lib/dependabot/pub/package/registry_package.rb +67 -0
- data/lib/dependabot/pub/update_checker/latest_version_finder.rb +24 -23
- data/lib/dependabot/pub/update_checker.rb +22 -13
- data/lib/dependabot/pub/version.rb +1 -1
- metadata +7 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bccb4cb21417d15087e804ed056b2ff00451cf1c908fd8cdfb40f7709fd02ce8
|
|
4
|
+
data.tar.gz: 685f8a0c5df291c2be68371b3c798343e61f23cd17ea5745efc879315dd3e178
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: af4a96a16577145fa0f6c3a9baf56c447f90dbade75678af5e8037faf926da725ecf3e4370dfae19e0f7f923c25aa984fb148aae146be7dacb361628809000a7
|
|
7
|
+
data.tar.gz: f615713050dddd07821622e4fd15a059b5c0470179d44236b901855c2db0feddc3fcbf89612ab681c71d4966f6ef5b355ccb73f777cc5d09411accb0188d609a
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "sorbet-runtime"
|
|
5
|
+
require "dependabot/pub/json_value_parser"
|
|
6
|
+
require "dependabot/shared_helpers"
|
|
7
|
+
|
|
8
|
+
module Dependabot
|
|
9
|
+
module Pub
|
|
10
|
+
module DependencyServicesResult
|
|
11
|
+
extend T::Sig
|
|
12
|
+
|
|
13
|
+
class ListedDependency < T::ImmutableStruct
|
|
14
|
+
const :name, String
|
|
15
|
+
const :version, String
|
|
16
|
+
const :kind, String
|
|
17
|
+
const :constraint, T.nilable(String)
|
|
18
|
+
const :source, T.nilable(JsonValueParser::ObjectHash)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class DependencyUpdate < T::ImmutableStruct
|
|
22
|
+
const :name, String
|
|
23
|
+
const :version, T.nilable(String)
|
|
24
|
+
const :kind, String
|
|
25
|
+
const :previous_version, T.nilable(String)
|
|
26
|
+
const :previous_constraint, T.nilable(String)
|
|
27
|
+
const :constraint_bumped, T.nilable(String)
|
|
28
|
+
const :constraint_bumped_if_needed, T.nilable(String)
|
|
29
|
+
const :constraint_widened, T.nilable(String)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class ReportEntry < T::ImmutableStruct
|
|
33
|
+
const :name, String
|
|
34
|
+
const :version, String
|
|
35
|
+
const :latest, T.nilable(String)
|
|
36
|
+
const :compatible, T::Array[DependencyUpdate]
|
|
37
|
+
const :single_breaking, T::Array[DependencyUpdate]
|
|
38
|
+
const :multi_breaking, T::Array[DependencyUpdate]
|
|
39
|
+
const :smallest_update, T.nilable(T::Array[DependencyUpdate])
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class Report < T::ImmutableStruct
|
|
43
|
+
const :dependencies, T::Array[ReportEntry]
|
|
44
|
+
const :cache_content, String
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
sig { params(content: String).returns(T::Array[ListedDependency]) }
|
|
48
|
+
def self.list_from_json(content)
|
|
49
|
+
context = "dependency_services list"
|
|
50
|
+
root = JsonValueParser.object(JsonValueParser.parse(content, context), context)
|
|
51
|
+
JsonValueParser.array(root["dependencies"], "#{context}.dependencies").each_with_index.map do |value, index|
|
|
52
|
+
entry_context = "#{context}.dependencies[#{index}]"
|
|
53
|
+
fields = JsonValueParser.object(value, entry_context)
|
|
54
|
+
ListedDependency.new(
|
|
55
|
+
name: JsonValueParser.string(fields["name"], "#{entry_context}.name"),
|
|
56
|
+
version: JsonValueParser.string(fields["version"], "#{entry_context}.version"),
|
|
57
|
+
kind: JsonValueParser.string(fields["kind"], "#{entry_context}.kind"),
|
|
58
|
+
constraint: JsonValueParser.optional_string(fields["constraint"], "#{entry_context}.constraint"),
|
|
59
|
+
source: JsonValueParser.optional_object(fields["source"], "#{entry_context}.source")
|
|
60
|
+
)
|
|
61
|
+
end
|
|
62
|
+
rescue JsonValueParser::InvalidValue => e
|
|
63
|
+
invalid_result("dependency_services list", e.message)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
sig { params(content: String).returns(Report) }
|
|
67
|
+
def self.report_from_json(content)
|
|
68
|
+
context = "dependency_services report"
|
|
69
|
+
root = JsonValueParser.object(JsonValueParser.parse(content, context), context)
|
|
70
|
+
build_report(root["dependencies"], "#{context}.dependencies")
|
|
71
|
+
rescue JsonValueParser::InvalidValue => e
|
|
72
|
+
invalid_result("dependency_services report", e.message)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
sig { params(content: String).returns(Report) }
|
|
76
|
+
def self.report_from_cache(content)
|
|
77
|
+
context = "dependency_services report cache"
|
|
78
|
+
build_report(JsonValueParser.parse(content, context), context)
|
|
79
|
+
rescue JsonValueParser::InvalidValue => e
|
|
80
|
+
invalid_result("dependency_services report cache", e.message)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
sig { params(reports: T::Array[ReportEntry], name: String).returns(ReportEntry) }
|
|
84
|
+
def self.find_report(reports, name)
|
|
85
|
+
report = reports.find { |entry| entry.name == name }
|
|
86
|
+
return report if report
|
|
87
|
+
|
|
88
|
+
invalid_result(
|
|
89
|
+
"dependency_services report",
|
|
90
|
+
"dependency_services report does not include the requested dependency"
|
|
91
|
+
)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
sig { params(context: String, message: String).returns(T.noreturn) }
|
|
95
|
+
def self.invalid_result(context, message)
|
|
96
|
+
raise SharedHelpers::HelperSubprocessFailed.new(
|
|
97
|
+
message: message,
|
|
98
|
+
error_class: "TypeError",
|
|
99
|
+
error_context: { function: context }
|
|
100
|
+
),
|
|
101
|
+
cause: nil
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
sig { params(value: Object, context: String).returns(Report) }
|
|
105
|
+
def self.build_report(value, context)
|
|
106
|
+
raw_entries = JsonValueParser.array(value, context)
|
|
107
|
+
entries = raw_entries.each_with_index.map do |entry, index|
|
|
108
|
+
report_entry(entry, "#{context}[#{index}]")
|
|
109
|
+
end
|
|
110
|
+
Report.new(dependencies: entries, cache_content: JSON.generate(raw_entries))
|
|
111
|
+
end
|
|
112
|
+
private_class_method :build_report
|
|
113
|
+
|
|
114
|
+
sig { params(value: Object, context: String).returns(ReportEntry) }
|
|
115
|
+
def self.report_entry(value, context)
|
|
116
|
+
fields = JsonValueParser.object(value, context)
|
|
117
|
+
ReportEntry.new(
|
|
118
|
+
name: JsonValueParser.string(fields["name"], "#{context}.name"),
|
|
119
|
+
version: JsonValueParser.string(fields["version"], "#{context}.version"),
|
|
120
|
+
latest: JsonValueParser.optional_string(fields["latest"], "#{context}.latest"),
|
|
121
|
+
compatible: updates(fields["compatible"], "#{context}.compatible"),
|
|
122
|
+
single_breaking: updates(fields["singleBreaking"], "#{context}.singleBreaking"),
|
|
123
|
+
multi_breaking: updates(fields["multiBreaking"], "#{context}.multiBreaking"),
|
|
124
|
+
smallest_update: if fields.key?("smallestUpdate")
|
|
125
|
+
updates(
|
|
126
|
+
fields["smallestUpdate"],
|
|
127
|
+
"#{context}.smallestUpdate"
|
|
128
|
+
)
|
|
129
|
+
end
|
|
130
|
+
)
|
|
131
|
+
end
|
|
132
|
+
private_class_method :report_entry
|
|
133
|
+
|
|
134
|
+
sig { params(value: Object, context: String).returns(T::Array[DependencyUpdate]) }
|
|
135
|
+
def self.updates(value, context)
|
|
136
|
+
JsonValueParser.array(value, context).each_with_index.map do |entry, index|
|
|
137
|
+
entry_context = "#{context}[#{index}]"
|
|
138
|
+
fields = JsonValueParser.object(entry, entry_context)
|
|
139
|
+
DependencyUpdate.new(
|
|
140
|
+
name: JsonValueParser.string(fields["name"], "#{entry_context}.name"),
|
|
141
|
+
version: JsonValueParser.optional_string(fields["version"], "#{entry_context}.version"),
|
|
142
|
+
kind: JsonValueParser.string(fields["kind"], "#{entry_context}.kind"),
|
|
143
|
+
previous_version: JsonValueParser.optional_string(
|
|
144
|
+
fields["previousVersion"],
|
|
145
|
+
"#{entry_context}.previousVersion"
|
|
146
|
+
),
|
|
147
|
+
previous_constraint: JsonValueParser.optional_string(
|
|
148
|
+
fields["previousConstraint"], "#{entry_context}.previousConstraint"
|
|
149
|
+
),
|
|
150
|
+
constraint_bumped: JsonValueParser.optional_string(
|
|
151
|
+
fields["constraintBumped"],
|
|
152
|
+
"#{entry_context}.constraintBumped"
|
|
153
|
+
),
|
|
154
|
+
constraint_bumped_if_needed: JsonValueParser.optional_string(
|
|
155
|
+
fields["constraintBumpedIfNeeded"], "#{entry_context}.constraintBumpedIfNeeded"
|
|
156
|
+
),
|
|
157
|
+
constraint_widened: JsonValueParser.optional_string(
|
|
158
|
+
fields["constraintWidened"],
|
|
159
|
+
"#{entry_context}.constraintWidened"
|
|
160
|
+
)
|
|
161
|
+
)
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
private_class_method :updates
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
@@ -82,9 +82,9 @@ module Dependabot
|
|
|
82
82
|
raise "No pubspec.yaml!" unless get_original_file("pubspec.yaml")
|
|
83
83
|
end
|
|
84
84
|
|
|
85
|
-
sig { returns(T::Array[
|
|
85
|
+
sig { returns(T::Array[DependencyServicesResult::ListedDependency]) }
|
|
86
86
|
def list
|
|
87
|
-
@list ||= T.let(dependency_services_list, T.nilable(T::Array[
|
|
87
|
+
@list ||= T.let(dependency_services_list, T.nilable(T::Array[DependencyServicesResult::ListedDependency]))
|
|
88
88
|
end
|
|
89
89
|
end
|
|
90
90
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strong
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "digest"
|
|
@@ -8,6 +8,8 @@ require "sorbet-runtime"
|
|
|
8
8
|
|
|
9
9
|
require "dependabot/errors"
|
|
10
10
|
require "dependabot/logger"
|
|
11
|
+
require "dependabot/pub/dependency_services_result"
|
|
12
|
+
require "dependabot/pub/package/registry_package"
|
|
11
13
|
require "dependabot/pub/requirement"
|
|
12
14
|
require "dependabot/pub/requirement_source"
|
|
13
15
|
require "dependabot/requirements_update_strategy"
|
|
@@ -23,13 +25,19 @@ module Dependabot
|
|
|
23
25
|
|
|
24
26
|
abstract!
|
|
25
27
|
|
|
28
|
+
class SdkVersions < T::ImmutableStruct
|
|
29
|
+
const :flutter, String
|
|
30
|
+
const :dart, String
|
|
31
|
+
const :channel, T.nilable(String), default: nil
|
|
32
|
+
end
|
|
33
|
+
|
|
26
34
|
sig { abstract.returns(T::Array[Dependabot::Credential]) }
|
|
27
35
|
def credentials; end
|
|
28
36
|
|
|
29
37
|
sig { abstract.returns(T::Array[Dependabot::DependencyFile]) }
|
|
30
38
|
def dependency_files; end
|
|
31
39
|
|
|
32
|
-
sig { abstract.returns(T::Hash[Symbol, T.
|
|
40
|
+
sig { abstract.returns(T::Hash[Symbol, T.anything]) }
|
|
33
41
|
def options; end
|
|
34
42
|
|
|
35
43
|
sig { returns(String) }
|
|
@@ -42,7 +50,7 @@ module Dependabot
|
|
|
42
50
|
dir: T.any(Pathname, String),
|
|
43
51
|
url: T.nilable(String)
|
|
44
52
|
)
|
|
45
|
-
.returns(T.nilable(
|
|
53
|
+
.returns(T.nilable(SdkVersions))
|
|
46
54
|
end
|
|
47
55
|
def self.run_infer_sdk_versions(dir, url: nil)
|
|
48
56
|
env = {}
|
|
@@ -51,24 +59,31 @@ module Dependabot
|
|
|
51
59
|
stdout, _, status = Open3.capture3(env, cmd, opts, chdir: dir)
|
|
52
60
|
return nil unless status.success?
|
|
53
61
|
|
|
54
|
-
|
|
62
|
+
fields = JsonValueParser.object(JsonValueParser.parse(stdout, "infer_sdk_versions"), "infer_sdk_versions")
|
|
63
|
+
SdkVersions.new(
|
|
64
|
+
flutter: JsonValueParser.string(fields["flutter"], "infer_sdk_versions.flutter"),
|
|
65
|
+
dart: JsonValueParser.string(fields["dart"], "infer_sdk_versions.dart"),
|
|
66
|
+
channel: JsonValueParser.string(fields["channel"], "infer_sdk_versions.channel")
|
|
67
|
+
)
|
|
68
|
+
rescue JsonValueParser::InvalidValue => e
|
|
69
|
+
DependencyServicesResult.invalid_result("infer_sdk_versions", e.message)
|
|
55
70
|
end
|
|
56
71
|
|
|
57
72
|
private
|
|
58
73
|
|
|
59
|
-
sig { returns(T::Array[
|
|
74
|
+
sig { returns(T::Array[DependencyServicesResult::ListedDependency]) }
|
|
60
75
|
def dependency_services_list
|
|
61
|
-
|
|
76
|
+
DependencyServicesResult.list_from_json(run_dependency_services("list"))
|
|
62
77
|
end
|
|
63
78
|
|
|
64
79
|
sig { params(dependency: Dependabot::Dependency).returns(String) }
|
|
65
80
|
def repository_url(dependency)
|
|
66
81
|
repository_url = RequirementSource.new(dependency.requirements.first).description_string("url") ||
|
|
67
|
-
|
|
82
|
+
option_string(:pub_hosted_url) || "https://pub.dev"
|
|
68
83
|
repository_url.delete_suffix("/")
|
|
69
84
|
end
|
|
70
85
|
|
|
71
|
-
sig { params(dependency: Dependabot::Dependency).returns(
|
|
86
|
+
sig { params(dependency: Dependabot::Dependency).returns(Package::RegistryPackage) }
|
|
72
87
|
def fetch_package_listing(dependency)
|
|
73
88
|
# Because we get the security_advisories as a set of constraints, we
|
|
74
89
|
# fetch the list of all versions and filter them to a list of vulnerable
|
|
@@ -77,17 +92,15 @@ module Dependabot
|
|
|
77
92
|
# Ideally we would like the helper to be the only one doing requests to
|
|
78
93
|
# the repository. But this should work for now:
|
|
79
94
|
response = Dependabot::RegistryClient.get(url: "#{repository_url(dependency)}/api/packages/#{dependency.name}")
|
|
80
|
-
|
|
95
|
+
Package::RegistryPackage.from_json(response.body)
|
|
81
96
|
end
|
|
82
97
|
|
|
83
98
|
sig { params(dependency: Dependabot::Dependency).returns(T::Array[Dependabot::Pub::Version]) }
|
|
84
99
|
def available_versions(dependency)
|
|
85
|
-
fetch_package_listing(dependency)
|
|
86
|
-
Dependabot::Pub::Version.new(v["version"])
|
|
87
|
-
end
|
|
100
|
+
fetch_package_listing(dependency).versions
|
|
88
101
|
end
|
|
89
102
|
|
|
90
|
-
sig { returns(T::Array[
|
|
103
|
+
sig { returns(T::Array[DependencyServicesResult::ReportEntry]) }
|
|
91
104
|
def dependency_services_report
|
|
92
105
|
sha256 = Digest::SHA256.new
|
|
93
106
|
dependency_files.each do |f|
|
|
@@ -96,11 +109,11 @@ module Dependabot
|
|
|
96
109
|
hash = sha256.hexdigest
|
|
97
110
|
|
|
98
111
|
cache_file = "/tmp/report-#{hash}-pid-#{Process.pid}.json"
|
|
99
|
-
return
|
|
112
|
+
return DependencyServicesResult.report_from_cache(File.read(cache_file)).dependencies if File.file?(cache_file)
|
|
100
113
|
|
|
101
|
-
report =
|
|
102
|
-
File.write(cache_file,
|
|
103
|
-
report
|
|
114
|
+
report = DependencyServicesResult.report_from_json(run_dependency_services("report"))
|
|
115
|
+
File.write(cache_file, report.cache_content)
|
|
116
|
+
report.dependencies
|
|
104
117
|
end
|
|
105
118
|
|
|
106
119
|
sig do
|
|
@@ -177,19 +190,19 @@ module Dependabot
|
|
|
177
190
|
## Detects the right flutter release to use for the pubspec.yaml.
|
|
178
191
|
## Then checks it out if it is not already.
|
|
179
192
|
## Returns the sdk versions
|
|
180
|
-
sig { params(dir: T.any(Pathname, String)).returns(
|
|
193
|
+
sig { params(dir: T.any(Pathname, String)).returns(SdkVersions) }
|
|
181
194
|
def ensure_right_flutter_release(dir)
|
|
182
195
|
versions = Helpers.run_infer_sdk_versions(
|
|
183
|
-
File.join(dir, dependency_files.first
|
|
184
|
-
url:
|
|
196
|
+
File.join(dir, T.must(dependency_files.first).directory),
|
|
197
|
+
url: option_string(:flutter_releases_url)
|
|
185
198
|
)
|
|
186
199
|
flutter_ref =
|
|
187
200
|
if versions
|
|
188
201
|
Dependabot.logger.info(
|
|
189
|
-
"Installing the Flutter SDK version: #{versions
|
|
190
|
-
"from channel #{versions
|
|
202
|
+
"Installing the Flutter SDK version: #{versions.flutter} " \
|
|
203
|
+
"from channel #{versions.channel} with Dart #{versions.dart}"
|
|
191
204
|
)
|
|
192
|
-
"refs/tags/#{versions
|
|
205
|
+
"refs/tags/#{versions.flutter}"
|
|
193
206
|
else
|
|
194
207
|
Dependabot.logger.info(
|
|
195
208
|
"Failed to infer the flutter version. Attempting to use latest stable release."
|
|
@@ -218,7 +231,7 @@ module Dependabot
|
|
|
218
231
|
end
|
|
219
232
|
|
|
220
233
|
# Runs `flutter version` and returns the dart and flutter version numbers in a map.
|
|
221
|
-
sig { returns(
|
|
234
|
+
sig { returns(SdkVersions) }
|
|
222
235
|
def run_flutter_version
|
|
223
236
|
Dependabot.logger.info "Running `flutter --version`"
|
|
224
237
|
# Run `flutter --version --machine` to get the current flutter version.
|
|
@@ -234,20 +247,18 @@ module Dependabot
|
|
|
234
247
|
"Running 'flutter --version --machine' failed: #{stderr}"
|
|
235
248
|
end
|
|
236
249
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
end
|
|
250
|
+
context = "flutter --version"
|
|
251
|
+
parsed = JsonValueParser.object(JsonValueParser.parse(stdout, context), context)
|
|
252
|
+
flutter_version = JsonValueParser.string(parsed["frameworkVersion"], "#{context}.frameworkVersion")
|
|
253
|
+
dart_version = JsonValueParser.string(parsed["dartSdkVersion"], "#{context}.dartSdkVersion").split.first
|
|
254
|
+
raise JsonValueParser::InvalidValue, "#{context}.dartSdkVersion must contain a version" unless dart_version
|
|
255
|
+
|
|
244
256
|
Dependabot.logger.info(
|
|
245
257
|
"Installed the Flutter SDK version: #{flutter_version} with Dart #{dart_version}."
|
|
246
258
|
)
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
259
|
+
SdkVersions.new(flutter: flutter_version, dart: dart_version)
|
|
260
|
+
rescue JsonValueParser::InvalidValue => e
|
|
261
|
+
DependencyServicesResult.invalid_result("flutter --version", e.message)
|
|
251
262
|
end
|
|
252
263
|
|
|
253
264
|
sig do
|
|
@@ -273,12 +284,12 @@ module Dependabot
|
|
|
273
284
|
"PUB_ENVIRONMENT" => "dependabot",
|
|
274
285
|
"FLUTTER_ROOT" => "/tmp/flutter",
|
|
275
286
|
"DART_ROOT" => "/tmp/flutter/bin/cache/dart-sdk",
|
|
276
|
-
"PUB_HOSTED_URL" =>
|
|
287
|
+
"PUB_HOSTED_URL" => option_string(:pub_hosted_url),
|
|
277
288
|
# This variable will make the solver run assuming that Dart SDK version.
|
|
278
289
|
# TODO(sigurdm): Would be nice to have a better handle for fixing the dart sdk version.
|
|
279
|
-
"_PUB_TEST_SDK_VERSION" => sdk_versions
|
|
290
|
+
"_PUB_TEST_SDK_VERSION" => sdk_versions.dart
|
|
280
291
|
}
|
|
281
|
-
command_dir = File.join(temp_dir, dependency_files.first
|
|
292
|
+
command_dir = File.join(temp_dir, T.must(dependency_files.first).directory)
|
|
282
293
|
|
|
283
294
|
stdout, stderr, status = Open3.capture3(
|
|
284
295
|
env.compact,
|
|
@@ -311,25 +322,19 @@ module Dependabot
|
|
|
311
322
|
end
|
|
312
323
|
|
|
313
324
|
# Parses a dependency as listed by `dependency_services list`.
|
|
314
|
-
sig { params(
|
|
315
|
-
def parse_listed_dependency(
|
|
316
|
-
|
|
317
|
-
name: json["name"],
|
|
318
|
-
version: json["version"],
|
|
319
|
-
package_manager: "pub",
|
|
320
|
-
requirements: []
|
|
321
|
-
}
|
|
325
|
+
sig { params(entry: DependencyServicesResult::ListedDependency).returns(Dependabot::Dependency) }
|
|
326
|
+
def parse_listed_dependency(entry)
|
|
327
|
+
requirements = []
|
|
322
328
|
|
|
323
|
-
if
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
source: json["source"],
|
|
329
|
+
if entry.kind != "transitive" && !entry.constraint.nil?
|
|
330
|
+
requirements << {
|
|
331
|
+
requirement: entry.constraint,
|
|
332
|
+
groups: [entry.kind],
|
|
333
|
+
source: entry.source,
|
|
329
334
|
file: "pubspec.yaml"
|
|
330
335
|
}
|
|
331
336
|
end
|
|
332
|
-
Dependency.new(
|
|
337
|
+
Dependency.new(name: entry.name, version: entry.version, package_manager: "pub", requirements: requirements)
|
|
333
338
|
end
|
|
334
339
|
|
|
335
340
|
# Parses the updated dependencies returned by
|
|
@@ -339,43 +344,41 @@ module Dependabot
|
|
|
339
344
|
# used to chose the right updated constraint.
|
|
340
345
|
sig do
|
|
341
346
|
params(
|
|
342
|
-
|
|
347
|
+
entry: DependencyServicesResult::DependencyUpdate,
|
|
343
348
|
requirements_update_strategy: Dependabot::RequirementsUpdateStrategy
|
|
344
349
|
)
|
|
345
350
|
.returns(Dependabot::Dependency)
|
|
346
351
|
end
|
|
347
|
-
def parse_updated_dependency(
|
|
352
|
+
def parse_updated_dependency(entry, requirements_update_strategy)
|
|
348
353
|
requirements = []
|
|
349
|
-
|
|
354
|
+
constraint = constraint_from_update_strategy(entry, requirements_update_strategy)
|
|
350
355
|
|
|
351
|
-
if
|
|
352
|
-
constraint = json[constraint_field]
|
|
356
|
+
if entry.kind != "transitive" && !constraint.nil?
|
|
353
357
|
requirements << {
|
|
354
358
|
requirement: constraint,
|
|
355
|
-
groups: [
|
|
359
|
+
groups: [entry.kind],
|
|
356
360
|
source: nil, # TODO: Expose some information about the source
|
|
357
361
|
file: "pubspec.yaml"
|
|
358
362
|
}
|
|
359
363
|
end
|
|
360
364
|
|
|
361
365
|
previous_requirements = []
|
|
362
|
-
if
|
|
363
|
-
constraint = json["previousConstraint"]
|
|
366
|
+
if entry.previous_version && entry.kind != "transitive" && !entry.previous_constraint.nil?
|
|
364
367
|
previous_requirements << {
|
|
365
|
-
requirement:
|
|
366
|
-
groups: [
|
|
368
|
+
requirement: entry.previous_constraint,
|
|
369
|
+
groups: [entry.kind],
|
|
367
370
|
source: nil, # TODO: Expose some information about the source
|
|
368
371
|
file: "pubspec.yaml"
|
|
369
372
|
}
|
|
370
373
|
end
|
|
371
374
|
|
|
372
375
|
Dependency.new(
|
|
373
|
-
name:
|
|
374
|
-
version:
|
|
376
|
+
name: entry.name,
|
|
377
|
+
version: entry.version,
|
|
375
378
|
package_manager: "pub",
|
|
376
379
|
requirements: requirements,
|
|
377
|
-
previous_version:
|
|
378
|
-
previous_requirements:
|
|
380
|
+
previous_version: entry.previous_version,
|
|
381
|
+
previous_requirements: entry.previous_version ? previous_requirements : nil
|
|
379
382
|
)
|
|
380
383
|
end
|
|
381
384
|
|
|
@@ -383,23 +386,35 @@ module Dependabot
|
|
|
383
386
|
# strategies.
|
|
384
387
|
sig do
|
|
385
388
|
params(
|
|
389
|
+
entry: DependencyServicesResult::DependencyUpdate,
|
|
386
390
|
requirements_update_strategy: Dependabot::RequirementsUpdateStrategy
|
|
387
391
|
)
|
|
388
|
-
.returns(String)
|
|
392
|
+
.returns(T.nilable(String))
|
|
389
393
|
end
|
|
390
|
-
def
|
|
394
|
+
def constraint_from_update_strategy(entry, requirements_update_strategy)
|
|
391
395
|
case requirements_update_strategy
|
|
392
396
|
when RequirementsUpdateStrategy::WidenRanges
|
|
393
|
-
|
|
397
|
+
entry.constraint_widened
|
|
394
398
|
when RequirementsUpdateStrategy::BumpVersions
|
|
395
|
-
|
|
399
|
+
entry.constraint_bumped
|
|
396
400
|
when RequirementsUpdateStrategy::BumpVersionsIfNecessary
|
|
397
|
-
|
|
401
|
+
entry.constraint_bumped_if_needed
|
|
398
402
|
else
|
|
399
403
|
raise "Unexpected requirements_update_strategy #{requirements_update_strategy}"
|
|
400
404
|
end
|
|
401
405
|
end
|
|
402
406
|
|
|
407
|
+
sig { params(key: Symbol).returns(T.nilable(String)) }
|
|
408
|
+
def option_string(key)
|
|
409
|
+
value = options[key]
|
|
410
|
+
|
|
411
|
+
case value
|
|
412
|
+
when String then value
|
|
413
|
+
when nil then nil
|
|
414
|
+
else raise TypeError, "Pub option #{key} must be a string or nil"
|
|
415
|
+
end
|
|
416
|
+
end
|
|
417
|
+
|
|
403
418
|
sig do
|
|
404
419
|
params(
|
|
405
420
|
dependencies: T.nilable(T::Array[Dependabot::Dependency])
|
|
@@ -407,29 +422,19 @@ module Dependabot
|
|
|
407
422
|
.returns(T.nilable(String))
|
|
408
423
|
end
|
|
409
424
|
def dependencies_to_json(dependencies)
|
|
410
|
-
if dependencies.nil?
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
unless d.requirements.nil? || d.requirements.empty?
|
|
422
|
-
obj["constraint"] =
|
|
423
|
-
d.requirements[0]&.[](:requirement).to_s
|
|
424
|
-
end
|
|
425
|
-
obj
|
|
426
|
-
end
|
|
427
|
-
JSON.generate(
|
|
428
|
-
{
|
|
429
|
-
"dependencyChanges" => deps
|
|
430
|
-
}
|
|
431
|
-
)
|
|
425
|
+
return if dependencies.nil?
|
|
426
|
+
|
|
427
|
+
changes = dependencies.map do |dependency|
|
|
428
|
+
requirement = dependency.requirements.first
|
|
429
|
+
fields = {
|
|
430
|
+
"name" => dependency.name,
|
|
431
|
+
"version" => dependency.version,
|
|
432
|
+
"source" => requirement&.source
|
|
433
|
+
}
|
|
434
|
+
fields["constraint"] = requirement.requirement.to_s if requirement
|
|
435
|
+
fields
|
|
432
436
|
end
|
|
437
|
+
JSON.generate("dependencyChanges" => changes)
|
|
433
438
|
end
|
|
434
439
|
end
|
|
435
440
|
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "json"
|
|
5
|
+
require "sorbet-runtime"
|
|
6
|
+
|
|
7
|
+
module Dependabot
|
|
8
|
+
module Pub
|
|
9
|
+
module JsonValueParser
|
|
10
|
+
extend T::Sig
|
|
11
|
+
|
|
12
|
+
class InvalidValue < TypeError; end
|
|
13
|
+
|
|
14
|
+
ObjectHash = T.type_alias { T::Hash[String, Object] }
|
|
15
|
+
|
|
16
|
+
sig { params(content: String, context: String).returns(Object) }
|
|
17
|
+
def self.parse(content, context)
|
|
18
|
+
T.cast(JSON.parse(content), Object)
|
|
19
|
+
rescue JSON::ParserError
|
|
20
|
+
raise InvalidValue.new("#{context} must be valid JSON"), cause: nil
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
sig { params(value: Object, context: String).returns(ObjectHash) }
|
|
24
|
+
def self.object(value, context)
|
|
25
|
+
raise InvalidValue, "#{context} must be an object" unless value.is_a?(Hash)
|
|
26
|
+
|
|
27
|
+
value.to_h do |raw_key, raw_value|
|
|
28
|
+
key = T.cast(raw_key, Object)
|
|
29
|
+
raise InvalidValue, "#{context} keys must be strings" unless key.is_a?(String)
|
|
30
|
+
|
|
31
|
+
[key, T.cast(raw_value, Object)]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
sig { params(value: Object, context: String).returns(T.nilable(ObjectHash)) }
|
|
36
|
+
def self.optional_object(value, context)
|
|
37
|
+
return if value.nil?
|
|
38
|
+
|
|
39
|
+
object(value, context)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
sig { params(value: Object, context: String).returns(T::Array[Object]) }
|
|
43
|
+
def self.array(value, context)
|
|
44
|
+
raise InvalidValue, "#{context} must be an array" unless value.is_a?(Array)
|
|
45
|
+
|
|
46
|
+
value.map { |entry| T.cast(entry, Object) }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
sig { params(value: Object, context: String).returns(String) }
|
|
50
|
+
def self.string(value, context)
|
|
51
|
+
return value if value.is_a?(String)
|
|
52
|
+
|
|
53
|
+
raise InvalidValue, "#{context} must be a string"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
sig { params(value: Object, context: String).returns(T.nilable(String)) }
|
|
57
|
+
def self.optional_string(value, context)
|
|
58
|
+
return if value.nil?
|
|
59
|
+
return value if value.is_a?(String)
|
|
60
|
+
|
|
61
|
+
raise InvalidValue, "#{context} must be a string or nil"
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strong
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "excon"
|
|
@@ -6,6 +6,7 @@ require "sorbet-runtime"
|
|
|
6
6
|
require "dependabot/metadata_finders"
|
|
7
7
|
require "dependabot/metadata_finders/base"
|
|
8
8
|
require "dependabot/pub/requirement_source"
|
|
9
|
+
require "dependabot/pub/package/registry_package"
|
|
9
10
|
require "dependabot/registry_client"
|
|
10
11
|
|
|
11
12
|
module Dependabot
|
|
@@ -26,20 +27,16 @@ module Dependabot
|
|
|
26
27
|
end
|
|
27
28
|
repository_url = (source.description_string("url") || "https://pub.dev").delete_suffix("/")
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
repo = listing.dig("latest", "pubspec", "repository")
|
|
31
|
-
# The repository field did not always exist in pubspec.yaml, and some
|
|
32
|
-
# packages specify a git repository in the "homepage" field.
|
|
33
|
-
repo ||= listing.dig("latest", "pubspec", "homepage")
|
|
30
|
+
repo = repository_listing(repository_url).source_url
|
|
34
31
|
return nil unless repo
|
|
35
32
|
|
|
36
33
|
Source.from_url(repo)
|
|
37
34
|
end
|
|
38
35
|
|
|
39
|
-
sig { params(repository_url: String).returns(
|
|
36
|
+
sig { params(repository_url: String).returns(Package::RegistryPackage) }
|
|
40
37
|
def repository_listing(repository_url)
|
|
41
38
|
response = Dependabot::RegistryClient.get(url: "#{repository_url}/api/packages/#{dependency.name}")
|
|
42
|
-
|
|
39
|
+
Package::RegistryPackage.from_json(response.body)
|
|
43
40
|
end
|
|
44
41
|
end
|
|
45
42
|
end
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strong
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
require "json"
|
|
5
|
-
require "time"
|
|
6
4
|
require "excon"
|
|
7
5
|
require "nokogiri"
|
|
8
6
|
require "sorbet-runtime"
|
|
@@ -29,7 +27,7 @@ module Dependabot
|
|
|
29
27
|
sig { override.returns(T::Array[Dependabot::DependencyFile]) }
|
|
30
28
|
attr_reader :dependency_files
|
|
31
29
|
|
|
32
|
-
sig { override.returns(T::Hash[Symbol, T.
|
|
30
|
+
sig { override.returns(T::Hash[Symbol, T.anything]) }
|
|
33
31
|
attr_reader :options
|
|
34
32
|
|
|
35
33
|
sig { override.returns(T::Array[Dependabot::Credential]) }
|
|
@@ -42,7 +40,7 @@ module Dependabot
|
|
|
42
40
|
credentials: T::Array[Dependabot::Credential],
|
|
43
41
|
ignored_versions: T::Array[String],
|
|
44
42
|
security_advisories: T::Array[Dependabot::SecurityAdvisory],
|
|
45
|
-
options: T::Hash[Symbol, T.
|
|
43
|
+
options: T::Hash[Symbol, T.anything]
|
|
46
44
|
)
|
|
47
45
|
.void
|
|
48
46
|
end
|
|
@@ -62,55 +60,33 @@ module Dependabot
|
|
|
62
60
|
@options = options
|
|
63
61
|
end
|
|
64
62
|
|
|
65
|
-
sig { returns(T::Array[
|
|
63
|
+
sig { returns(T::Array[DependencyServicesResult::ReportEntry]) }
|
|
66
64
|
def report
|
|
67
65
|
@report ||= T.let(
|
|
68
66
|
dependency_services_report,
|
|
69
|
-
T.nilable(T::Array[
|
|
67
|
+
T.nilable(T::Array[DependencyServicesResult::ReportEntry])
|
|
70
68
|
)
|
|
71
69
|
end
|
|
72
70
|
|
|
73
|
-
sig { returns(T
|
|
71
|
+
sig { returns(T::Array[Dependabot::Package::PackageRelease]) }
|
|
74
72
|
def package_details_metadata
|
|
75
73
|
Dependabot.logger.info("Initializing package metadata for \"#{@dependency.name}\"")
|
|
76
74
|
|
|
77
75
|
response = fetch_package_metadata(dependency)
|
|
78
76
|
return [] if response.status >= 500
|
|
79
77
|
|
|
80
|
-
versions = JSON.parse(response.body).fetch("versions", [])
|
|
81
|
-
|
|
82
78
|
# Build the full list up front. If any release can't be parsed (e.g. a
|
|
83
79
|
# missing or invalid publish date) the partial result is discarded, so
|
|
84
80
|
# callers can treat a non-empty list as a complete, trustworthy snapshot
|
|
85
81
|
# and an empty list as "no usable metadata".
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
version: v["version"],
|
|
89
|
-
publish_date: Time.parse(v["published"])
|
|
90
|
-
)
|
|
91
|
-
end
|
|
92
|
-
rescue JSON::ParserError
|
|
82
|
+
RegistryPackage.from_json(response.body).releases
|
|
83
|
+
rescue JsonValueParser::InvalidValue
|
|
93
84
|
Dependabot.logger.error("Failed to parse package metadata")
|
|
94
85
|
[]
|
|
95
86
|
rescue StandardError => e
|
|
96
87
|
Dependabot.logger.error("Failed to fetch package metadata #{e.message}")
|
|
97
88
|
[]
|
|
98
89
|
end
|
|
99
|
-
|
|
100
|
-
private
|
|
101
|
-
|
|
102
|
-
sig do
|
|
103
|
-
params(
|
|
104
|
-
version: String,
|
|
105
|
-
publish_date: T.nilable(Time)
|
|
106
|
-
).returns(Dependabot::Package::PackageRelease)
|
|
107
|
-
end
|
|
108
|
-
def package_release(version:, publish_date: nil)
|
|
109
|
-
Dependabot::Package::PackageRelease.new(
|
|
110
|
-
version: Pub::Version.new(version),
|
|
111
|
-
released_at: publish_date
|
|
112
|
-
)
|
|
113
|
-
end
|
|
114
90
|
end
|
|
115
91
|
end
|
|
116
92
|
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# typed: strong
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "time"
|
|
5
|
+
require "sorbet-runtime"
|
|
6
|
+
require "dependabot/package/package_release"
|
|
7
|
+
require "dependabot/pub/json_value_parser"
|
|
8
|
+
require "dependabot/pub/version"
|
|
9
|
+
|
|
10
|
+
module Dependabot
|
|
11
|
+
module Pub
|
|
12
|
+
module Package
|
|
13
|
+
class RegistryPackage
|
|
14
|
+
extend T::Sig
|
|
15
|
+
|
|
16
|
+
sig { params(content: String).returns(RegistryPackage) }
|
|
17
|
+
def self.from_json(content)
|
|
18
|
+
new(JsonValueParser.object(JsonValueParser.parse(content, "Pub package"), "Pub package"))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
sig { params(data: JsonValueParser::ObjectHash).void }
|
|
22
|
+
def initialize(data)
|
|
23
|
+
@data = data
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
sig { returns(T::Array[Dependabot::Pub::Version]) }
|
|
27
|
+
def versions
|
|
28
|
+
version_entries(@data["versions"]).map do |fields|
|
|
29
|
+
Dependabot::Pub::Version.new(JsonValueParser.string(fields["version"], "Pub package version"))
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
sig { returns(T::Array[Dependabot::Package::PackageRelease]) }
|
|
34
|
+
def releases
|
|
35
|
+
version_entries(@data.fetch("versions", [])).map do |fields|
|
|
36
|
+
Dependabot::Package::PackageRelease.new(
|
|
37
|
+
version: Dependabot::Pub::Version.new(JsonValueParser.string(fields["version"], "Pub package version")),
|
|
38
|
+
released_at: Time.parse(JsonValueParser.string(fields["published"], "Pub package published"))
|
|
39
|
+
)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
sig { returns(T.nilable(String)) }
|
|
44
|
+
def source_url
|
|
45
|
+
latest = JsonValueParser.optional_object(@data["latest"], "Pub package latest")
|
|
46
|
+
return unless latest
|
|
47
|
+
|
|
48
|
+
pubspec = JsonValueParser.optional_object(latest["pubspec"], "Pub package latest.pubspec")
|
|
49
|
+
return unless pubspec
|
|
50
|
+
|
|
51
|
+
value = pubspec["repository"] || pubspec["homepage"]
|
|
52
|
+
# Preserve the existing false-as-absent behavior of optional source metadata.
|
|
53
|
+
JsonValueParser.optional_string(value || nil, "Pub package repository or homepage")
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
sig { params(value: Object).returns(T::Array[JsonValueParser::ObjectHash]) }
|
|
59
|
+
def version_entries(value)
|
|
60
|
+
JsonValueParser.array(value, "Pub package versions").each_with_index.map do |entry, index|
|
|
61
|
+
JsonValueParser.object(entry, "Pub package versions[#{index}]")
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# typed:
|
|
1
|
+
# typed: strong
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require "excon"
|
|
@@ -27,7 +27,7 @@ module Dependabot
|
|
|
27
27
|
credentials: T::Array[Dependabot::Credential],
|
|
28
28
|
ignored_versions: T::Array[String],
|
|
29
29
|
security_advisories: T::Array[Dependabot::SecurityAdvisory],
|
|
30
|
-
options: T::Hash[Symbol, T.
|
|
30
|
+
options: T::Hash[Symbol, T.anything],
|
|
31
31
|
cooldown_options: T.nilable(Dependabot::Package::ReleaseCooldownOptions)
|
|
32
32
|
).void
|
|
33
33
|
end
|
|
@@ -49,10 +49,10 @@ module Dependabot
|
|
|
49
49
|
@cooldown_options = cooldown_options
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
-
sig { returns(
|
|
52
|
+
sig { returns(DependencyServicesResult::ReportEntry) }
|
|
53
53
|
def current_report
|
|
54
54
|
@current_report ||= T.let(
|
|
55
|
-
|
|
55
|
+
DependencyServicesResult.find_report(
|
|
56
56
|
PackageDetailsFetcher.new(
|
|
57
57
|
dependency: dependency,
|
|
58
58
|
dependency_files: dependency_files,
|
|
@@ -60,15 +60,16 @@ module Dependabot
|
|
|
60
60
|
ignored_versions: ignored_versions,
|
|
61
61
|
security_advisories: security_advisories,
|
|
62
62
|
options: options
|
|
63
|
-
).report
|
|
63
|
+
).report,
|
|
64
|
+
dependency.name
|
|
64
65
|
),
|
|
65
|
-
T.nilable(
|
|
66
|
+
T.nilable(DependencyServicesResult::ReportEntry)
|
|
66
67
|
)
|
|
67
68
|
end
|
|
68
69
|
|
|
69
70
|
sig { returns(T.nilable(String)) }
|
|
70
71
|
def latest_version
|
|
71
|
-
latest_version = current_report
|
|
72
|
+
latest_version = current_report.latest
|
|
72
73
|
return nil unless latest_version
|
|
73
74
|
|
|
74
75
|
filter_cooldown_versions(latest_version)
|
|
@@ -76,36 +77,36 @@ module Dependabot
|
|
|
76
77
|
|
|
77
78
|
sig { returns(T.nilable(String)) }
|
|
78
79
|
def latest_resolvable_version
|
|
79
|
-
|
|
80
|
-
return nil unless
|
|
80
|
+
version = latest_resolvable_update&.version
|
|
81
|
+
return nil unless version
|
|
81
82
|
|
|
82
|
-
filter_cooldown_versions(
|
|
83
|
+
filter_cooldown_versions(version)
|
|
83
84
|
end
|
|
84
85
|
|
|
85
86
|
sig { returns(T.nilable(String)) }
|
|
86
87
|
def latest_resolvable_version_with_no_unlock
|
|
87
|
-
|
|
88
|
-
return nil unless
|
|
88
|
+
version = current_report.compatible.find { |entry| entry.name == dependency.name }&.version
|
|
89
|
+
return nil unless version
|
|
89
90
|
|
|
90
|
-
filter_cooldown_versions(
|
|
91
|
+
filter_cooldown_versions(version)
|
|
91
92
|
end
|
|
92
93
|
|
|
93
94
|
sig { returns(T.nilable(String)) }
|
|
94
95
|
def latest_version_resolvable_with_full_unlock
|
|
95
|
-
|
|
96
|
-
return nil unless
|
|
96
|
+
version = full_unlock_updates.find { |entry| entry.name == dependency.name }&.version
|
|
97
|
+
return nil unless version
|
|
97
98
|
|
|
98
|
-
filter_cooldown_versions(
|
|
99
|
+
filter_cooldown_versions(version)
|
|
99
100
|
end
|
|
100
101
|
|
|
101
|
-
sig { returns(T
|
|
102
|
-
def
|
|
103
|
-
current_report
|
|
102
|
+
sig { returns(T::Array[DependencyServicesResult::DependencyUpdate]) }
|
|
103
|
+
def full_unlock_updates
|
|
104
|
+
current_report.multi_breaking
|
|
104
105
|
end
|
|
105
106
|
|
|
106
|
-
sig { returns(T.
|
|
107
|
-
def
|
|
108
|
-
current_report
|
|
107
|
+
sig { returns(T.nilable(DependencyServicesResult::DependencyUpdate)) }
|
|
108
|
+
def latest_resolvable_update
|
|
109
|
+
current_report.single_breaking.find { |entry| entry.name == dependency.name }
|
|
109
110
|
end
|
|
110
111
|
|
|
111
112
|
private
|
|
@@ -286,7 +287,7 @@ module Dependabot
|
|
|
286
287
|
sig { returns(T::Array[Dependabot::SecurityAdvisory]) }
|
|
287
288
|
attr_reader :security_advisories
|
|
288
289
|
|
|
289
|
-
sig { returns(T::Hash[Symbol, T.
|
|
290
|
+
sig { returns(T::Hash[Symbol, T.anything]) }
|
|
290
291
|
attr_reader :options
|
|
291
292
|
|
|
292
293
|
sig { returns(T.nilable(Dependabot::Package::ReleaseCooldownOptions)) }
|
|
@@ -21,7 +21,10 @@ module Dependabot
|
|
|
21
21
|
|
|
22
22
|
sig { override.returns(T.nilable(T.any(String, Dependabot::Version))) }
|
|
23
23
|
def latest_version
|
|
24
|
-
|
|
24
|
+
candidate = version_report.latest_version
|
|
25
|
+
return nil unless candidate
|
|
26
|
+
|
|
27
|
+
version = version_unless_ignored(candidate, current_version: dependency.version)
|
|
25
28
|
|
|
26
29
|
raise AllVersionsIgnored if version.nil? && @raise_on_ignored
|
|
27
30
|
|
|
@@ -48,10 +51,12 @@ module Dependabot
|
|
|
48
51
|
e = dependency_services_smallest_update
|
|
49
52
|
return nil if e.nil?
|
|
50
53
|
|
|
51
|
-
upgrade = e.find { |u| u
|
|
54
|
+
upgrade = e.find { |u| u.name == dependency.name }
|
|
55
|
+
|
|
56
|
+
version = upgrade&.version
|
|
57
|
+
return unless version
|
|
52
58
|
|
|
53
|
-
version
|
|
54
|
-
T.cast(version_unless_ignored(version), Dependabot::Version)
|
|
59
|
+
T.cast(version_unless_ignored(version), T.nilable(Dependabot::Version))
|
|
55
60
|
end
|
|
56
61
|
|
|
57
62
|
sig { override.returns(T.nilable(Dependabot::Version)) }
|
|
@@ -80,16 +85,16 @@ module Dependabot
|
|
|
80
85
|
|
|
81
86
|
# Ideally we would like to do any upgrade that migrates away from the vulnerability
|
|
82
87
|
# but this method can only return a single requirement udate.
|
|
83
|
-
breaking_changes = updates&.filter { |d| d
|
|
88
|
+
breaking_changes = updates&.filter { |d| d.previous_constraint != d.constraint_bumped_if_needed }
|
|
84
89
|
|
|
85
90
|
# This security update would require unlocking other packages, which is not currently supported.
|
|
86
91
|
# Because of that, return original requirements, so that no requirements are actually updated and
|
|
87
92
|
# the error bubbles up as security_update_not_possible to the user.
|
|
88
93
|
return dependency.requirements if breaking_changes&.size&.> 1
|
|
89
94
|
|
|
90
|
-
updates&.find { |u| u
|
|
95
|
+
updates&.find { |u| u.name == dependency.name }
|
|
91
96
|
else
|
|
92
|
-
version_report.
|
|
97
|
+
version_report.latest_resolvable_update
|
|
93
98
|
end
|
|
94
99
|
return [] unless entry
|
|
95
100
|
|
|
@@ -100,7 +105,7 @@ module Dependabot
|
|
|
100
105
|
private
|
|
101
106
|
|
|
102
107
|
# rubocop:disable Metrics/AbcSize
|
|
103
|
-
sig { returns(T.nilable(T::Array[
|
|
108
|
+
sig { returns(T.nilable(T::Array[DependencyServicesResult::DependencyUpdate])) }
|
|
104
109
|
def dependency_services_smallest_update
|
|
105
110
|
return @smallest_update if @smallest_update
|
|
106
111
|
|
|
@@ -129,10 +134,12 @@ module Dependabot
|
|
|
129
134
|
}
|
|
130
135
|
]
|
|
131
136
|
}
|
|
132
|
-
report =
|
|
137
|
+
report = DependencyServicesResult.report_from_json(
|
|
138
|
+
run_dependency_services("report", stdin_data: JSON.generate(input))
|
|
139
|
+
)
|
|
133
140
|
@smallest_update = T.let(
|
|
134
|
-
report.
|
|
135
|
-
T.nilable(T::Array[
|
|
141
|
+
DependencyServicesResult.find_report(report.dependencies, dependency.name).smallest_update,
|
|
142
|
+
T.nilable(T::Array[DependencyServicesResult::DependencyUpdate])
|
|
136
143
|
)
|
|
137
144
|
end
|
|
138
145
|
# rubocop:enable Metrics/AbcSize
|
|
@@ -184,11 +191,13 @@ module Dependabot
|
|
|
184
191
|
report_section = if vulnerable?
|
|
185
192
|
dependency_services_smallest_update
|
|
186
193
|
else
|
|
187
|
-
version_report.
|
|
194
|
+
version_report.full_unlock_updates
|
|
188
195
|
end
|
|
196
|
+
return [] unless report_section
|
|
197
|
+
|
|
189
198
|
# We only expose non-transitive dependencies here...
|
|
190
199
|
direct_deps = report_section.reject do |d|
|
|
191
|
-
d
|
|
200
|
+
d.kind == "transitive"
|
|
192
201
|
end
|
|
193
202
|
direct_deps.map do |d|
|
|
194
203
|
parse_updated_dependency(d, resolved_requirements_update_strategy)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dependabot-pub
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.399.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.399.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.399.0
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: debug
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -242,13 +242,16 @@ extensions: []
|
|
|
242
242
|
extra_rdoc_files: []
|
|
243
243
|
files:
|
|
244
244
|
- lib/dependabot/pub.rb
|
|
245
|
+
- lib/dependabot/pub/dependency_services_result.rb
|
|
245
246
|
- lib/dependabot/pub/file_fetcher.rb
|
|
246
247
|
- lib/dependabot/pub/file_parser.rb
|
|
247
248
|
- lib/dependabot/pub/file_updater.rb
|
|
248
249
|
- lib/dependabot/pub/helpers.rb
|
|
250
|
+
- lib/dependabot/pub/json_value_parser.rb
|
|
249
251
|
- lib/dependabot/pub/language.rb
|
|
250
252
|
- lib/dependabot/pub/metadata_finder.rb
|
|
251
253
|
- lib/dependabot/pub/package/package_details_fetcher.rb
|
|
254
|
+
- lib/dependabot/pub/package/registry_package.rb
|
|
252
255
|
- lib/dependabot/pub/package_manager.rb
|
|
253
256
|
- lib/dependabot/pub/requirement.rb
|
|
254
257
|
- lib/dependabot/pub/requirement_source.rb
|
|
@@ -260,7 +263,7 @@ licenses:
|
|
|
260
263
|
- MIT
|
|
261
264
|
metadata:
|
|
262
265
|
bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
|
|
263
|
-
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.
|
|
266
|
+
changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.399.0
|
|
264
267
|
rdoc_options: []
|
|
265
268
|
require_paths:
|
|
266
269
|
- lib
|