dependabot-pub 0.227.0 → 0.228.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8d6b98f865064a2c3ed99dd01f82474e78b0e6bd11f9af0205bbe8d664ebac92
4
- data.tar.gz: dff1e05b143ad48e91dfd895931d02739ed84b2758c8163cd9417738de25c881
3
+ metadata.gz: 89c3dd639ade3b8c89f0b9ef43904d6d3974b3828c44cef691f9fbb706d3e958
4
+ data.tar.gz: a2b03d36175babea90b1d610a5344144efefc864f4ca6096498af13751a79e0e
5
5
  SHA512:
6
- metadata.gz: e68671a3ed56b6ac5b8a2129fe663f0a8d6f7c7535bbf3d625dd7e5565c3fb51dad52e582b1b24ce3bcc3a57662825803e080ed1531dae2ad84cf5261d15ea7b
7
- data.tar.gz: 6e7c8cba2a24407a1b4acf842bbc81427b085de0f5e64854c7ad849dd585f07ba68e81ee116121f959086a2ca073c2292dfcee5c6eef1599e4e7065ae385fbbd
6
+ metadata.gz: fe5f28e407052da38c627cc4852ff111375027b6532e739599bec42373cc1230b1e712c2f7759080fa74ad601047f271990cda03d74e90a1aa1ffb61da681615
7
+ data.tar.gz: 0d2726e86605abd222592a526d12e3ccda488405ed583c9ec15b544143a752e9e61390ae513cdaee281aeb0627e0681972b1b9f7a1dcabeb520dc309e5da3b95
@@ -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.228.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-25 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.228.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.228.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.228.0
218
218
  post_install_message:
219
219
  rdoc_options: []
220
220
  require_paths: