dependabot-pub 0.227.0 → 0.229.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8d6b98f865064a2c3ed99dd01f82474e78b0e6bd11f9af0205bbe8d664ebac92
4
- data.tar.gz: dff1e05b143ad48e91dfd895931d02739ed84b2758c8163cd9417738de25c881
3
+ metadata.gz: daace877e528954fb85b689b497de5ecd8a6609d073a33656f8d3d5e2f08a5e7
4
+ data.tar.gz: c9a721320ac13c603ad5d3dcb657049ba6d3c1dfdfe26608577838631030c578
5
5
  SHA512:
6
- metadata.gz: e68671a3ed56b6ac5b8a2129fe663f0a8d6f7c7535bbf3d625dd7e5565c3fb51dad52e582b1b24ce3bcc3a57662825803e080ed1531dae2ad84cf5261d15ea7b
7
- data.tar.gz: 6e7c8cba2a24407a1b4acf842bbc81427b085de0f5e64854c7ad849dd585f07ba68e81ee116121f959086a2ca073c2292dfcee5c6eef1599e4e7065ae385fbbd
6
+ metadata.gz: e96e24f1ae88cfdc7371c3dff527969b77bbe9b7f6560162e02104aca7ed8e5eaefe070ce8b1354f268191e143b2ec94ec47abb5b43aa4af65e4f223757fd80d
7
+ data.tar.gz: c9df124c58bbb7b679539060d73ea511a91b8c193d5ed97bc05497952963fc7bd185f2649ddf4bf0c2d54746a3939041ac7e7c774ed7cd7dc2b3afff4c2a7395
@@ -17,13 +17,12 @@ module Dependabot
17
17
  end
18
18
 
19
19
  def self.run_infer_sdk_versions(dir, url: nil)
20
- stdout, _, status = Dir.chdir dir do
21
- Open3.capture3(
22
- {},
23
- File.join(pub_helpers_path, "infer_sdk_versions"),
24
- *("--flutter-releases-url=#{url}" if url)
25
- )
26
- end
20
+ stdout, _, status = Open3.capture3(
21
+ {},
22
+ File.join(pub_helpers_path, "infer_sdk_versions"),
23
+ *("--flutter-releases-url=#{url}" if url),
24
+ chdir: dir
25
+ )
27
26
  return nil unless status.success?
28
27
 
29
28
  JSON.parse(stdout)
@@ -35,6 +34,60 @@ module Dependabot
35
34
  JSON.parse(run_dependency_services("list"))["dependencies"]
36
35
  end
37
36
 
37
+ def repository_url(dependency)
38
+ source = dependency.requirements&.first&.dig(:source)
39
+ source&.dig("description", "url") || options[:pub_hosted_url] || "https://pub.dev"
40
+ end
41
+
42
+ def fetch_package_listing(dependency)
43
+ # Because we get the security_advisories as a set of constraints, we
44
+ # fetch the list of all versions and filter them to a list of vulnerable
45
+ # versions.
46
+ #
47
+ # Ideally we would like the helper to be the only one doing requests to
48
+ # the repository. But this should work for now:
49
+ response = Dependabot::RegistryClient.get(url: "#{repository_url(dependency)}/api/packages/#{dependency.name}")
50
+ JSON.parse(response.body)
51
+ end
52
+
53
+ def available_versions(dependency)
54
+ fetch_package_listing(dependency)["versions"].map do |v|
55
+ Dependabot::Pub::Version.new(v["version"])
56
+ end
57
+ end
58
+
59
+ def dependency_services_smallest_update
60
+ return @smallest_update if @smallest_update
61
+
62
+ security_advisories.each do |a|
63
+ # Sanity check, that we only get the advisories for a single package
64
+ # at a time. If we got all advisories for all current dependencies,
65
+ # the helper would be able to handle it, but we would need a better
66
+ # way to find the repository url.
67
+ if a.dependency_name != dependency.name
68
+ raise "Only expected advisories for #{dependency.name} got for #{a.dependency_name}"
69
+ end
70
+ end
71
+ vulnerable_versions = available_versions(dependency).select do |v|
72
+ security_advisories.any? { |a| a.vulnerable?(v) }
73
+ end
74
+ input = {
75
+ # For "smallest update" we don't cache the report to be shared between
76
+ # dependencies, but run a specific report for the current dependency.
77
+ target: dependency.name,
78
+ disallowed:
79
+ [
80
+ {
81
+ name: dependency.name,
82
+ url: repository_url(dependency),
83
+ versions: vulnerable_versions.map { |v| { range: v.to_s } }
84
+ }
85
+ ]
86
+ }
87
+ report = JSON.parse(run_dependency_services("report", stdin_data: JSON.generate(input)))["dependencies"]
88
+ @smallest_update = report.find { |d| d["name"] == dependency.name }["smallestUpdate"]
89
+ end
90
+
38
91
  def dependency_services_report
39
92
  sha256 = Digest::SHA256.new
