dependabot-bundler 0.122.1 → 0.123.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/dependabot/bundler/file_fetcher.rb +1 -0
- data/lib/dependabot/bundler/file_parser.rb +44 -91
- data/lib/dependabot/bundler/file_parser/gemfile_declaration_finder.rb +5 -3
- data/lib/dependabot/bundler/file_updater.rb +8 -5
- data/lib/dependabot/bundler/file_updater/lockfile_updater.rb +16 -245
- data/lib/dependabot/bundler/native_helpers.rb +18 -0
- data/lib/dependabot/bundler/update_checker/file_preparer.rb +1 -0
- data/lib/dependabot/bundler/update_checker/force_updater.rb +32 -186
- data/lib/dependabot/bundler/update_checker/latest_version_finder.rb +0 -4
- data/lib/dependabot/bundler/update_checker/latest_version_finder/dependency_source.rb +43 -52
- data/lib/dependabot/bundler/update_checker/shared_bundler_helpers.rb +68 -89
- data/lib/dependabot/bundler/update_checker/version_resolver.rb +63 -132
- metadata +4 -6
- data/lib/dependabot/monkey_patches/bundler/definition_bundler_version_patch.rb +0 -15
- data/lib/dependabot/monkey_patches/bundler/definition_ruby_version_patch.rb +0 -17
- data/lib/dependabot/monkey_patches/bundler/git_source_patch.rb +0 -61
@@ -1,9 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dependabot/monkey_patches/bundler/definition_ruby_version_patch"
|
4
|
-
require "dependabot/monkey_patches/bundler/definition_bundler_version_patch"
|
5
|
-
require "dependabot/monkey_patches/bundler/git_source_patch"
|
6
|
-
|
7
3
|
require "excon"
|
8
4
|
|
9
5
|
require "dependabot/bundler/update_checker"
|
@@ -21,8 +17,6 @@ module Dependabot
|
|
21
17
|
require_relative "shared_bundler_helpers"
|
22
18
|
include SharedBundlerHelpers
|
23
19
|
|
24
|
-
GEM_NOT_FOUND_ERROR_REGEX = /locked to (?<name>[^\s]+) \(/.freeze
|
25
|
-
|
26
20
|
def initialize(dependency:, unprepared_dependency_files:,
|
27
21
|
repo_contents_path: nil, credentials:, ignored_versions:,
|
28
22
|
raise_on_ignored: false,
|
@@ -77,42 +71,47 @@ module Dependabot
|
|
77
71
|
return latest_version_details unless gemfile
|
78
72
|
|
79
73
|
SharedHelpers.with_git_configured(credentials: credentials) do
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
74
|
+
# We do not want the helper to handle errors for us as there are
|
75
|
+
# some errors we want to handle specifically ourselves, including
|
76
|
+
# potentially retrying in the case of the Ruby version being locked
|
77
|
+
in_a_native_bundler_context(error_handling: false) do |tmp_dir|
|
78
|
+
details = SharedHelpers.run_helper_subprocess(
|
79
|
+
command: NativeHelpers.helper_path,
|
80
|
+
function: "resolve_version",
|
81
|
+
args: {
|
82
|
+
dependency_name: dependency.name,
|
83
|
+
dependency_requirements: dependency.requirements,
|
84
|
+
gemfile_name: gemfile.name,
|
85
|
+
lockfile_name: lockfile&.name,
|
86
|
+
using_bundler_2: using_bundler_2?,
|
87
|
+
dir: tmp_dir,
|
88
|
+
credentials: credentials
|
89
|
+
}
|
90
|
+
)
|
91
|
+
|
92
|
+
return latest_version_details if details == "latest"
|
93
|
+
|
94
|
+
if details
|
95
|
+
details.transform_keys!(&:to_sym)
|
96
|
+
|
97
|
+
# If the old Gemfile index was used then it won't have checked
|
98
|
+
# Ruby compatibility. Fix that by doing the check manually and
|
99
|
+
# saying no update is possible if the Ruby version is a
|
100
|
+
# mismatch
|
101
|
+
return nil if ruby_version_incompatible?(details)
|
102
|
+
|
103
|
+
details[:version] = Gem::Version.new(details[:version])
|
108
104
|
end
|
109
105
|
details
|
110
106
|
end
|
111
107
|
end
|
112
|
-
rescue Dependabot::
|
108
|
+
rescue Dependabot::SharedHelpers::HelperSubprocessFailed => e
|
113
109
|
return if error_due_to_restrictive_upper_bound?(e)
|
114
110
|
return if circular_dependency_at_new_version?(e)
|
115
|
-
|
111
|
+
|
112
|
+
# If we are unable to handle the error ourselves, pass it on to the
|
113
|
+
# general bundler error handling.
|
114
|
+
handle_bundler_errors(e) unless ruby_lock_error?(e)
|
116
115
|
|
117
116
|
@gemspec_ruby_unlocked = true
|
118
117
|
regenerate_dependency_files_without_ruby_lock && retry
|
@@ -120,7 +119,9 @@ module Dependabot
|
|
120
119
|
# rubocop:enable Metrics/PerceivedComplexity
|
121
120
|
|
122
121
|
def circular_dependency_at_new_version?(error)
|
123
|
-
|
122
|
+
unless error.error_class.include?("CyclicDependencyError")
|
123
|
+
return false
|
124
|
+
end
|
124
125
|
|
125
126
|
error.message.include?("'#{dependency.name}'")
|
126
127
|
end
|
@@ -155,71 +156,30 @@ module Dependabot
|
|
155
156
|
).prepared_dependency_files
|
156
157
|
end
|
157
158
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
attempt ||= 1
|
170
|
-
attempt += 1
|
171
|
-
raise if attempt > 3 || !e.message.include?("Network error")
|
172
|
-
|
173
|
-
retry
|
174
|
-
end
|
175
|
-
|
176
|
-
dep = definition.resolve.find { |d| d.name == dependency.name }
|
177
|
-
return dep if dep
|
178
|
-
return if dependency.requirements.any? || !unlock_subdependencies
|
179
|
-
|
180
|
-
# If no definition was found and we're updating a sub-dependency,
|
181
|
-
# try again but without unlocking any other sub-dependencies
|
182
|
-
dependency_from_definition(unlock_subdependencies: false)
|
183
|
-
end
|
184
|
-
|
185
|
-
# rubocop:enable Metrics/PerceivedComplexity
|
186
|
-
|
187
|
-
def unlock_yanked_gem(dependencies_to_unlock, error)
|
188
|
-
raise unless error.message.match?(GEM_NOT_FOUND_ERROR_REGEX)
|
189
|
-
|
190
|
-
gem_name = error.message.match(GEM_NOT_FOUND_ERROR_REGEX).
|
191
|
-
named_captures["name"]
|
192
|
-
raise if dependencies_to_unlock.include?(gem_name)
|
193
|
-
|
194
|
-
dependencies_to_unlock << gem_name
|
195
|
-
end
|
196
|
-
|
197
|
-
def subdependencies
|
198
|
-
# If there's no lockfile we don't need to worry about
|
199
|
-
# subdependencies
|
200
|
-
return [] unless lockfile
|
201
|
-
|
202
|
-
all_deps = ::Bundler::LockfileParser.new(sanitized_lockfile_body).
|
203
|
-
specs.map(&:name).map(&:to_s).uniq
|
204
|
-
top_level = build_definition([]).dependencies.
|
205
|
-
map(&:name).map(&:to_s)
|
206
|
-
|
207
|
-
all_deps - top_level
|
159
|
+
def latest_version_details
|
160
|
+
@latest_version_details ||=
|
161
|
+
LatestVersionFinder.new(
|
162
|
+
dependency: dependency,
|
163
|
+
dependency_files: dependency_files,
|
164
|
+
repo_contents_path: repo_contents_path,
|
165
|
+
credentials: credentials,
|
166
|
+
ignored_versions: ignored_versions,
|
167
|
+
raise_on_ignored: @raise_on_ignored,
|
168
|
+
security_advisories: []
|
169
|
+
).latest_version_details
|
208
170
|
end
|
209
171
|
|
210
|
-
def ruby_version_incompatible?(
|
211
|
-
return false unless dep.source.is_a?(::Bundler::Source::Rubygems)
|
212
|
-
|
213
|
-
fetcher = dep.source.fetchers.first.fetchers.first
|
214
|
-
|
172
|
+
def ruby_version_incompatible?(details)
|
215
173
|
# It's only the old index we have a problem with
|
216
|
-
|
174
|
+
unless details[:fetcher] == "Bundler::Fetcher::Dependency"
|
175
|
+
return false
|
176
|
+
end
|
217
177
|
|
218
178
|
# If no Ruby version is specified, we don't have a problem
|
219
|
-
return false unless ruby_version
|
179
|
+
return false unless details[:ruby_version]
|
220
180
|
|
221
181
|
versions = Excon.get(
|
222
|
-
"
|
182
|
+
"https://rubygems.org/api/v1/versions/#{dependency.name}.json",
|
223
183
|
idempotent: true,
|
224
184
|
**SharedHelpers.excon_defaults
|
225
185
|
)
|
@@ -230,53 +190,23 @@ module Dependabot
|
|
230
190
|
|
231
191
|
ruby_requirement =
|
232
192
|
JSON.parse(versions.body).
|
233
|
-
find { |
|
193
|
+
find { |version| version["number"] == details[:version] }&.
|
234
194
|
fetch("ruby_version", nil)
|
235
195
|
|
236
196
|
# Give the benefit of the doubt if we can't find the version's
|
237
197
|
# required Ruby version.
|
238
198
|
return false unless ruby_requirement
|
239
199
|
|
240
|
-
ruby_requirement = Requirement.new(ruby_requirement)
|
200
|
+
ruby_requirement = Gem::Requirement.new(ruby_requirement)
|
201
|
+
current_ruby_version = Gem::Version.new(details[:ruby_version])
|
241
202
|
|
242
|
-
!ruby_requirement.satisfied_by?(
|
203
|
+
!ruby_requirement.satisfied_by?(current_ruby_version)
|
243
204
|
rescue JSON::ParserError, Excon::Error::Socket, Excon::Error::Timeout
|
244
205
|
# Give the benefit of the doubt if something goes wrong fetching
|
245
206
|
# version details (could be that it's a private index, etc.)
|
246
207
|
false
|
247
208
|
end
|
248
209
|
|
249
|
-
def build_definition(dependencies_to_unlock)
|
250
|
-
# Note: we lock shared dependencies to avoid any top-level
|
251
|
-
# dependencies getting unlocked (which would happen if they were
|
252
|
-
# also subdependencies of the dependency being unlocked)
|
253
|
-
::Bundler::Definition.build(
|
254
|
-
gemfile.name,
|
255
|
-
lockfile&.name,
|
256
|
-
gems: dependencies_to_unlock,
|
257
|
-
lock_shared_dependencies: true
|
258
|
-
)
|
259
|
-
end
|
260
|
-
|
261
|
-
def ruby_version
|
262
|
-
return nil unless gemfile
|
263
|
-
|
264
|
-
@ruby_version ||= build_definition([]).ruby_version&.gem_version
|
265
|
-
end
|
266
|
-
|
267
|
-
def latest_version_details
|
268
|
-
@latest_version_details ||=
|
269
|
-
LatestVersionFinder.new(
|
270
|
-
dependency: dependency,
|
271
|
-
dependency_files: dependency_files,
|
272
|
-
repo_contents_path: repo_contents_path,
|
273
|
-
credentials: credentials,
|
274
|
-
ignored_versions: ignored_versions,
|
275
|
-
raise_on_ignored: @raise_on_ignored,
|
276
|
-
security_advisories: []
|
277
|
-
).latest_version_details
|
278
|
-
end
|
279
|
-
|
280
210
|
def gemfile
|
281
211
|
dependency_files.find { |f| f.name == "Gemfile" } ||
|
282
212
|
dependency_files.find { |f| f.name == "gems.rb" }
|
@@ -287,9 +217,10 @@ module Dependabot
|
|
287
217
|
dependency_files.find { |f| f.name == "gems.locked" }
|
288
218
|
end
|
289
219
|
|
290
|
-
def
|
291
|
-
|
292
|
-
|
220
|
+
def using_bundler_2?
|
221
|
+
return unless lockfile
|
222
|
+
|
223
|
+
lockfile.content.match?(/BUNDLED WITH\s+2/m)
|
293
224
|
end
|
294
225
|
end
|
295
226
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dependabot-bundler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.123.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dependabot
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.123.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.
|
26
|
+
version: 0.123.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: byebug
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -191,6 +191,7 @@ files:
|
|
191
191
|
- lib/dependabot/bundler/file_updater/requirement_replacer.rb
|
192
192
|
- lib/dependabot/bundler/file_updater/ruby_requirement_setter.rb
|
193
193
|
- lib/dependabot/bundler/metadata_finder.rb
|
194
|
+
- lib/dependabot/bundler/native_helpers.rb
|
194
195
|
- lib/dependabot/bundler/requirement.rb
|
195
196
|
- lib/dependabot/bundler/update_checker.rb
|
196
197
|
- lib/dependabot/bundler/update_checker/file_preparer.rb
|
@@ -201,9 +202,6 @@ files:
|
|
201
202
|
- lib/dependabot/bundler/update_checker/shared_bundler_helpers.rb
|
202
203
|
- lib/dependabot/bundler/update_checker/version_resolver.rb
|
203
204
|
- lib/dependabot/bundler/version.rb
|
204
|
-
- lib/dependabot/monkey_patches/bundler/definition_bundler_version_patch.rb
|
205
|
-
- lib/dependabot/monkey_patches/bundler/definition_ruby_version_patch.rb
|
206
|
-
- lib/dependabot/monkey_patches/bundler/git_source_patch.rb
|
207
205
|
homepage: https://github.com/dependabot/dependabot-core
|
208
206
|
licenses:
|
209
207
|
- Nonstandard
|
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "bundler/definition"
|
4
|
-
|
5
|
-
# Ignore the Bundler version specified in the Gemfile (since the only Bundler
|
6
|
-
# version available to us is the one we're using).
|
7
|
-
module Bundler
|
8
|
-
class Definition
|
9
|
-
def expanded_dependencies
|
10
|
-
@expanded_dependencies ||=
|
11
|
-
expand_dependencies(dependencies + metadata_dependencies, @remote).
|
12
|
-
reject { |d| d.name == "bundler" }
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module BundlerDefinitionRubyVersionPatch
|
4
|
-
def index
|
5
|
-
@index ||= super.tap do
|
6
|
-
if ruby_version
|
7
|
-
requested_version = ruby_version.to_gem_version_with_patchlevel
|
8
|
-
sources.metadata_source.specs <<
|
9
|
-
Gem::Specification.new("ruby\0", requested_version)
|
10
|
-
end
|
11
|
-
|
12
|
-
sources.metadata_source.specs <<
|
13
|
-
Gem::Specification.new("ruby\0", "2.5.3p105")
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
Bundler::Definition.prepend(BundlerDefinitionRubyVersionPatch)
|
@@ -1,61 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Bundler
|
4
|
-
class Source
|
5
|
-
class Git
|
6
|
-
class GitProxy
|
7
|
-
private
|
8
|
-
|
9
|
-
# Bundler allows ssh authentication when talking to GitHub but there's
|
10
|
-
# no way for Dependabot to do so (it doesn't have any ssh keys).
|
11
|
-
# Instead, we convert all `git@github.com:` URLs to use HTTPS.
|
12
|
-
def configured_uri_for(uri)
|
13
|
-
uri = uri.gsub(%r{git@(.*?):/?}, 'https://\1/')
|
14
|
-
if uri.match?(/https?:/)
|
15
|
-
remote = URI(uri)
|
16
|
-
config_auth =
|
17
|
-
Bundler.settings[remote.to_s] || Bundler.settings[remote.host]
|
18
|
-
remote.userinfo ||= config_auth
|
19
|
-
remote.to_s
|
20
|
-
else
|
21
|
-
uri
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
module Bundler
|
30
|
-
class Source
|
31
|
-
class Git < Path
|
32
|
-
private
|
33
|
-
|
34
|
-
def serialize_gemspecs_in(destination)
|
35
|
-
original_load_paths = $LOAD_PATH.dup
|
36
|
-
reduced_load_paths = original_load_paths.
|
37
|
-
reject { |p| p.include?("/gems/") }
|
38
|
-
|
39
|
-
$LOAD_PATH.shift until $LOAD_PATH.empty?
|
40
|
-
reduced_load_paths.each { |p| $LOAD_PATH << p }
|
41
|
-
|
42
|
-
if destination.relative?
|
43
|
-
destination = destination.expand_path(Bundler.root)
|
44
|
-
end
|
45
|
-
Dir["#{destination}/#{@glob}"].each do |spec_path|
|
46
|
-
# Evaluate gemspecs and cache the result. Gemspecs
|
47
|
-
# in git might require git or other dependencies.
|
48
|
-
# The gemspecs we cache should already be evaluated.
|
49
|
-
spec = Bundler.load_gemspec(spec_path)
|
50
|
-
next unless spec
|
51
|
-
|
52
|
-
Bundler.rubygems.set_installed_by_version(spec)
|
53
|
-
Bundler.rubygems.validate(spec)
|
54
|
-
File.open(spec_path, "wb") { |file| file.write(spec.to_ruby) }
|
55
|
-
end
|
56
|
-
$LOAD_PATH.shift until $LOAD_PATH.empty?
|
57
|
-
original_load_paths.each { |p| $LOAD_PATH << p }
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|