dependabot-bundler 0.136.0 → 0.138.1
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 +4 -4
- data/helpers/v1/Gemfile +8 -3
- data/helpers/v1/build +2 -2
- data/helpers/v1/spec/functions/conflicting_dependency_resolver_spec.rb +133 -0
- data/helpers/v1/spec/functions/dependency_source_spec.rb +187 -0
- data/helpers/v1/spec/functions/file_parser_spec.rb +77 -0
- data/helpers/v1/spec/functions/version_resolver_spec.rb +97 -0
- data/helpers/v1/spec/native_spec_helper.rb +49 -0
- data/helpers/v1/spec/shared_contexts.rb +59 -0
- data/helpers/v2/.bundle/config +2 -0
- data/helpers/v2/.gitignore +9 -0
- data/helpers/v2/Gemfile +12 -0
- data/helpers/v2/build +23 -0
- data/helpers/v2/lib/functions.rb +67 -0
- data/helpers/v2/run.rb +30 -0
- data/helpers/v2/spec/functions_spec.rb +37 -0
- data/helpers/v2/spec/native_spec_helper.rb +50 -0
- data/lib/dependabot/bundler/file_parser.rb +13 -1
- data/lib/dependabot/bundler/file_updater.rb +3 -2
- data/lib/dependabot/bundler/file_updater/lockfile_updater.rb +4 -3
- data/lib/dependabot/bundler/helpers.rb +15 -3
- data/lib/dependabot/bundler/native_helpers.rb +8 -1
- data/lib/dependabot/bundler/update_checker.rb +12 -6
- data/lib/dependabot/bundler/update_checker/conflicting_dependency_resolver.rb +5 -2
- data/lib/dependabot/bundler/update_checker/force_updater.rb +6 -3
- data/lib/dependabot/bundler/update_checker/latest_version_finder.rb +6 -3
- data/lib/dependabot/bundler/update_checker/latest_version_finder/dependency_source.rb +5 -3
- data/lib/dependabot/bundler/update_checker/shared_bundler_helpers.rb +0 -4
- data/lib/dependabot/bundler/update_checker/version_resolver.rb +8 -4
- metadata +18 -4
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rspec/its"
|
4
|
+
require "webmock/rspec"
|
5
|
+
require "byebug"
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
8
|
+
$LOAD_PATH.unshift(File.expand_path("../monkey_patches", __dir__))
|
9
|
+
|
10
|
+
# Bundler monkey patches
|
11
|
+
require "definition_ruby_version_patch"
|
12
|
+
require "definition_bundler_version_patch"
|
13
|
+
require "git_source_patch"
|
14
|
+
|
15
|
+
require "functions"
|
16
|
+
|
17
|
+
RSpec.configure do |config|
|
18
|
+
config.color = true
|
19
|
+
config.order = :rand
|
20
|
+
config.mock_with(:rspec) { |mocks| mocks.verify_partial_doubles = true }
|
21
|
+
config.raise_errors_for_deprecations!
|
22
|
+
end
|
23
|
+
|
24
|
+
# Duplicated in lib/dependabot/bundler/file_updater/lockfile_updater.rb
|
25
|
+
# TODO: Stop sanitizing the lockfile once we have bundler 2 installed
|
26
|
+
LOCKFILE_ENDING = /(?<ending>\s*(?:RUBY VERSION|BUNDLED WITH).*)/m.freeze
|
27
|
+
|
28
|
+
def project_dependency_files(project)
|
29
|
+
project_path = File.expand_path(File.join("../../spec/fixtures/projects/bundler1", project))
|
30
|
+
Dir.chdir(project_path) do
|
31
|
+
# NOTE: Include dotfiles (e.g. .npmrc)
|
32
|
+
files = Dir.glob("**/*", File::FNM_DOTMATCH)
|
33
|
+
files = files.select { |f| File.file?(f) }
|
34
|
+
files.map do |filename|
|
35
|
+
content = File.read(filename)
|
36
|
+
if filename == "Gemfile.lock"
|
37
|
+
content = content.gsub(LOCKFILE_ENDING, "")
|
38
|
+
end
|
39
|
+
{
|
40
|
+
name: filename,
|
41
|
+
content: content
|
42
|
+
}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def fixture(*name)
|
48
|
+
File.read(File.join("../../spec/fixtures", File.join(*name)))
|
49
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/compact_index_client"
|
4
|
+
require "bundler/compact_index_client/updater"
|
5
|
+
|
6
|
+
TMP_DIR_PATH = File.expand_path("../tmp", __dir__)
|
7
|
+
|
8
|
+
RSpec.shared_context "in a temporary bundler directory" do
|
9
|
+
let(:project_name) { "gemfile" }
|
10
|
+
|
11
|
+
let(:tmp_path) do
|
12
|
+
Dir.mkdir(TMP_DIR_PATH) unless Dir.exist?(TMP_DIR_PATH)
|
13
|
+
dir = Dir.mktmpdir("native_helper_spec_", TMP_DIR_PATH)
|
14
|
+
Pathname.new(dir).expand_path
|
15
|
+
end
|
16
|
+
|
17
|
+
before do
|
18
|
+
project_dependency_files(project_name).each do |file|
|
19
|
+
File.write(File.join(tmp_path, file[:name]), file[:content])
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def in_tmp_folder(&block)
|
24
|
+
Dir.chdir(tmp_path, &block)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
RSpec.shared_context "without caching rubygems" do
|
29
|
+
before do
|
30
|
+
# Stub Bundler to stop it using a cached versions of Rubygems
|
31
|
+
allow_any_instance_of(Bundler::CompactIndexClient::Updater).
|
32
|
+
to receive(:etag_for).and_return("")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
RSpec.shared_context "stub rubygems compact index" do
|
37
|
+
include_context "without caching rubygems"
|
38
|
+
|
39
|
+
before do
|
40
|
+
# Stub the Rubygems index
|
41
|
+
stub_request(:get, "https://index.rubygems.org/versions").
|
42
|
+
to_return(
|
43
|
+
status: 200,
|
44
|
+
body: fixture("ruby", "rubygems_responses", "index")
|
45
|
+
)
|
46
|
+
|
47
|
+
# Stub the Rubygems response for each dependency we have a fixture for
|
48
|
+
fixtures =
|
49
|
+
Dir[File.join("../../spec", "fixtures", "ruby", "rubygems_responses", "info-*")]
|
50
|
+
fixtures.each do |path|
|
51
|
+
dep_name = path.split("/").last.gsub("info-", "")
|
52
|
+
stub_request(:get, "https://index.rubygems.org/info/#{dep_name}").
|
53
|
+
to_return(
|
54
|
+
status: 200,
|
55
|
+
body: fixture("ruby", "rubygems_responses", "info-#{dep_name}")
|
56
|
+
)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/helpers/v2/Gemfile
ADDED
data/helpers/v2/build
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
set -e
|
4
|
+
|
5
|
+
install_dir=$1
|
6
|
+
if [ -z "$install_dir" ]; then
|
7
|
+
echo "usage: $0 INSTALL_DIR"
|
8
|
+
exit 1
|
9
|
+
fi
|
10
|
+
|
11
|
+
helpers_dir="$(dirname "${BASH_SOURCE[0]}")"
|
12
|
+
cp -r \
|
13
|
+
"$helpers_dir/.bundle" \
|
14
|
+
"$helpers_dir/lib" \
|
15
|
+
"$helpers_dir/run.rb" \
|
16
|
+
"$helpers_dir/Gemfile" \
|
17
|
+
"$install_dir"
|
18
|
+
|
19
|
+
cd "$install_dir"
|
20
|
+
|
21
|
+
# NOTE: Sets `BUNDLED WITH` to match the installed v1 version in Gemfile.lock
|
22
|
+
# forcing specs and native helpers to run with the same version
|
23
|
+
BUNDLER_VERSION=2 bundle install
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Functions
|
2
|
+
class NotImplementedError < StandardError; end
|
3
|
+
|
4
|
+
def self.parsed_gemfile(lockfile_name:, gemfile_name:, dir:)
|
5
|
+
raise NotImplementedError, "Bundler 2 adapter does not yet implement #{__method__}"
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.parsed_gemspec(lockfile_name:, gemspec_name:, dir:)
|
9
|
+
raise NotImplementedError, "Bundler 2 adapter does not yet implement #{__method__}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.vendor_cache_dir(dir:)
|
13
|
+
raise NotImplementedError, "Bundler 2 adapter does not yet implement #{__method__}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.update_lockfile(dir:, gemfile_name:, lockfile_name:, using_bundler2:,
|
17
|
+
credentials:, dependencies:)
|
18
|
+
raise NotImplementedError, "Bundler 2 adapter does not yet implement #{__method__}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.force_update(dir:, dependency_name:, target_version:, gemfile_name:,
|
22
|
+
lockfile_name:, using_bundler2:, credentials:,
|
23
|
+
update_multiple_dependencies:)
|
24
|
+
raise NotImplementedError, "Bundler 2 adapter does not yet implement #{__method__}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.dependency_source_type(gemfile_name:, dependency_name:, dir:,
|
28
|
+
credentials:)
|
29
|
+
raise NotImplementedError, "Bundler 2 adapter does not yet implement #{__method__}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.depencency_source_latest_git_version(gemfile_name:, dependency_name:,
|
33
|
+
dir:, credentials:,
|
34
|
+
dependency_source_url:,
|
35
|
+
dependency_source_branch:)
|
36
|
+
raise NotImplementedError, "Bundler 2 adapter does not yet implement #{__method__}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.private_registry_versions(gemfile_name:, dependency_name:, dir:,
|
40
|
+
credentials:)
|
41
|
+
raise NotImplementedError, "Bundler 2 adapter does not yet implement #{__method__}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.resolve_version(dependency_name:, dependency_requirements:,
|
45
|
+
gemfile_name:, lockfile_name:, using_bundler2:,
|
46
|
+
dir:, credentials:)
|
47
|
+
raise NotImplementedError, "Bundler 2 adapter does not yet implement #{__method__}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.jfrog_source(dir:, gemfile_name:, credentials:, using_bundler2:)
|
51
|
+
raise NotImplementedError, "Bundler 2 adapter does not yet implement #{__method__}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.git_specs(dir:, gemfile_name:, credentials:, using_bundler2:)
|
55
|
+
raise NotImplementedError, "Bundler 2 adapter does not yet implement #{__method__}"
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.set_bundler_flags_and_credentials(dir:, credentials:,
|
59
|
+
using_bundler2:)
|
60
|
+
raise NotImplementedError, "Bundler 2 adapter does not yet implement #{__method__}"
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.conflicting_dependencies(dir:, dependency_name:, target_version:,
|
64
|
+
lockfile_name:, using_bundler2:, credentials:)
|
65
|
+
raise NotImplementedError, "Bundler 2 adapter does not yet implement #{__method__}"
|
66
|
+
end
|
67
|
+
end
|
data/helpers/v2/run.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require "bundler"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(File.expand_path("./lib", __dir__))
|
5
|
+
$LOAD_PATH.unshift(File.expand_path("../v1/monkey_patches", __dir__))
|
6
|
+
|
7
|
+
# Bundler monkey patches
|
8
|
+
require "definition_ruby_version_patch"
|
9
|
+
require "definition_bundler_version_patch"
|
10
|
+
require "git_source_patch"
|
11
|
+
|
12
|
+
require "functions"
|
13
|
+
|
14
|
+
def output(obj)
|
15
|
+
print JSON.dump(obj)
|
16
|
+
end
|
17
|
+
|
18
|
+
begin
|
19
|
+
request = JSON.parse($stdin.read)
|
20
|
+
|
21
|
+
function = request["function"]
|
22
|
+
args = request["args"].transform_keys(&:to_sym)
|
23
|
+
|
24
|
+
output({ result: Functions.send(function, **args) })
|
25
|
+
rescue => error
|
26
|
+
output(
|
27
|
+
{ error: error.message, error_class: error.class, trace: error.backtrace }
|
28
|
+
)
|
29
|
+
exit(1)
|
30
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "native_spec_helper"
|
4
|
+
|
5
|
+
RSpec.describe Functions do
|
6
|
+
# Verify v1 method signatures are exist, but raise as NYI
|
7
|
+
{
|
8
|
+
parsed_gemfile: [ :lockfile_name, :gemfile_name, :dir ],
|
9
|
+
parsed_gemspec: [ :lockfile_name, :gemspec_name, :dir ],
|
10
|
+
vendor_cache_dir: [ :dir ],
|
11
|
+
update_lockfile: [ :dir, :gemfile_name, :lockfile_name, :using_bundler2, :credentials, :dependencies ],
|
12
|
+
force_update: [ :dir, :dependency_name, :target_version, :gemfile_name, :lockfile_name, :using_bundler2,
|
13
|
+
:credentials, :update_multiple_dependencies ],
|
14
|
+
dependency_source_type: [ :gemfile_name, :dependency_name, :dir, :credentials ],
|
15
|
+
depencency_source_latest_git_version: [ :gemfile_name, :dependency_name, :dir, :credentials, :dependency_source_url,
|
16
|
+
:dependency_source_branch ],
|
17
|
+
private_registry_versions: [:gemfile_name, :dependency_name, :dir, :credentials ],
|
18
|
+
resolve_version: [:dependency_name, :dependency_requirements, :gemfile_name, :lockfile_name, :using_bundler2,
|
19
|
+
:dir, :credentials],
|
20
|
+
jfrog_source: [:dir, :gemfile_name, :credentials, :using_bundler2],
|
21
|
+
git_specs: [:dir, :gemfile_name, :credentials, :using_bundler2],
|
22
|
+
set_bundler_flags_and_credentials: [:dir, :credentials, :using_bundler2],
|
23
|
+
conflicting_dependencies: [:dir, :dependency_name, :target_version, :lockfile_name, :using_bundler2, :credentials]
|
24
|
+
}.each do |function, kwargs|
|
25
|
+
describe "::#{function}" do
|
26
|
+
let(:args) do
|
27
|
+
kwargs.inject({}) do |args, keyword|
|
28
|
+
args.merge({ keyword => anything })
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it "raises a NYI" do
|
33
|
+
expect { Functions.send(function, **args) }.to raise_error(Functions::NotImplementedError)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rspec/its"
|
4
|
+
require "webmock/rspec"
|
5
|
+
require "byebug"
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
8
|
+
# TODO: Fork `v1/monkey_patches` into `v2/monkey_patches` ?
|
9
|
+
$LOAD_PATH.unshift(File.expand_path("../../v1/monkey_patches", __dir__))
|
10
|
+
|
11
|
+
# Bundler monkey patches
|
12
|
+
require "definition_ruby_version_patch"
|
13
|
+
require "definition_bundler_version_patch"
|
14
|
+
require "git_source_patch"
|
15
|
+
|
16
|
+
require "functions"
|
17
|
+
|
18
|
+
RSpec.configure do |config|
|
19
|
+
config.color = true
|
20
|
+
config.order = :rand
|
21
|
+
config.mock_with(:rspec) { |mocks| mocks.verify_partial_doubles = true }
|
22
|
+
config.raise_errors_for_deprecations!
|
23
|
+
end
|
24
|
+
|
25
|
+
# Duplicated in lib/dependabot/bundler/file_updater/lockfile_updater.rb
|
26
|
+
# TODO: Stop sanitizing the lockfile once we have bundler 2 installed
|
27
|
+
LOCKFILE_ENDING = /(?<ending>\s*(?:RUBY VERSION|BUNDLED WITH).*)/m.freeze
|
28
|
+
|
29
|
+
def project_dependency_files(project)
|
30
|
+
project_path = File.expand_path(File.join("../../spec/fixtures/projects/bundler1", project))
|
31
|
+
Dir.chdir(project_path) do
|
32
|
+
# NOTE: Include dotfiles (e.g. .npmrc)
|
33
|
+
files = Dir.glob("**/*", File::FNM_DOTMATCH)
|
34
|
+
files = files.select { |f| File.file?(f) }
|
35
|
+
files.map do |filename|
|
36
|
+
content = File.read(filename)
|
37
|
+
if filename == "Gemfile.lock"
|
38
|
+
content = content.gsub(LOCKFILE_ENDING, "")
|
39
|
+
end
|
40
|
+
{
|
41
|
+
name: filename,
|
42
|
+
content: content
|
43
|
+
}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def fixture(*name)
|
49
|
+
File.read(File.join("../../spec/fixtures", File.join(*name)))
|
50
|
+
end
|
@@ -23,6 +23,7 @@ module Dependabot
|
|
23
23
|
dependency_set += gemspec_dependencies
|
24
24
|
dependency_set += lockfile_dependencies
|
25
25
|
check_external_code(dependency_set.dependencies)
|
26
|
+
instrument_package_manager_version
|
26
27
|
dependency_set.dependencies
|
27
28
|
end
|
28
29
|
|
@@ -42,6 +43,17 @@ module Dependabot
|
|
42
43
|
end
|
43
44
|
end
|
44
45
|
|
46
|
+
def instrument_package_manager_version
|
47
|
+
version = Helpers.detected_bundler_version(lockfile)
|
48
|
+
Dependabot.instrument(
|
49
|
+
Notifications::FILE_PARSER_PACKAGE_MANAGER_VERSION_PARSED,
|
50
|
+
ecosystem: "bundler",
|
51
|
+
package_managers: {
|
52
|
+
"bundler" => version
|
53
|
+
}
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
45
57
|
def gemfile_dependencies
|
46
58
|
dependencies = DependencySet.new
|
47
59
|
|
@@ -301,7 +313,7 @@ module Dependabot
|
|
301
313
|
end
|
302
314
|
|
303
315
|
def bundler_version
|
304
|
-
@bundler_version ||= Helpers.bundler_version(lockfile)
|
316
|
+
@bundler_version ||= Helpers.bundler_version(lockfile, options: options)
|
305
317
|
end
|
306
318
|
end
|
307
319
|
end
|
@@ -151,7 +151,8 @@ module Dependabot
|
|
151
151
|
dependencies: dependencies,
|
152
152
|
dependency_files: dependency_files,
|
153
153
|
repo_contents_path: repo_contents_path,
|
154
|
-
credentials: credentials
|
154
|
+
credentials: credentials,
|
155
|
+
options: options
|
155
156
|
).updated_lockfile_content
|
156
157
|
end
|
157
158
|
|
@@ -162,7 +163,7 @@ module Dependabot
|
|
162
163
|
end
|
163
164
|
|
164
165
|
def bundler_version
|
165
|
-
@bundler_version ||= Helpers.bundler_version(lockfile)
|
166
|
+
@bundler_version ||= Helpers.bundler_version(lockfile, options: options)
|
166
167
|
end
|
167
168
|
end
|
168
169
|
end
|
@@ -33,11 +33,12 @@ module Dependabot
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def initialize(dependencies:, dependency_files:,
|
36
|
-
repo_contents_path: nil, credentials:)
|
36
|
+
repo_contents_path: nil, credentials:, options:)
|
37
37
|
@dependencies = dependencies
|
38
38
|
@dependency_files = dependency_files
|
39
39
|
@repo_contents_path = repo_contents_path
|
40
40
|
@credentials = credentials
|
41
|
+
@options = options
|
41
42
|
end
|
42
43
|
|
43
44
|
def updated_lockfile_content
|
@@ -54,7 +55,7 @@ module Dependabot
|
|
54
55
|
private
|
55
56
|
|
56
57
|
attr_reader :dependencies, :dependency_files, :repo_contents_path,
|
57
|
-
:credentials
|
58
|
+
:credentials, :options
|
58
59
|
|
59
60
|
def build_updated_lockfile
|
60
61
|
base_dir = dependency_files.first.directory
|
@@ -304,7 +305,7 @@ module Dependabot
|
|
304
305
|
end
|
305
306
|
|
306
307
|
def bundler_version
|
307
|
-
@bundler_version ||= Helpers.bundler_version(lockfile)
|
308
|
+
@bundler_version ||= Helpers.bundler_version(lockfile, options: options)
|
308
309
|
end
|
309
310
|
end
|
310
311
|
end
|
@@ -6,9 +6,21 @@ module Dependabot
|
|
6
6
|
V1 = "1"
|
7
7
|
V2 = "2"
|
8
8
|
|
9
|
-
#
|
10
|
-
|
11
|
-
|
9
|
+
# NOTE: options is a manditory argument to ensure we pass it from all calling classes
|
10
|
+
def self.bundler_version(_lockfile, options:)
|
11
|
+
# For now, force V2 if bundler_2_available
|
12
|
+
return V2 if options[:bundler_2_available]
|
13
|
+
|
14
|
+
# TODO: Add support for bundler v2 based on lockfile
|
15
|
+
# return V2 if lockfile.content.match?(/BUNDLED WITH\s+2/m)
|
16
|
+
|
17
|
+
V1
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.detected_bundler_version(lockfile)
|
21
|
+
return "unknown" unless lockfile
|
22
|
+
return V2 if lockfile.content.match?(/BUNDLED WITH\s+2/m)
|
23
|
+
|
12
24
|
V1
|
13
25
|
end
|
14
26
|
end
|