dependabot-bundler 0.303.0 → 0.304.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: fea7b824346608c85aa153277a3d95c1490b32601fd390390bad519a76264b69
4
- data.tar.gz: 50530f2584e007afa21e905f9ef29cb7e9fe894b7bc5127fa6001ad19be805a3
3
+ metadata.gz: afac5aac6bfb6ee45bfa6a928dcd47663352670e32334a78859f6062cdf5e38e
4
+ data.tar.gz: 9a5c98bda93d938912881fdc6d4407304d485795e6e170c2256b462f8a967546
5
5
  SHA512:
6
- metadata.gz: cc9b5a20c3812ca94c287432710e021c925c75e6bfd044a6d084e97d0c1f00f4ab51f46ef9015202c9de75b8627445c3c0a31b3c2d198462fde57ab7e8b0976a
7
- data.tar.gz: a91e3098508822b8afb01ec20feb86d1e3dba8631be244629869560635e414256e8f0c4628c1cb00fcbe1a019460fe7fb5a14292d6a973f92ad6269538ab24dc
6
+ metadata.gz: 19e479a5ea88a9a770c780172b9a1e07cd8a694a3b22825adb348257126871490fe044d56da48a81ca02973cbd0835e5d681a752e4405c3fe0cda3f7c2cda57e
7
+ data.tar.gz: 45aa64aef52bfca8cb704e1eab1af719ac4a59d3f806e5a4cd412f7ebf234a336fcab74f8e0b56ee749f1ceb92a0b578e0aecf715886a4f1d1960249c7badf11
@@ -18,12 +18,20 @@ module Dependabot
18
18
  class PackageDetailsFetcher
19
19
  extend T::Sig
20
20
 
21
+ require_relative "../update_checker/shared_bundler_helpers"
22
+ include Dependabot::Bundler::UpdateChecker::SharedBundlerHelpers
23
+
21
24
  RELEASES_URL = "https://rubygems.org/api/v1/versions/%s.json"
22
25
  GEM_URL = "https://rubygems.org/gems/%s.gem"
23
26
  PACKAGE_TYPE = "gem"
24
27
  PACKAGE_LANGUAGE = "ruby"
25
28
  APPLICATION_JSON = "application/json"
26
29
 
30
+ RUBYGEMS = "rubygems"
31
+ PRIVATE_REGISTRY = "private"
32
+ GIT = "git"
33
+ OTHER = "other"
34
+
27
35
  sig do
