Skip to content

Commit 2abc07a

Browse files
committed
Bundler: Run v1 native helpers with bundler v1
This runs existing bundler v1 native helpers with `BUNDLER_VERSION=1`, not using the default version, which will be v2 once it's installed.
1 parent 750b6e0 commit 2abc07a

18 files changed

Lines changed: 374 additions & 82 deletions

File tree

.github/workflows/ci.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ jobs:
102102
run: |
103103
docker run --rm "$CORE_CI_IMAGE" bash -c "cd /opt/npm_and_yarn && npm run lint"
104104
docker run --rm "$CORE_CI_IMAGE" bash -c "cd /opt/npm_and_yarn && npm test"
105+
- name: Run bundler v1 native helper specs
106+
if: matrix.suite == 'bundler'
107+
run: |
108+
docker run --rm "$CORE_CI_IMAGE" bash -c \
109+
"cd /home/dependabot/dependabot-core/bundler/helpers/v1 && BUNDLER_VERSION=1 bundle install && BUNDLER_VERSION=1 bundle exec rspec spec"
105110
- name: Run ${{ matrix.suite }} tests with rspec
106111
run: |
107112
docker run --env "CI=true" --env "DEPENDABOT_TEST_ACCESS_TOKEN=$DEPENDABOT_TEST_ACCESS_TOKEN" --rm "$CORE_CI_IMAGE" bash -c \

bundler/helpers/v1/Gemfile

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
source "https://rubygems.org"
44

5-
# NOTE: This is intentionally left blank as it's currently only used to force
6-
# bundler to use v1 when executing native helpers by pointing the BUNDLE_GEMFILE
7-
# env to this Gemfile in Dependabot::Bundler::NativeHelpers
5+
# NOTE: Used to run native helper specs
6+
group :test do
7+
gem "byebug", "11.1.3"
8+
gem "rspec", "3.10.0"
9+
gem "rspec-its", "1.3.0"
10+
gem "vcr", "6.0.0"
11+
gem "webmock", "3.12.1"
12+
end

bundler/helpers/v1/build

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@ cd "$install_dir"
2121

2222
# NOTE: Sets `BUNDLED WITH` to match the installed v1 version in Gemfile.lock
2323
# forcing specs and native helpers to run with the same version
24-
BUNDLER_VERSION=1 bundle install
24+
BUNDLER_VERSION=1 bundle install --without test

bundler/spec/native_helpers/functions/conflicting_dependency_resolver_spec.rb renamed to bundler/helpers/v1/spec/functions/conflicting_dependency_resolver_spec.rb

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,14 @@
1010
described_class.new(
1111
dependency_name: dependency_name,
1212
target_version: target_version,
13-
lockfile_name: lockfile_name
13+
lockfile_name: "Gemfile.lock"
1414
)
1515
end
1616

1717
let(:dependency_name) { "dummy-pkg-a" }
1818
let(:target_version) { "2.0.0" }
1919

20-
let(:gemfile_fixture_name) { "blocked_by_subdep" }
21-
let(:lockfile_fixture_name) { "blocked_by_subdep.lock" }
20+
let(:project_name) { "blocked_by_subdep" }
2221

2322
describe "#conflicting_dependencies" do
2423
subject(:conflicting_dependencies) do
@@ -37,8 +36,7 @@
3736
end
3837

3938
context "for nested transitive dependencies" do
40-
let(:gemfile_fixture_name) { "transitive_blocking" }
41-
let(:lockfile_fixture_name) { "transitive_blocking.lock" }
39+
let(:project_name) { "transitive_blocking" }
4240
let(:dependency_name) { "activesupport" }
4341
let(:target_version) { "6.0.0" }
4442

@@ -96,8 +94,7 @@
9694
let(:dependency_name) { "activesupport" }
9795
let(:current_version) { "5.0.0" }
9896
let(:target_version) { "6.0.0" }
99-
let(:gemfile_fixture_name) { "multiple_blocking" }
100-
let(:lockfile_fixture_name) { "multiple_blocking.lock" }
97+
let(:project_name) { "multiple_blocking" }
10198