40
93
  dependency_files.each do |f|
@@ -45,16 +98,16 @@ module Dependabot
45
98
  cache_file = "/tmp/report-#{hash}-pid-#{Process.pid}.json"
46
99
  return JSON.parse(File.read(cache_file)) if File.file?(cache_file)
47
100
 
48
- report = JSON.parse(run_dependency_services("report"))["dependencies"]
101
+ report = JSON.parse(run_dependency_services("report", stdin_data: ""))["dependencies"]
49
102
  File.write(cache_file, JSON.generate(report))
50
103
  report
51
104
  end
52
105
 
53
106
  def dependency_services_apply(dependency_changes)
54
- run_dependency_services("apply", stdin_data: dependencies_to_json(dependency_changes)) do
107
+ run_dependency_services("apply", stdin_data: dependencies_to_json(dependency_changes)) do |temp_dir|
55
108
  dependency_files.map do |f|
56
109
  updated_file = f.dup
57
- updated_file.content = File.read(f.name)
110
+ updated_file.content = File.read(File.join(temp_dir, f.name))
58
111
  updated_file
59
112
  end
60
113
  end
@@ -108,31 +161,29 @@ module Dependabot
108
161
  ## Detects the right flutter release to use for the pubspec.yaml.
109
162
  ## Then checks it out if it is not already.
110
163
  ## Returns the sdk versions
111
- def ensure_right_flutter_release
112
- @ensure_right_flutter_release ||= begin
113
- versions = Helpers.run_infer_sdk_versions(
114
- File.join(Dir.pwd, dependency_files.first.directory),
115
- url: options[:flutter_releases_url]
116
- )
117
- flutter_ref =
118
- if versions
119
- Dependabot.logger.info(
120
- "Installing the Flutter SDK version: #{versions['flutter']} " \
121
- "from channel #{versions['channel']} with Dart #{versions['dart']}"
122
- )
123
- "refs/tags/#{versions['flutter']}"
124
- else
125
- Dependabot.logger.info(
126
- "Failed to infer the flutter version. Attempting to use latest stable release."
127
- )
128
- # Choose the 'stable' version if the tool failed to infer a version.
129
- "stable"
130
- end
131
-
132
- check_out_flutter_ref flutter_ref
133
- run_flutter_doctor
134
- run_flutter_version
135
- end
164
+ def ensure_right_flutter_release(dir)
165
+ versions = Helpers.run_infer_sdk_versions(
166
+ File.join(dir, dependency_files.first.directory),
167
+ url: options[:flutter_releases_url]
168
+ )
169
+ flutter_ref =
170
+ if versions
171
+ Dependabot.logger.info(
172
+ "Installing the Flutter SDK version: #{versions['flutter']} " \
173
+ "from channel #{versions['channel']} with Dart #{versions['dart']}"
174
+ )
175
+ "refs/tags/#{versions['flutter']}"
176
+ else
177
+ Dependabot.logger.info(
178
+ "Failed to infer the flutter version. Attempting to use latest stable release."
179
+ )
180
+ # Choose the 'stable' version if the tool failed to infer a version.
181
+ "stable"
182
+ end
183
+
184
+ check_out_flutter_ref flutter_ref
185
+ run_flutter_doctor
186
+ run_flutter_version
136
187
  end
137
188
 
138
189
  def run_flutter_doctor
@@ -181,13 +232,13 @@ module Dependabot
181
232
  end
182
233
 
183
234
  def run_dependency_services(command, stdin_data: nil)
184
- SharedHelpers.in_a_temporary_directory do
235
+ SharedHelpers.in_a_temporary_directory do |temp_dir|
185
236
  dependency_files.each do |f|
186
- in_path_name = File.join(Dir.pwd, f.directory, f.name)
237
+ in_path_name = File.join(temp_dir, f.directory, f.name)
187
238
  FileUtils.mkdir_p File.dirname(in_path_name)
188
239
  File.write(in_path_name, f.content)
189
240
  end
190
- sdk_versions = ensure_right_flutter_release
241
+ sdk_versions = ensure_right_flutter_release(temp_dir)
191
242
  SharedHelpers.with_git_configured(credentials: credentials) do
192
243
  env = {
193
244
  "CI" => "true",
@@ -198,18 +249,19 @@ module Dependabot
198
249
  # TODO(sigurdm): Would be nice to have a better handle for fixing the dart sdk version.
199
250
  "_PUB_TEST_SDK_VERSION" => sdk_versions["dart"]
200
251
  }
