dependabot-core 0.93.17 → 0.94.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/lib/dependabot/dependency.rb +16 -21
  4. data/lib/dependabot/file_fetchers.rb +1 -5
  5. data/lib/dependabot/file_parsers.rb +1 -5
  6. data/lib/dependabot/file_updaters.rb +1 -5
  7. data/lib/dependabot/metadata_finders.rb +1 -5
  8. data/lib/dependabot/pull_request_creator/labeler.rb +26 -24
  9. data/lib/dependabot/update_checkers.rb +1 -5
  10. data/lib/dependabot/utils.rb +2 -12
  11. data/lib/dependabot/version.rb +1 -1
  12. metadata +1 -28
  13. data/lib/dependabot/file_fetchers/ruby/bundler.rb +0 -215
  14. data/lib/dependabot/file_fetchers/ruby/bundler/child_gemfile_finder.rb +0 -70
  15. data/lib/dependabot/file_fetchers/ruby/bundler/gemspec_finder.rb +0 -98
  16. data/lib/dependabot/file_fetchers/ruby/bundler/path_gemspec_finder.rb +0 -114
  17. data/lib/dependabot/file_fetchers/ruby/bundler/require_relative_finder.rb +0 -67
  18. data/lib/dependabot/file_parsers/ruby/bundler.rb +0 -294
  19. data/lib/dependabot/file_parsers/ruby/bundler/file_preparer.rb +0 -86
  20. data/lib/dependabot/file_parsers/ruby/bundler/gemfile_checker.rb +0 -48
  21. data/lib/dependabot/file_updaters/ruby/bundler.rb +0 -123
  22. data/lib/dependabot/file_updaters/ruby/bundler/gemfile_updater.rb +0 -116
  23. data/lib/dependabot/file_updaters/ruby/bundler/gemspec_dependency_name_finder.rb +0 -52
  24. data/lib/dependabot/file_updaters/ruby/bundler/gemspec_sanitizer.rb +0 -298
  25. data/lib/dependabot/file_updaters/ruby/bundler/gemspec_updater.rb +0 -64
  26. data/lib/dependabot/file_updaters/ruby/bundler/git_pin_replacer.rb +0 -80
  27. data/lib/dependabot/file_updaters/ruby/bundler/git_source_remover.rb +0 -102
  28. data/lib/dependabot/file_updaters/ruby/bundler/lockfile_updater.rb +0 -389
  29. data/lib/dependabot/file_updaters/ruby/bundler/requirement_replacer.rb +0 -223
  30. data/lib/dependabot/metadata_finders/ruby/bundler.rb +0 -202
  31. data/lib/dependabot/update_checkers/ruby/bundler.rb +0 -331
  32. data/lib/dependabot/update_checkers/ruby/bundler/file_preparer.rb +0 -281
  33. data/lib/dependabot/update_checkers/ruby/bundler/force_updater.rb +0 -261
  34. data/lib/dependabot/update_checkers/ruby/bundler/latest_version_finder.rb +0 -169
  35. data/lib/dependabot/update_checkers/ruby/bundler/requirements_updater.rb +0 -283
  36. data/lib/dependabot/update_checkers/ruby/bundler/ruby_requirement_setter.rb +0 -115
  37. data/lib/dependabot/update_checkers/ruby/bundler/shared_bundler_helpers.rb +0 -246
  38. data/lib/dependabot/update_checkers/ruby/bundler/version_resolver.rb +0 -272
  39. data/lib/dependabot/utils/ruby/requirement.rb +0 -26
@@ -1,169 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "bundler_definition_ruby_version_patch"
4
- require "bundler_definition_bundler_version_patch"
5
- require "bundler_git_source_patch"
6
-
7
- require "excon"
8
-
9
- require "dependabot/update_checkers/ruby/bundler"
10
- require "dependabot/utils/ruby/requirement"
11
- require "dependabot/shared_helpers"
12
- require "dependabot/errors"
13
-
14
- module Dependabot
15
- module UpdateCheckers
16
- module Ruby
17
- class Bundler
18
- class LatestVersionFinder
19
- require_relative "shared_bundler_helpers"
20
- include SharedBundlerHelpers
21
-
22
- def initialize(dependency:, dependency_files:, credentials:,
23
- ignored_versions:)
24
- @dependency = dependency
25
- @dependency_files = dependency_files
26
- @credentials = credentials
27
- @ignored_versions = ignored_versions
28
- end
29
-
30
- def latest_version_details
31
- @latest_version_details ||= fetch_latest_version_details
32
- end
33
-
34
- private
35
-
36
- attr_reader :dependency, :dependency_files, :credentials,
37
- :ignored_versions
38
-
39
- def fetch_latest_version_details
40
- if dependency.name == "bundler"
41
- return latest_rubygems_version_details
42
- end
43
-
44
- case dependency_source
45
- when NilClass then latest_rubygems_version_details
46
- when ::Bundler::Source::Rubygems
47
- if dependency_source.remotes.none? ||
48
- dependency_source.remotes.first.to_s == "https://rubygems.org/"
49
- latest_rubygems_version_details
50
- else
51
- latest_private_version_details
52
- end
53
- when ::Bundler::Source::Git then latest_git_version_details
54
- end
55
- end
56
-
57
- def latest_rubygems_version_details
58
- response = Excon.get(
59
- "https://rubygems.org/api/v1/versions/#{dependency.name}.json",
60
- idempotent: true,
61
- **SharedHelpers.excon_defaults
62
- )
63
-
64
- relevant_versions =
65
- JSON.parse(response.body).
66
- reject do |d|
67
- version = Gem::Version.new(d["number"])
68
- next true if version.prerelease? && !wants_prerelease?
69
- next true if ignore_reqs.any? { |r| r.satisfied_by?(version) }
70
-
71
- false
72
- end
73
-
74
- dep = relevant_versions.max_by { |d| Gem::Version.new(d["number"]) }
75
- return unless dep
76
-
77
- {
78
- version: Gem::Version.new(dep["number"]),
79
- sha: dep["sha"]
80
- }
81
- rescue JSON::ParserError, Excon::Error::Timeout
82
- nil
83
- end
84
-
85
- def latest_private_version_details
86
- in_a_temporary_bundler_context do
87
- spec =
88
- dependency_source.
89
- fetchers.flat_map do |fetcher|
90
- fetcher.
91
- specs_with_retry([dependency.name], dependency_source).
92
- search_all(dependency.name).
93
- reject { |s| s.version.prerelease? && !wants_prerelease? }.
94
- reject do |s|
95
- ignore_reqs.any? { |r| r.satisfied_by?(s.version) }
96
- end
97
- end.
98
- max_by(&:version)
99
- spec.nil? ? nil : { version: spec.version }
100
- end
101
- end
102
-
103
- def latest_git_version_details
104
- dependency_source_details =
105
- dependency.requirements.map { |r| r.fetch(:source) }.
106
- uniq.compact.first
107
-
108
- in_a_temporary_bundler_context do
109
- SharedHelpers.with_git_configured(credentials: credentials) do
110
- # Note: we don't set `ref`, as we want to unpin the dependency
111
- source = ::Bundler::Source::Git.new(
112
- "uri" => dependency_source_details[:url],
113
- "branch" => dependency_source_details[:branch],
114
- "name" => dependency.name,
115
- "submodules" => true
116
- )
117
-
118
- # Tell Bundler we're fine with fetching the source remotely
119
- source.instance_variable_set(:@allow_remote, true)
120
-
121
- spec = source.specs.first
122
- { version: spec.version, commit_sha: spec.source.revision }
123
- end
124
- end
125
- end
126
-
127
- def wants_prerelease?
128
- @wants_prerelease ||=
129
- begin
130
- current_version = dependency.version
131
- if current_version && Gem::Version.correct?(current_version) &&
132
- Gem::Version.new(current_version).prerelease?
133
- return true
134
- end
135
-
136
- dependency.requirements.any? do |req|
137
- req[:requirement].match?(/[a-z]/i)
138
- end
139
- end
140
- end
141
-
142
- def dependency_source
143
- return nil unless gemfile
144
-
145
- @dependency_source ||=
146
- in_a_temporary_bundler_context do
147
- definition = ::Bundler::Definition.build(gemfile.name, nil, {})
148
-
149
- specified_source =
150
- definition.dependencies.
151
- find { |dep| dep.name == dependency.name }&.source
152
-
153
- specified_source || definition.send(:sources).default_source
154
- end
155
- end
156
-
157
- def ignore_reqs
158
- ignored_versions.map { |req| Gem::Requirement.new(req.split(",")) }
159
- end
160
-
161
- def gemfile
162
- dependency_files.find { |f| f.name == "Gemfile" } ||
163
- dependency_files.find { |f| f.name == "gems.rb" }
164
- end
165
- end
166
- end
167
- end
168
- end
169
- end
@@ -1,283 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "dependabot/update_checkers/ruby/bundler"
4
-
5
- module Dependabot
6
- module UpdateCheckers
7
- module Ruby
8
- class Bundler
9
- class RequirementsUpdater
10
- class UnfixableRequirement < StandardError; end
11
-
12
- ALLOWED_UPDATE_STRATEGIES =
13
- %i(bump_versions bump_versions_if_necessary).freeze
14
-
15
- def initialize(requirements:, update_strategy:, updated_source:,
16
- latest_version:, latest_resolvable_version:)
17
- @requirements = requirements
18
- @latest_version = Gem::Version.new(latest_version) if latest_version
19
- @updated_source = updated_source
20
- @update_strategy = update_strategy
21
-
22
- check_update_strategy
23
-
24
- return unless latest_resolvable_version
25
-
26
- @latest_resolvable_version =
27
- Gem::Version.new(latest_resolvable_version)
28
- end
29
-
30
- def updated_requirements
31
- requirements.map do |req|
32
- if req[:file].match?(/\.gemspec/)
33
- update_gemspec_requirement(req)
34
- else
35
- # If a requirement doesn't come from a gemspec, it must be from
36
- # a Gemfile.
37
- update_gemfile_requirement(req)
38
- end
39
- end
40
- end
41
-
42
- private
43
-
44
- attr_reader :requirements, :updated_source,
45
- :latest_version, :latest_resolvable_version,
46
- :update_strategy
47
-
48
- def check_update_strategy
49
- return if ALLOWED_UPDATE_STRATEGIES.include?(update_strategy)
50
-
51
- raise "Unknown update strategy: #{update_strategy}"
52
- end
53
-
54
- def update_gemfile_requirement(req)
55
- req = req.merge(source: updated_source)
56
- return req unless latest_resolvable_version
57
-
58
- case update_strategy
59
- when :bump_versions
60
- update_version_requirement(req)
61
- when :bump_versions_if_necessary
62
- update_version_requirement_if_needed(req)
63
- else raise "Unexpected update strategy: #{update_strategy}"
64
- end
65
- end
66
-
67
- def update_version_requirement_if_needed(req)
68
- return req if new_version_satisfies?(req)
69
-
70
- update_version_requirement(req)
71
- end
72
-
73
- def update_version_requirement(req)
74
- requirements =
75
- req[:requirement].split(",").map { |r| Gem::Requirement.new(r) }
76
-
77
- new_requirement =
78
- if requirements.any?(&:exact?) then latest_resolvable_version.to_s
79
- elsif requirements.any? { |r| r.to_s.start_with?("~>") }
80
- tw_req = requirements.find { |r| r.to_s.start_with?("~>") }
81
- update_twiddle_version(tw_req, latest_resolvable_version).to_s
82
- else
83
- update_gemfile_range(requirements).map(&:to_s).join(", ")
84
- end
85
-
86
- req.merge(requirement: new_requirement)
87
- end
88
-
89
- def new_version_satisfies?(req)
90
- original_req = Gem::Requirement.new(req[:requirement].split(","))
91
- original_req.satisfied_by?(latest_resolvable_version)
92
- end
93
-
94
- def update_gemfile_range(requirements)
95
- updated_requirements =
96
- requirements.flat_map do |r|
97
- next r if r.satisfied_by?(latest_resolvable_version)
98
-
99
- case op = r.requirements.first.first
100
- when "<", "<="
101
- [update_greatest_version(r, latest_resolvable_version)]
102
- when "!="
103
- []
104
- else
105
- raise "Unexpected operation for unsatisfied Gemfile "\
106
- "requirement: #{op}"
107
- end
108
- end
109
-
110
- binding_requirements(updated_requirements)
111
- end
112
-
113
- def at_same_precision(new_version, old_version)
114
- release_precision =
115
- old_version.to_s.split(".").select { |i| i.match?(/^\d+$/) }.count
116
- prerelease_precision =
117
- old_version.to_s.split(".").count - release_precision
118
-
119
- new_release =
120
- new_version.to_s.split(".").first(release_precision)
121
- new_prerelease =
122
- new_version.to_s.split(".").
123
- drop_while { |i| i.match?(/^\d+$/) }.
124
- first([prerelease_precision, 1].max)
125
-
126
- [*new_release, *new_prerelease].join(".")
127
- end
128
-
129
- # rubocop:disable Metrics/PerceivedComplexity
130
- def update_gemspec_requirement(req)
131
- return req unless latest_version && latest_resolvable_version
132
-
133
- requirements =
134
- req[:requirement].split(",").map { |r| Gem::Requirement.new(r) }
135
-
136
- return req if requirements.all? do |r|
137
- requirement_satisfied?(r, req[:groups])
138
- end
139
-
140
- updated_requirements =
141
- requirements.flat_map do |r|
142
- next r if requirement_satisfied?(r, req[:groups])
143
-
144
- if req[:groups] == ["development"] then bumped_requirements(r)
145
- else widened_requirements(r)
146
- end
147
- end
148
-
149
- updated_requirements = binding_requirements(updated_requirements)
150
- req.merge(requirement: updated_requirements.map(&:to_s).join(", "))
151
- rescue UnfixableRequirement
152
- req.merge(requirement: :unfixable)
153
- end
154
- # rubocop:enable Metrics/PerceivedComplexity
155
-
156
- def requirement_satisfied?(req, groups)
157
- if groups == ["development"]
158
- req.satisfied_by?(latest_resolvable_version)
159
- else
160
- req.satisfied_by?(latest_version)
161
- end
162
- end
163
-
164
- def binding_requirements(requirements)
165
- grouped_by_operator =
166
- requirements.group_by { |r| r.requirements.first.first }
167
-
168
- binding_reqs = grouped_by_operator.flat_map do |operator, reqs|
169
- case operator
170
- when "<", "<=" then reqs.min_by { |r| r.requirements.first.last }
171
- when ">", ">=" then reqs.max_by { |r| r.requirements.first.last }
172
- else requirements
173
- end
174
- end.uniq
175
-
176
- binding_reqs << Gem::Requirement.new if binding_reqs.empty?
177
- binding_reqs.sort_by { |r| r.requirements.first.last }
178
- end
179
-
180
- def widened_requirements(req)
181
- op, version = req.requirements.first
182
-
183
- case op
184
- when "=", nil
185
- if version < latest_resolvable_version
186
- [Gem::Requirement.new("#{op} #{latest_resolvable_version}")]
187
- else
188
- req
189
- end
190
- when "<", "<=" then [update_greatest_version(req, latest_version)]
191
- when "~>" then convert_twidle_to_range(req, latest_version)
192
- when "!=" then []
193
- when ">", ">=" then raise UnfixableRequirement
194
- else raise "Unexpected operation for requirement: #{op}"
195
- end
196
- end
197
-
198
- def bumped_requirements(req)
199
- op, version = req.requirements.first
200
-
201
- case op
202
- when "=", nil
203
- if version < latest_resolvable_version
204
- [Gem::Requirement.new("#{op} #{latest_resolvable_version}")]
205
- else
206
- req
207
- end
208
- when "~>"
209
- [update_twiddle_version(req, latest_resolvable_version)]
210
- when "<", "<=" then [update_greatest_version(req, latest_version)]
211
- when "!=" then []
212
- when ">", ">=" then raise UnfixableRequirement
213
- else raise "Unexpected operation for requirement: #{op}"
214
- end
215
- end
216
-
217
- # rubocop:disable Metrics/AbcSize
218
- def convert_twidle_to_range(requirement, version_to_be_permitted)
219
- version = requirement.requirements.first.last
220
- version = version.release if version.prerelease?
221
-
222
- index_to_update = [version.segments.count - 2, 0].max
223
-
224
- ub_segments = version_to_be_permitted.segments
225
- ub_segments << 0 while ub_segments.count <= index_to_update
226
- ub_segments = ub_segments[0..index_to_update]
227
- ub_segments[index_to_update] += 1
228
-
229
- lb_segments = version.segments
230
- lb_segments.pop while lb_segments.any? && lb_segments.last.zero?
231
-
232
- if lb_segments.none?
233
- return [Gem::Requirement.new("< #{ub_segments.join('.')}")]
234
- end
235
-
236
- # Ensure versions have the same length as each other (cosmetic)
237
- length = [lb_segments.count, ub_segments.count].max
238
- lb_segments.fill(0, lb_segments.count...length)
239
- ub_segments.fill(0, ub_segments.count...length)
240
-
241
- [
242
- Gem::Requirement.new(">= #{lb_segments.join('.')}"),
243
- Gem::Requirement.new("< #{ub_segments.join('.')}")
244
- ]
245
- end
246
- # rubocop:enable Metrics/AbcSize
247
-
248
- # Updates the version in a "~>" constraint to allow the given version
249
- def update_twiddle_version(requirement, version_to_be_permitted)
250
- old_version = requirement.requirements.first.last
251
- updated_v = at_same_precision(version_to_be_permitted, old_version)
252
- Gem::Requirement.new("~> #{updated_v}")
253
- end
254
-
255
- # Updates the version in a "<" or "<=" constraint to allow the given
256
- # version
257
- def update_greatest_version(requirement, version_to_be_permitted)
258
- if version_to_be_permitted.is_a?(String)
259
- version_to_be_permitted =
260
- Gem::Version.new(version_to_be_permitted)
261
- end
262
- op, version = requirement.requirements.first
263
- version = version.release if version.prerelease?
264
-
265
- index_to_update =
266
- version.segments.map.with_index { |seg, i| seg.zero? ? 0 : i }.max
267
-
268
- new_segments = version.segments.map.with_index do |_, index|
269
- if index < index_to_update
270
- version_to_be_permitted.segments[index]
271
- elsif index == index_to_update
272
- version_to_be_permitted.segments[index] + 1
273
- else 0
274
- end
275
- end
276
-
277
- Gem::Requirement.new("#{op} #{new_segments.join('.')}")
278
- end
279
- end
280
- end
281
- end
282
- end
283
- end