10299
it "returns all of the blocking dependencies" do
103100
expect(conflicting_dependencies).to match_array(

bundler/spec/native_helpers/functions/dependency_source_spec.rb renamed to bundler/helpers/v1/spec/functions/dependency_source_spec.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88

99
let(:dependency_source) do
1010
described_class.new(
11-
gemfile_name: gemfile_name,
11+
gemfile_name: "Gemfile",
1212
dependency_name: dependency_name
1313
)
1414
end
1515

1616
let(:dependency_name) { "business" }
1717

18-
let(:gemfile_fixture_name) { "specified_source" }
18+
let(:project_name) { "specified_source_no_lockfile" }
1919
let(:registry_url) { "https://repo.fury.io/greysteil/" }
2020
let(:gemfury_business_url) do
2121
"https://repo.fury.io/greysteil/api/v1/dependencies?gems=business"
@@ -47,7 +47,7 @@
4747
end
4848

4949
context "specified as the default source" do
50-
let(:gemfile_fixture_name) { "specified_default_source" }
50+
let(:project_name) { "specified_default_source_no_lockfile" }
5151

5252
it "returns all versions from the private source" do
5353
is_expected.to eq([
@@ -152,7 +152,7 @@
152152
end
153153

154154
context "that only implements the old Bundler index format..." do
155-
let(:gemfile_fixture_name) { "sidekiq_pro" }
155+
let(:project_name) { "sidekiq_pro" }
156156
let(:dependency_name) { "sidekiq-pro" }
157157
let(:registry_url) { "https://gems.contribsys.com/" }
158158

bundler/spec/native_helpers/functions/file_parser_spec.rb renamed to bundler/helpers/v1/spec/functions/file_parser_spec.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
)
1313
end
1414

15-
let(:gemfile_fixture_name) { "Gemfile" }
16-
let(:lockfile_fixture_name) { "Gemfile.lock" }
15+
let(:project_name) { "gemfile" }
1716

1817
describe "#parsed_gemfile" do
1918
subject(:parsed_gemfile) do

bundler/spec/native_helpers/functions/version_resolver_spec.rb renamed to bundler/helpers/v1/spec/functions/version_resolver_spec.rb

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
require "native_spec_helper"
44
require "shared_contexts"
55

6-
require "dependabot/dependency"
7-
86
RSpec.describe Functions::VersionResolver do
97
include_context "in a temporary bundler directory"
108
include_context "stub rubygems compact index"
@@ -13,8 +11,8 @@
1311
described_class.new(
1412
dependency_name: dependency_name,
1513
dependency_requirements: dependency_requirements,
16-
gemfile_name: gemfile_name,
17-
lockfile_name: lockfile_name
14+
gemfile_name: "Gemfile",
15+
lockfile_name: "Gemfile.lock"
1816
)
1917
end
2018

@@ -37,8 +35,7 @@
3735
in_tmp_folder { version_resolver.version_details }
3836
end
3937

40-
let(:gemfile_fixture_name) { "Gemfile" }
41-
let(:lockfile_fixture_name) { "Gemfile.lock" }
38+
let(:project_name) { "gemfile" }
4239
let(:requirement_string) { " >= 0" }
4340

4441
its([:version]) { is_expected.to eq(Gem::Version.new("1.4.0")) }
@@ -47,8 +44,7 @@
4744
context "with a private gemserver source" do
4845
include_context "stub rubygems compact index"
4946

50-
let(:gemfile_fixture_name) { "specified_source" }
51-
let(:lockfile_fixture_name) { "specified_source.lock" }
47+
let(:project_name) { "specified_source" }
5248
let(:requirement_string) { ">= 0" }
5349

5450
before do
@@ -72,8 +68,7 @@
7268
end
7369

7470
context "with a git source" do
75-
let(:gemfile_fixture_name) { "git_source" }
76-
let(:lockfile_fixture_name) { "git_source.lock" }
71+
let(:project_name) { "git_source" }
7772

7873
its([:version]) { is_expected.to eq(Gem::Version.new("1.6.0")) }
7974
its([:fetcher]) { is_expected.to be_nil }
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
source "https://rubygems.org"
2+
3+
gem "activesupport", "5.0.0"
4+
gem "actionview", "5.0.0"
5+
gem "actionmailer", "5.0.0"

0 commit comments

Comments
 (0)