201
- Dir.chdir File.join(Dir.pwd, dependency_files.first.directory) do
202
- stdout, stderr, status = Open3.capture3(
203
- env.compact,
204
- File.join(Helpers.pub_helpers_path, "dependency_services"),
205
- command,
206
- stdin_data: stdin_data
207
- )
208
- raise Dependabot::DependabotError, "dependency_services failed: #{stderr}" unless status.success?
209
- return stdout unless block_given?
210
-
211
- yield
212
- end
252
+ command_dir = File.join(temp_dir, dependency_files.first.directory)
253
+
254
+ stdout, stderr, status = Open3.capture3(
255
+ env.compact,
256
+ File.join(Helpers.pub_helpers_path, "dependency_services"),
257
+ command,
258
+ stdin_data: stdin_data,
259
+ chdir: command_dir
260
+ )
261
+ raise Dependabot::DependabotError, "dependency_services failed: #{stderr}" unless status.success?
262
+ return stdout unless block_given?
263
+
264
+ yield command_dir
213
265
  end
214
266
  end
215
267
  end
@@ -52,7 +52,7 @@ module Dependabot
52
52
 
53
53
  def to_s
54
54
  if @raw_constraint.nil?
55
- as_list.join ", "
55
+ as_list.join " "
56
56
  else
57
57
  @raw_constraint
58
58
  end
@@ -42,26 +42,39 @@ module Dependabot
42
42
  end
43
43
 
44
44
  def lowest_security_fix_version
45
- # TODO: Pub lacks a lowest-non-vulnerable version strategy, for now we simply bump to latest resolvable:
46
- # https://github.com/dependabot/dependabot-core/issues/5391
47
- relevant_version = latest_resolvable_version
48
- return unless relevant_version
49
-
50
- # NOTE: in other ecosystems, the native helpers return a list of possible versions, to which we apply
51
- # post-filtering. Ideally we move toward a world where we hand the native helper a list of ignored versions
52
- # and possibly a flag indicating "use min version rather than max". The pub team is interested in supporting
53
- # that. But in the meantime for internal consistency with other dependabot ecosystem implementations I kept
54
- # `relevant_versions` as an array.
55
- relevant_versions = [relevant_version]
56
- relevant_versions = Dependabot::UpdateCheckers::VersionFilters.filter_vulnerable_versions(relevant_versions,
57
- security_advisories)
58
- relevant_versions.min
45
+ # Don't attempt to do security updates for git dependencies.
46
+ return nil if git_revision? dependency.version
47
+ # If the current version is not vulnerable, we stay on it.
48
+ return version_unless_ignored dependency.version unless vulnerable?
49
+
50
+ e = dependency_services_smallest_update
51
+ return nil if e.nil?
52
+
53
+ upgrade = e.find { |u| u["name"] == dependency.name }
54
+
55
+ version = upgrade["version"]
56
+ version_unless_ignored(version)
59
57
  end
60
58
 
61
59
  def updated_requirements
62
60
  # Requirements that need to be changed, if obtain:
63
- # latest_resolvable_version
64
- entry = current_report["singleBreaking"].find { |d| d["name"] == dependency.name }
61
+ # latest_resolvable_version or lowest_security_fix_version
62
+ entry = if vulnerable?
63
+ updates = dependency_services_smallest_update
64
+
65
+ # Ideally we would like to do any upgrade that migrates away from the vulnerability
66
+ # but this method can only return a single requirement udate.
67
+ breaking_changes = updates.filter { |d| d["previousConstraint"] != d["constraintBumpedIfNeeded"] }
68
+
69
+ # This security update would require unlocking other packages, which is not currently supported.
70
+ # Because of that, return original requirements, so that no requirements are actually updated and
71
+ # the error bubbles up as security_update_not_possible to the user.
72
+ return dependency.requirements if breaking_changes.size > 1
73
+
74
+ updates.find { |u| u["name"] == dependency.name }
75
+ else
76
+ current_report["singleBreaking"].find { |d| d["name"] == dependency.name }
77
+ end
65
78
  return unless entry
66
79
 
67
80
  parse_updated_dependency(entry, requirements_update_strategy: resolved_requirements_update_strategy).
@@ -108,8 +121,13 @@ module Dependabot
108
121
  end
109
122
 
110
123
  def updated_dependencies_after_full_unlock
124
+ report_section = if vulnerable?
125
+ dependency_services_smallest_update
126
+ else
127
+ current_report["multiBreaking"]
128
+ end
111
129
  # We only expose non-transitive dependencies here...
112
- direct_deps = current_report["multiBreaking"].reject do |d|
130
+ direct_deps = report_section.reject do |d|
113
131
  d["kind"] == "transitive"
114
132
  end
115
133
  direct_deps.map do |d|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-pub
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.227.0
4
+ version: 0.229.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-18 00:00:00.000000000 Z
11
+ date: 2023-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dependabot-common
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.227.0
19
+ version: 0.229.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.227.0
26
+ version: 0.229.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: webrick
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -128,14 +128,14 @@ dependencies:
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: 1.50.0
131
+ version: 1.56.0
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: 1.50.0
138
+ version: 1.56.0
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: rubocop-performance
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -214,7 +214,7 @@ licenses:
214
214
  - Nonstandard
215
215
  metadata:
216
216
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
217
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.227.0
217
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.229.0
218
218
  post_install_message:
219
219
  rdoc_options: []
220
220
  require_paths: