dependabot-cargo 0.254.0 → 0.255.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: 515ba13e5a17c85e0d1c425689323b57e96207d4fa690e5d7bb512d504c8ca1f
4
- data.tar.gz: 92c17353748806f39f0d71aa662d4d9eca9a3446ab4b176e336ece75aa0d5515
3
+ metadata.gz: 1e8a251c7b5361b8d4aae2d7c1675a144c29c375574e23f2ecd531dbe8c9e6d5
4
+ data.tar.gz: b5c60f7a5ce3f50998e902524210dbb34790fcc72f098020d067b274948908b0
5
5
  SHA512:
6
- metadata.gz: 8ff8cfbaeb15b891945b6494f37b6e1b1d022dcc2aabc76ece9c110b231eb528af18a3e08d9d55ee6f12e395ab1e47e46492eb54cf8e079fa139bd4d3eb182b3
7
- data.tar.gz: ba1efb9eae5aebb5e49cdbdb4de29ef4d10e3e3e7659f2872faa2e4cf279b7a671db4295276dfeac81bebddec22a9454ca72cabba3fbc54cd5e3162add2c08ce
6
+ metadata.gz: 11d9b26fccaa6d1a1008c5550fd377fa70b0836f00d34db911eaa76102111663974b325b5dc9d603629b46787b3408340df81c2cba7ad8091d0a3bf970b4a5cd
7
+ data.tar.gz: 41f248cf390a8b9e864ad6ae77115f49af50bf0c1091de05bcead3f735556128a65ec7bcde9ce28bb669089ee45160b72757c007c5ace6d7258fcb20032dff80
@@ -46,7 +46,7 @@ module Dependabot
46
46
 
47
47
  sig { override.returns(T::Array[DependencyFile]) }
48
48
  def fetch_files
49
- fetched_files = []
49
+ fetched_files = T.let([], T::Array[DependencyFile])
50
50
  fetched_files << cargo_toml
51
51
  fetched_files << cargo_lock if cargo_lock
52
52
  fetched_files << cargo_config if cargo_config
@@ -327,7 +327,10 @@ module Dependabot
327
327
  def cargo_config
328
328
  return @cargo_config if defined?(@cargo_config)
329
329
 
330
- @cargo_config = fetch_file_if_present(".cargo/config.toml")
330
+ @cargo_config = fetch_support_file(".cargo/config.toml")
331
+
332
+ @cargo_config ||= fetch_support_file(".cargo/config")
333
+ &.tap { |f| f.name = ".cargo/config.toml" }
331
334
  end
332
335
 
333
336
  def rust_toolchain
@@ -2,6 +2,7 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "toml-rb"
5
+ require "pathname"
5
6
 
6
7
  require "dependabot/dependency"
7
8
  require "dependabot/file_parsers"
@@ -9,6 +10,7 @@ require "dependabot/file_parsers/base"
9
10
  require "dependabot/cargo/requirement"
10
11
  require "dependabot/cargo/version"
11
12
  require "dependabot/errors"
13
+ require "dependabot/cargo/registry_fetcher"
12
14
 
13
15
  # Relevant Cargo docs can be found at:
14
16
  # - https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -162,8 +164,77 @@ module Dependabot
162
164
  raise "Unexpected dependency declaration: #{declaration}" unless declaration.is_a?(Hash)
163
165
 
164
166
  return git_source_details(declaration) if declaration["git"]
167
+ return { type: "path" } if declaration["path"]
165
168
 
166
- { type: "path" } if declaration["path"]
169
+ registry_source_details(declaration)
170
+ end
171
+
172
+ def registry_source_details(declaration)
173
+ registry_name = declaration["registry"]
174
+ return if registry_name.nil?
175
+
176
+ index_url = cargo_config_field("registries.#{registry_name}.index")
177
+ if index_url.nil?
178
+ raise "Registry index for #{registry_name} must be defined via " \
179
+ "cargo config"
180
+ end
181
+
182
+ if index_url.start_with?("sparse+")
183
+ sparse_registry_source_details(registry_name, index_url)
184
+ else
185
+ source = Source.from_url(index_url)
186
+ registry_fetcher = RegistryFetcher.new(
187
+ source: T.must(source),
188
+ credentials: credentials
189
+ )
190
+
191
+ {
192
+ type: "registry",
193
+ name: registry_name,
194
+ index: index_url,
195
+ dl: registry_fetcher.dl,
196
+ api: registry_fetcher.api
197
+ }
198
+ end
199
+ end
200
+
201
+ def sparse_registry_source_details(registry_name, index_url)
202
+ token = credentials.find do |cred|
203
+ cred["type"] == "cargo_registry" && cred["registry"] == registry_name
204
+ end&.fetch("token", nil)
205
+ # Fallback to configuration in the environment if available
206
+ token ||= cargo_config_from_env("registries.#{registry_name}.token")
207
+
208
+ headers = {}
209
+ headers["Authorization"] = "Token #{token}" if token
210
+
211
+ url = index_url.delete_prefix("sparse+")
212
+ url << "/" unless url.end_with?("/")
213
+ url << "config.json"
214
+ config_json = JSON.parse(RegistryClient.get(url: url, headers: headers).body)
215
+
216
+ {
217
+ type: "registry",
218
+ name: registry_name,
219
+ index: index_url,
220
+ dl: config_json["dl"],
221
+ api: config_json["api"]
222
+ }
223
+ end
224
+
225
+ # Looks up dotted key name in cargo config
226
+ # e.g. "registries.my_registry.index"
227
+ def cargo_config_field(key_name)
228
+ cargo_config_from_env(key_name) || cargo_config_from_file(key_name)
229
+ end
230
+
231
+ def cargo_config_from_env(key_name)
232
+ env_var = "CARGO_#{key_name.upcase.tr('-.', '_')}"
233
+ ENV.fetch(env_var, nil)
234
+ end
235
+
236
+ def cargo_config_from_file(key_name)
237
+ parsed_file(cargo_config).dig(*key_name.split("."))
167
238
  end
168
239
 
169
240
  def version_from_lockfile(name, declaration)
@@ -237,6 +308,10 @@ module Dependabot
237
308
  @lockfile ||= get_original_file("Cargo.lock")
238
309
  end
239
310
 
311
+ def cargo_config
312
+ @cargo_config ||= get_original_file(".cargo/config.toml")
313
+ end
314
+
240
315
  def version_class
241
316
  Cargo::Version
242
317
  end
@@ -7,6 +7,7 @@ require "dependabot/git_commit_checker"
7
7
  require "dependabot/cargo/file_updater"
8
8
  require "dependabot/cargo/file_updater/manifest_updater"
9
9
  require "dependabot/cargo/file_parser"
10
+ require "dependabot/cargo/helpers"
10
11
  require "dependabot/shared_helpers"
11
12
  module Dependabot
12
13
  module Cargo
@@ -33,7 +34,7 @@ module Dependabot
33
34
  SharedHelpers.with_git_configured(credentials: credentials) do
34
35
  # Shell out to Cargo, which handles everything for us, and does
35
36
  # so without doing an install (so it's fast).
36
- run_shell_command("cargo update -p #{dependency_spec}", fingerprint: "cargo update -p <dependency_spec>")
37
+ run_cargo_command("cargo update -p #{dependency_spec}", fingerprint: "cargo update -p <dependency_spec>")
37
38
  end
38
39
 
39
40
  updated_lockfile = File.read("Cargo.lock")
@@ -112,7 +113,6 @@ module Dependabot
112
113
  spec += ":#{git_previous_version}" if git_previous_version
113
114
  elsif dependency.previous_version
114
115
  spec += ":#{dependency.previous_version}"
115
- spec = "https://github.com/rust-lang/crates.io-index#" + spec
116
116
  end
117
117
 
118
118
  spec
@@ -138,10 +138,14 @@ module Dependabot
138
138
  %(name = "#{dependency.name}"\nversion = "#{dependency.version}")
139
139
  end
140
140
 
141
- def run_shell_command(command, fingerprint:)
141
+ def run_cargo_command(command, fingerprint:)
142
142
  start = Time.now
143
143
  command = SharedHelpers.escape_command(command)
144
- stdout, process = Open3.capture2e(command)
144
+ Helpers.setup_credentials_in_environment(credentials)
145
+ # Pass through any registry tokens supplied via CARGO_REGISTRIES_...
146
+ # environment variables.
147
+ env = ENV.select { |key, _value| key.match(/^CARGO_REGISTRIES_/) }
148
+ stdout, process = Open3.capture2e(env, command)
145
149
  time_taken = Time.now - start
146
150
 
147
151
  # Raise an error with the output from the shell session if Cargo
@@ -187,6 +191,10 @@ module Dependabot
187
191
 
188
192
  File.write(lockfile.name, lockfile.content)
189
193
  File.write(toolchain.name, toolchain.content) if toolchain
194
+ return unless config
195
+
196
+ FileUtils.mkdir_p(File.dirname(config.name))
197
+ File.write(config.name, config.content)
190
198
  end
191
199
 
192
200
  def write_temporary_manifest_files
@@ -394,6 +402,10 @@ module Dependabot
394
402
  dependency_files.find { |f| f.name == "rust-toolchain" }
395
403
  end
396
404
 
405
+ def config
406
+ @config ||= dependency_files.find { |f| f.name == ".cargo/config.toml" }
407
+ end
408
+
397
409
  def virtual_manifest?(file)
398
410
  !file.content.include?("[package]")
399
411
  end
@@ -0,0 +1,38 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ require "yaml"
5
+
6
+ module Dependabot
7
+ module Cargo
8
+ module Helpers
9
+ def self.setup_credentials_in_environment(credentials)
10
+ credentials.each do |cred|
11
+ next if cred["type"] != "cargo_registry"
12
+
13
+ # If there is a 'token' property, then apply it.
14
+ # If there is not, it probably means we are running under dependabot-cli which stripped
15
+ # all tokens. So in that case, we assume that the dependabot proxy will re-inject the
16
+ # actual correct token, and we just use 'token' as a placeholder at this point.
17
+ # (We must add these environment variables here, or 'cargo update' will not think it is
18
+ # configured properly for the private registries.)
19
+
20
+ token_env_var = "CARGO_REGISTRIES_#{cred['cargo_registry'].upcase.tr('-', '_')}_TOKEN"
21
+
22
+ token = "placeholder_token"
23
+ if cred["token"].nil?
24
+ puts "Setting #{token_env_var} to 'placeholder_token' because dependabot-cli proxy will override it anyway"
25
+ else
26
+ token = cred["token"]
27
+ puts "Setting #{token_env_var} to provided token value"
28
+ end
29
+
30
+ ENV[token_env_var] ||= token
31
+ end
32
+
33
+ # And set CARGO_REGISTRY_GLOBAL_CREDENTIAL_PROVIDERS here as well, so Cargo will expect tokens
34
+ ENV["CARGO_REGISTRY_GLOBAL_CREDENTIAL_PROVIDERS"] ||= "cargo:token"
35
+ end
36
+ end
37
+ end
38
+ end
@@ -10,12 +10,14 @@ module Dependabot
10
10
  module Cargo
11
11
  class MetadataFinder < Dependabot::MetadataFinders::Base
12
12
  SOURCE_KEYS = %w(repository homepage documentation).freeze
13
+ CRATES_IO_API = "https://crates.io/api/v1/crates"
13
14
 
14
15
  private
15
16
 
16
17
  def look_up_source
17
18
  case new_source_type
18
19
  when "default" then find_source_from_crates_listing
20
+ when "registry" then find_source_from_crates_listing
19
21
  when "git" then find_source_from_git_url
20
22
  else raise "Unexpected source type: #{new_source_type}"
21
23
  end
@@ -44,9 +46,47 @@ module Dependabot
44
46
  def crates_listing
45
47
  return @crates_listing unless @crates_listing.nil?
46
48
 
47
- response = Dependabot::RegistryClient.get(url: "https://crates.io/api/v1/crates/#{dependency.name}")
49
+ info = dependency.requirements.filter_map { |r| r[:source] }.first
50
+ index = (info && info[:index]) || CRATES_IO_API
51
+
52
+ # Default request headers
53
+ hdrs = { "User-Agent" => "Dependabot (dependabot.com)" }
54
+
55
+ if index != CRATES_IO_API
56
+ # Add authentication headers if credentials are present for this registry
57
+ credentials.find { |cred| cred["type"] == "cargo_registry" && cred["registry"] == info[:name] }&.tap do |cred|
58
+ hdrs["Authorization"] = "Token #{cred['token']}"
59
+ end
60
+ end
61
+
62
+ url = metadata_fetch_url(dependency, index)
63
+
64
+ response = Excon.get(
65
+ url,
66
+ idempotent: true,
67
+ **SharedHelpers.excon_defaults(headers: hdrs)
68
+ )
69
+
48
70
  @crates_listing = JSON.parse(response.body)
49
71
  end
72
+
73
+ def metadata_fetch_url(dependency, index)
74
+ return "#{index}/#{dependency.name}" if index == CRATES_IO_API
75
+
76
+ # Determine cargo's index file path for the dependency
77
+ index = index.delete_prefix("sparse+")
78
+ name_length = dependency.name.length
79
+ dependency_path = case name_length
80
+ when 1, 2
81
+ "#{name_length}/#{dependency.name}"
82
+ when 3
83
+ "#{name_length}/#{dependency.name[0..1]}/#{dependency.name}"
84
+ else
85
+ "#{dependency.name[0..1]}/#{dependency.name[2..3]}/#{dependency.name}"
86
+ end
87
+
88
+ "#{index}#{'/' unless index.end_with?('/')}#{dependency_path}"
89
+ end
50
90
  end
51
91
  end
52
92
  end
@@ -0,0 +1,42 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ require "dependabot/file_fetchers"
5
+ require "dependabot/file_fetchers/base"
6
+
7
+ module Dependabot
8
+ module Cargo
9
+ class RegistryFetcher < Dependabot::FileFetchers::Base
10
+ def self.required_files_in?(filenames)
11
+ filenames.include?("config.json")
12
+ end
13
+
14
+ def self.required_files_message
15
+ "Repo must contain a config.json"
16
+ end
17
+
18
+ def dl
19
+ parsed_config_json["dl"].chomp("/")
20
+ end
21
+
22
+ def api
23
+ parsed_config_json["api"].chomp("/")
24
+ end
25
+
26
+ private
27
+
28
+ def fetch_files
29
+ fetched_files = []
30
+ fetched_files << config_json
31
+ end
32
+
33
+ def parsed_config_json
34
+ @parsed_config_json ||= JSON.parse(config_json.content)
35
+ end
36
+
37
+ def config_json
38
+ @config_json ||= fetch_file_from_host("config.json")
39
+ end
40
+ end
41
+ end
42
+ end
@@ -13,6 +13,8 @@ module Dependabot
13
13
  class LatestVersionFinder
14
14
  extend T::Sig
15
15
 
16
+ CRATES_IO_API = "https://crates.io/api/v1/crates"
17
+
16
18
  def initialize(dependency:, dependency_files:, credentials:,
17
19
  ignored_versions:, raise_on_ignored: false,
18
20
  security_advisories:)
@@ -101,8 +103,64 @@ module Dependabot
101
103
  def crates_listing
102
104
  return @crates_listing unless @crates_listing.nil?
103
105
 
104
- response = Dependabot::RegistryClient.get(url: "https://crates.io/api/v1/crates/#{dependency.name}")
106
+ info = dependency.requirements.filter_map { |r| r[:source] }.first
107
+ index = (info && info[:index]) || CRATES_IO_API
108
+
109
+ # Default request headers
110
+ hdrs = { "User-Agent" => "Dependabot (dependabot.com)" }
111
+
112
+ if index != CRATES_IO_API
113
+ # Add authentication headers if credentials are present for this registry
114
+ registry_creds = credentials.find do |cred|
115
+ cred["type"] == "cargo_registry" && cred["registry"] == info[:name]
116
+ end
117
+
118
+ unless registry_creds.nil?
119
+ # If there is a credential, but no actual token at this point, it means that dependabot-cli
120
+ # stripped the token from our credentials. In this case, the dependabot proxy will reintroduce
121
+ # the correct token, so we just use 'placeholder_token' as the token value.
122
+ token = registry_creds["token"] || "placeholder_token"
123
+
124
+ hdrs["Authorization"] = token
125
+ end
126
+ end
127
+
128
+ url = metadata_fetch_url(dependency, index)
129
+
130
+ # B4PR
131
+ puts "Calling #{url} to fetch metadata for #{dependency.name} from #{index}"
132
+
133
+ response = Excon.get(
134
+ url,
135
+ idempotent: true,
136
+ **SharedHelpers.excon_defaults(headers: hdrs)
137
+ )
138
+
105
139
  @crates_listing = JSON.parse(response.body)
140
+
141
+ # B4PR
142
+ puts "Fetched metadata for #{dependency.name} from #{index} successfully"
143
+ puts response.body
144
+
145
+ @crates_listing
146
+ end
147
+
148
+ def metadata_fetch_url(dependency, index)
149
+ return "#{index}/#{dependency.name}" if index == CRATES_IO_API
150
+
151
+ # Determine cargo's index file path for the dependency
152
+ index = index.delete_prefix("sparse+")
153
+ name_length = dependency.name.length
154
+ dependency_path = case name_length
155
+ when 1, 2
156
+ "#{name_length}/#{dependency.name}"
157
+ when 3
158
+ "#{name_length}/#{dependency.name[0..1]}/#{dependency.name}"
159
+ else
160
+ "#{dependency.name[0..1]}/#{dependency.name[2..3]}/#{dependency.name}"
161
+ end
162
+
163
+ "#{index}#{'/' unless index.end_with?('/')}#{dependency_path}"
106
164
  end
107
165
 
108
166
  def wants_prerelease?
@@ -4,6 +4,7 @@
4
4
  require "toml-rb"
5
5
  require "open3"
6
6
  require "dependabot/shared_helpers"
7
+ require "dependabot/cargo/helpers"
7
8
  require "dependabot/cargo/update_checker"
8
9
  require "dependabot/cargo/file_parser"
9
10
  require "dependabot/cargo/version"
@@ -31,6 +32,8 @@ module Dependabot
31
32
  return @latest_resolvable_version if defined?(@latest_resolvable_version)
32
33
 
33
34
  @latest_resolvable_version = fetch_latest_resolvable_version
35
+ rescue Dependabot::SharedHelpers::HelperSubprocessFailed => e
36
+ raise Dependabot::DependencyFileNotResolvable, e.message
34
37
  end
35
38
 
36
39
  private
@@ -127,7 +130,6 @@ module Dependabot
127
130
  spec += ":#{git_dependency_version}" if git_dependency_version
128
131
  elsif dependency.version
129
132
  spec += ":#{dependency.version}"
130
- spec = "https://github.com/rust-lang/crates.io-index#" + spec
131
133
  end
132
134
 
133
135
  spec
@@ -137,15 +139,20 @@ module Dependabot
137
139
  # so without doing an install (so it's fast).
138
140
  def run_cargo_update_command
139
141
  run_cargo_command(
140
- "cargo update -p #{dependency_spec} --verbose",
141
- fingerprint: "cargo update -p <dependency_spec> --verbose"
142
+ "cargo update -p #{dependency_spec} -vv",
143
+ fingerprint: "cargo update -p <dependency_spec> -vv"
142
144
  )
143
145
  end
144
146
 
145
147
  def run_cargo_command(command, fingerprint: nil)
146
148
  start = Time.now
147
149
  command = SharedHelpers.escape_command(command)
148
- stdout, process = Open3.capture2e(command)
150
+ Helpers.setup_credentials_in_environment(credentials)
151
+ # Pass through any registry tokens supplied via CARGO_REGISTRIES_...
152
+ # environment variables, and also any CARGO_REGISTRY_... configuration.
153
+ env = ENV.select { |key, _value| key.match(/^(CARGO_REGISTRY|CARGO_REGISTRIES)_/) }
154
+
155
+ stdout, process = Open3.capture2e(env, command)
149
156
  time_taken = Time.now - start
150
157
 
151
158
  # Raise an error with the output from the shell session if Cargo
@@ -168,6 +175,10 @@ module Dependabot
168
175
 
169
176
  File.write(lockfile.name, lockfile.content) if lockfile
170
177
  File.write(toolchain.name, toolchain.content) if toolchain
178
+ return unless config
179
+
180
+ FileUtils.mkdir_p(File.dirname(config.name))
181
+ File.write(config.name, config.content)
171
182
  end
172
183
 
173
184
  def check_rust_workspace_root
@@ -425,10 +436,14 @@ module Dependabot
425
436
  end
426
437
 
427
438
  def toolchain
428
- @toolchain ||= prepared_dependency_files
439
+ @toolchain ||= original_dependency_files
429
440
  .find { |f| f.name == "rust-toolchain" }
430
441
  end
431
442
 
443
+ def config
444
+ @config ||= original_dependency_files.find { |f| f.name == ".cargo/config.toml" }
445
+ end
446
+
432
447
  def git_dependency?
433
448
  GitCommitChecker.new(
434
449
  dependency: dependency,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-cargo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.254.0
4
+ version: 0.255.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-24 00:00:00.000000000 Z
11
+ date: 2024-05-03 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.254.0
19
+ version: 0.255.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.254.0
26
+ version: 0.255.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: debug
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -164,6 +164,20 @@ dependencies:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
166
  version: 0.8.1
167
+ - !ruby/object:Gem::Dependency
168
+ name: simplecov
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: 0.22.0
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: 0.22.0
167
181
  - !ruby/object:Gem::Dependency
168
182
  name: turbo_tests
169
183
  requirement: !ruby/object:Gem::Requirement
@@ -234,7 +248,9 @@ files:
234
248
  - lib/dependabot/cargo/file_updater.rb
235
249
  - lib/dependabot/cargo/file_updater/lockfile_updater.rb
236
250
  - lib/dependabot/cargo/file_updater/manifest_updater.rb
251
+ - lib/dependabot/cargo/helpers.rb
237
252
  - lib/dependabot/cargo/metadata_finder.rb
253
+ - lib/dependabot/cargo/registry_fetcher.rb
238
254
  - lib/dependabot/cargo/requirement.rb
239
255
  - lib/dependabot/cargo/update_checker.rb
240
256
  - lib/dependabot/cargo/update_checker/file_preparer.rb
@@ -247,7 +263,7 @@ licenses:
247
263
  - Nonstandard
248
264
  metadata:
249
265
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
250
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.254.0
266
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.255.0
251
267
  post_install_message:
252
268
  rdoc_options: []
253
269
  require_paths:
@@ -263,7 +279,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
263
279
  - !ruby/object:Gem::Version
264
280
  version: 3.1.0
265
281
  requirements: []
266
- rubygems_version: 3.3.26
282
+ rubygems_version: 3.5.9
267
283
  signing_key:
268
284
  specification_version: 4
269
285
  summary: Provides Dependabot support for Rust (Cargo)