28
36
  params(
29
37
  dependency: Dependabot::Dependency,
@@ -35,6 +43,8 @@ module Dependabot
35
43
  @dependency = dependency
36
44
  @dependency_files = dependency_files
37
45
  @credentials = credentials
46
+
47
+ @source_type = T.let(nil, T.nilable(String))
38
48
  end
39
49
 
40
50
  sig { returns(Dependabot::Dependency) }
@@ -46,6 +56,21 @@ module Dependabot
46
56
  sig { returns(T::Array[T.untyped]) }
47
57
  attr_reader :credentials
48
58
 
59
+ sig { returns(Dependabot::Package::PackageDetails) }
60
+ def fetch
61
+ return rubygems_versions if dependency.name == "bundler"
62
+ return rubygems_versions unless gemfile
63
+
64
+ case source_type
65
+ when OTHER, GIT, PRIVATE_REGISTRY
66
+ package_details([])
67
+ else
68
+ rubygems_versions
69
+ end
70
+ end
71
+
72
+ private
73
+
49
74
  # Example JSON Response Format:
50
75
  # eg https://rubygems.org/api/v1/versions/dependabot-common.json
51
76
  # response:
@@ -101,35 +126,23 @@ module Dependabot
101
126
  # ...
102
127
  # ]
103
128
  sig { returns(Dependabot::Package::PackageDetails) }
104
- def fetch
129
+ def rubygems_versions
105
130
  response = registry_json_response_for_dependency
106
131
  raise unless response.status == 200
107
132
 
108
133
  package_releases = JSON.parse(response.body).map do |release|
109
- Dependabot::Package::PackageRelease.new(
110
- version: Dependabot::Bundler::Version.new(release["number"]),
134
+ package_release(
135
+ version: release["number"],
111
136
  released_at: Time.parse(release["created_at"]),
112
- yanked: false,
113
- yanked_reason: nil,
114
137
  downloads: release["downloads_count"],
115
138
  url: GEM_URL % "#{@dependency.name}-#{release['number']}",
116
- package_type: PACKAGE_TYPE,
117
- language: Dependabot::Package::PackageLanguage.new(
118
- name: PACKAGE_LANGUAGE,
119
- version: nil,
120
- requirement: language_requirement(release["ruby_version"])
121
- )
139
+ ruby_version: release["ruby_version"]
122
140
  )
123
141
  end
124
142
 
125
- Dependabot::Package::PackageDetails.new(
126
- dependency: dependency,
127
- releases: package_releases.reverse.uniq(&:version)
128
- )
143
+ package_details(package_releases)
129
144
  end
130
145
 
131
- private
132
-
133
146
  sig { returns(Excon::Response) }
134
147
  def registry_json_response_for_dependency
135
148
  url = RELEASES_URL % dependency.name
@@ -143,6 +156,72 @@ module Dependabot
143
156
  def language_requirement(req_string)
144
157
  Requirement.new(req_string)
145
158
  end
159
+
160
+ sig { returns(String) }
161
+ def source_type
162
+ @source_type ||= begin
163
+ return @source_type = RUBYGEMS unless gemfile
164
+
165
+ @source_type = in_a_native_bundler_context do |tmp_dir|
166
+ NativeHelpers.run_bundler_subprocess(
167
+ bundler_version: bundler_version,
168
+ function: "dependency_source_type",
169
+ options: {}, # options,
170
+ args: {
171
+ dir: tmp_dir,
172
+ gemfile_name: gemfile.name,
173
+ dependency_name: dependency.name,
174
+ credentials: credentials
175
+ }
176
+ )
177
+ end
178
+ end
179
+ end
180
+
181
+ sig { override.returns(String) }
182
+ def bundler_version
183
+ @bundler_version ||= T.let(Helpers.bundler_version(lockfile), T.nilable(String))
184
+ end
185
+
186
+ sig do
187
+ params(releases: T::Array[Dependabot::Package::PackageRelease])
188
+ .returns(Dependabot::Package::PackageDetails)
189
+ end
190
+ def package_details(releases)
191
+ @package_details ||= T.let(
192
+ Dependabot::Package::PackageDetails.new(
193
+ dependency: dependency,
194
+ releases: releases.reverse.uniq(&:version)
195
+ ), T.nilable(Dependabot::Package::PackageDetails)
196
+ )
197
+ end
198
+
199
+ sig do
200
+ params(
201
+ version: String,
202
+ released_at: Time,
203
+ downloads: Integer,
204
+ url: String,
205
+ ruby_version: String,
206
+ yanked: T::Boolean
207
+ ).returns(Dependabot::Package::PackageRelease)
208
+ end
209
+ def package_release(version:, released_at:, downloads:, url:, ruby_version:, yanked: false)
210
+ Dependabot::Package::PackageRelease.new(
211
+ version: Dependabot::Bundler::Version.new(version),
212
+ released_at: released_at,
213
+ yanked: yanked,
214
+ yanked_reason: nil,
215
+ downloads: downloads,
216
+ url: url,
217
+ package_type: PACKAGE_TYPE,
218
+ language: Dependabot::Package::PackageLanguage.new(
219
+ name: PACKAGE_LANGUAGE,
220
+ version: nil,
221
+ requirement: language_requirement(ruby_version)
222
+ )
223
+ )
224
+ end
146
225
  end
147
226
  end
148
227
  end
@@ -4,12 +4,13 @@
4
4
  require "dependabot/registry_client"
5
5
  require "dependabot/bundler/native_helpers"
6
6
  require "dependabot/bundler/helpers"
7
+ require "dependabot/bundler/update_checker/latest_version_finder"
7
8
  require "sorbet-runtime"
8
9
 
9
10
  module Dependabot
10
11
  module Bundler
11
12
  class UpdateChecker
12
- class LatestVersionFinder
13
+ class LatestVersionFinder < Dependabot::Package::PackageLatestVersionFinder
13
14
  class DependencySource
14
15
  extend T::Sig
15
16
 
@@ -8,46 +8,54 @@ require "dependabot/update_checkers/version_filters"
8
8
  require "dependabot/bundler/requirement"
9
9
  require "dependabot/shared_helpers"
10
10
  require "dependabot/errors"
11
+ require "dependabot/package/package_latest_version_finder"
11
12
  require "dependabot/bundler/update_checker/latest_version_finder/" \
12
13
  "dependency_source"
14
+ require "dependabot/bundler/package/package_details_fetcher"
13
15
  require "sorbet-runtime"
14
16
 
15
17
  module Dependabot
16
18
  module Bundler
17
19
  class UpdateChecker
18
- class LatestVersionFinder
20
+ class LatestVersionFinder < Dependabot::Package::PackageLatestVersionFinder
19
21
  extend T::Sig
20
22
 
21
- def initialize(dependency:, dependency_files:, repo_contents_path: nil,
22
- credentials:, ignored_versions:, raise_on_ignored: false,
23
- security_advisories:, options:)
24
- @dependency = dependency
25
- @dependency_files = dependency_files
26
- @repo_contents_path = repo_contents_path
27
- @credentials = credentials
28
- @ignored_versions = ignored_versions
29
- @raise_on_ignored = raise_on_ignored
30
- @security_advisories = security_advisories
31
- @options = options
23
+ sig { override.returns(T.nilable(Dependabot::Package::PackageDetails)) }
24
+ def package_details
25
+ @package_details ||= Package::PackageDetailsFetcher.new(
26
+ dependency: dependency,
27
+ dependency_files: dependency_files,
28
+ credentials: credentials
29
+ ).fetch
32
30
  end
33
31
 
34
32
  def latest_version_details
35
- @latest_version_details ||= fetch_latest_version_details
33
+ @latest_version_details ||= if cooldown_enabled?
34
+ latest_version = fetch_latest_version(language_version: nil)
35
+ latest_version ? { version: latest_version } : nil
36
+ else
37
+ fetch_latest_version_details
38
+ end
36
39
  end
37
40
 
38
- def lowest_security_fix_version
39
- @lowest_security_fix_version ||= fetch_lowest_security_fix_version
41
+ sig { override.returns(T::Boolean) }
42
+ def cooldown_enabled?
43
+ Dependabot::Experiments.enabled?(:enable_cooldown_for_bundler)
40
44
  end
41
45
 
42
- private
46
+ sig { override.returns(T.nilable(T::Array[Dependabot::Package::PackageRelease])) }
47
+ def available_versions
48
+ return nil if package_details&.releases.nil?
49
+
50
+ source_versions = dependency_source.versions
51
+ return [] if source_versions.empty?
43
52
 
44
- attr_reader :dependency
45
- attr_reader :dependency_files
46
- attr_reader :repo_contents_path
47
- attr_reader :credentials
48
- attr_reader :ignored_versions
49
- attr_reader :security_advisories
50
- attr_reader :options
53
+ T.must(package_details).releases.select do |release|
54
+ source_versions.any? { |v| v.to_s == release.version.to_s }
55
+ end
56
+ end
57
+
58
+ private
51
59
 
52
60
  def fetch_latest_version_details
53
61
  return dependency_source.latest_git_version_details if dependency_source.git?
@@ -59,7 +67,7 @@ module Dependabot
59
67
  relevant_versions.empty? ? nil : { version: relevant_versions.max }
60
68
  end
61
69
 
62
- def fetch_lowest_security_fix_version
70
+ def fetch_lowest_security_fix_version(*)
63
71
  return if dependency_source.git?
64
72
 
65
73
  relevant_versions = dependency_source.versions
@@ -72,41 +80,9 @@ module Dependabot
72
80
  relevant_versions.min
73
81
  end
74
82
 
75
- sig { params(versions_array: T::Array[Gem::Version]).returns(T::Array[Gem::Version]) }
76
- def filter_prerelease_versions(versions_array)
77
- return versions_array if wants_prerelease?
78
-
79
- filtered = versions_array.reject(&:prerelease?)
80
- if versions_array.count > filtered.count
81
- Dependabot.logger.info("Filtered out #{versions_array.count - filtered.count} pre-release versions")
82
- end
83
- filtered
84
- end
85
-
86
- sig { params(versions_array: T::Array[Gem::Version]).returns(T::Array[Gem::Version]) }
87
- def filter_ignored_versions(versions_array)
88
- filtered = versions_array
89
- .reject { |v| ignore_requirements.any? { |r| r.satisfied_by?(v) } }
90
- if @raise_on_ignored && filter_lower_versions(filtered).empty? && filter_lower_versions(versions_array).any?
91
- raise AllVersionsIgnored
92
- end
93
-
94
- if versions_array.count > filtered.count
95
- Dependabot.logger.info("Filtered out #{versions_array.count - filtered.count} ignored versions")
96
- end
97
-
98
- filtered
99
- end
100
-
101
- def filter_lower_versions(versions_array)
102
- return versions_array unless dependency.numeric_version
103
-
104
- versions_array
105
- .select { |version| version > dependency.numeric_version }
106
- end
107
-
83
+ sig { returns(T::Boolean) }
108
84
  def wants_prerelease?
109
- @wants_prerelease ||=
85
+ @wants_prerelease ||= T.let(
110
86
  begin
111
87
  current_version = dependency.numeric_version
112
88
  if current_version&.prerelease?
@@ -116,30 +92,21 @@ module Dependabot
116
92
  req[:requirement].match?(/[a-z]/i)
117
93
  end
118
94
  end
119
- end
95
+ end, T.nilable(T::Boolean)
96
+ )
120
97
  end
121
98
 
99
+ # sig { returns(DependencySource) }
122
100
  def dependency_source
123
- @dependency_source ||= DependencySource.new(
124
- dependency: dependency,
125
- dependency_files: dependency_files,
126
- credentials: credentials,
127
- options: options
101
+ @dependency_source ||= T.let(
102
+ DependencySource.new(
103
+ dependency: dependency,
104
+ dependency_files: dependency_files,
105
+ credentials: credentials,
106
+ options: options
107
+ ), T.nilable(DependencySource)
128
108
  )
129
109
  end
130
-
131
- def ignore_requirements
132
- ignored_versions.flat_map { |req| requirement_class.requirements_array(req) }
133
- end
134
-
135
- def requirement_class
136
- dependency.requirement_class
137
- end
138
-
139
- def gemfile
140
- dependency_files.find { |f| f.name == "Gemfile" } ||
141
- dependency_files.find { |f| f.name == "gems.rb" }
142
- end
143
110
  end
144
111
  end
145
112
  end
@@ -26,6 +26,7 @@ module Dependabot
26
26
  replacement_git_pin: nil, remove_git_source: false,
27
27
  unlock_requirement: true,
28
28
  latest_allowable_version: nil,
29
+ cooldown_options: {},
29
30
  options:)
30
31
  @dependency = dependency
31
32
  @unprepared_dependency_files = unprepared_dependency_files
@@ -37,6 +38,7 @@ module Dependabot
37
38
  @remove_git_source = remove_git_source
38
39
  @unlock_requirement = unlock_requirement
39
40
  @latest_allowable_version = latest_allowable_version
41
+ @cooldown_options = cooldown_options
40
42
  @options = options
41
43
 
42
44
  @latest_allowable_version_incompatible_with_ruby = false
@@ -183,7 +185,6 @@ module Dependabot
183
185
  LatestVersionFinder.new(
184
186
  dependency: dependency,
185
187
  dependency_files: dependency_files,
186
- repo_contents_path: repo_contents_path,
187
188
  credentials: credentials,
188
189
  ignored_versions: ignored_versions,
189
190
  raise_on_ignored: @raise_on_ignored,
@@ -367,7 +367,6 @@ module Dependabot
367
367
  LatestVersionFinder.new(
368
368
  dependency: dependency,
369
369
  dependency_files: prepared_dependency_files,
370
- repo_contents_path: repo_contents_path,
371
370
  credentials: credentials,
372
371
  ignored_versions: ignored_versions,
373
372
  raise_on_ignored: raise_on_ignored,
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-bundler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.303.0
4
+ version: 0.304.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-03-27 00:00:00.000000000 Z
11
+ date: 2025-04-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.303.0
19
+ version: 0.304.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.303.0
26
+ version: 0.304.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: parallel
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -323,7 +323,7 @@ licenses:
323
323
  - MIT
324
324
  metadata:
325
325
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
326
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.303.0
326
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.304.0
327
327
  post_install_message:
328
328
  rdoc_options: []
329
329
  require_paths: