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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/dependabot/dependency.rb +16 -21
- data/lib/dependabot/file_fetchers.rb +1 -5
- data/lib/dependabot/file_parsers.rb +1 -5
- data/lib/dependabot/file_updaters.rb +1 -5
- data/lib/dependabot/metadata_finders.rb +1 -5
- data/lib/dependabot/pull_request_creator/labeler.rb +26 -24
- data/lib/dependabot/update_checkers.rb +1 -5
- data/lib/dependabot/utils.rb +2 -12
- data/lib/dependabot/version.rb +1 -1
- metadata +1 -28
- data/lib/dependabot/file_fetchers/ruby/bundler.rb +0 -215
- data/lib/dependabot/file_fetchers/ruby/bundler/child_gemfile_finder.rb +0 -70
- data/lib/dependabot/file_fetchers/ruby/bundler/gemspec_finder.rb +0 -98
- data/lib/dependabot/file_fetchers/ruby/bundler/path_gemspec_finder.rb +0 -114
- data/lib/dependabot/file_fetchers/ruby/bundler/require_relative_finder.rb +0 -67
- data/lib/dependabot/file_parsers/ruby/bundler.rb +0 -294
- data/lib/dependabot/file_parsers/ruby/bundler/file_preparer.rb +0 -86
- data/lib/dependabot/file_parsers/ruby/bundler/gemfile_checker.rb +0 -48
- data/lib/dependabot/file_updaters/ruby/bundler.rb +0 -123
- data/lib/dependabot/file_updaters/ruby/bundler/gemfile_updater.rb +0 -116
- data/lib/dependabot/file_updaters/ruby/bundler/gemspec_dependency_name_finder.rb +0 -52
- data/lib/dependabot/file_updaters/ruby/bundler/gemspec_sanitizer.rb +0 -298
- data/lib/dependabot/file_updaters/ruby/bundler/gemspec_updater.rb +0 -64
- data/lib/dependabot/file_updaters/ruby/bundler/git_pin_replacer.rb +0 -80
- data/lib/dependabot/file_updaters/ruby/bundler/git_source_remover.rb +0 -102
- data/lib/dependabot/file_updaters/ruby/bundler/lockfile_updater.rb +0 -389
- data/lib/dependabot/file_updaters/ruby/bundler/requirement_replacer.rb +0 -223
- data/lib/dependabot/metadata_finders/ruby/bundler.rb +0 -202
- data/lib/dependabot/update_checkers/ruby/bundler.rb +0 -331
- data/lib/dependabot/update_checkers/ruby/bundler/file_preparer.rb +0 -281
- data/lib/dependabot/update_checkers/ruby/bundler/force_updater.rb +0 -261
- data/lib/dependabot/update_checkers/ruby/bundler/latest_version_finder.rb +0 -169
- data/lib/dependabot/update_checkers/ruby/bundler/requirements_updater.rb +0 -283
- data/lib/dependabot/update_checkers/ruby/bundler/ruby_requirement_setter.rb +0 -115
- data/lib/dependabot/update_checkers/ruby/bundler/shared_bundler_helpers.rb +0 -246
- data/lib/dependabot/update_checkers/ruby/bundler/version_resolver.rb +0 -272
- 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
|