Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions bundler/lib/dependabot/bundler/file_fetcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def fetch_files
fetched_files += gemspecs
fetched_files << T.must(ruby_version_file) if ruby_version_file
fetched_files << T.must(tool_versions_file) if tool_versions_file
fetched_files << T.must(ruby_file_version_file) if ruby_file_version_file
fetched_files += path_gemspecs
fetched_files += find_included_files(fetched_files)

Expand Down Expand Up @@ -138,6 +139,35 @@ def tool_versions_file
@tool_versions_file ||= T.let(fetch_support_file(".tool-versions"), T.nilable(Dependabot::DependencyFile))
end

sig { returns(T.nilable(DependencyFile)) }
def ruby_file_version_file
return unless gemfile

@ruby_file_version_file ||= T.let(
begin
filename = ruby_file_version_filename
fetch_support_file(filename) if filename
end,
T.nilable(Dependabot::DependencyFile)
)
end

sig { returns(T.nilable(String)) }
def ruby_file_version_filename
content = gemfile&.content
return unless content

match = content.match(/^\s*ruby\s+file:\s*['"]([^'"]+)['"]/)
filename = match&.captures&.first
return unless filename

pathname = Pathname.new(filename).cleanpath
return unless pathname.relative?
return if pathname.to_s.start_with?("..")

pathname.to_s
end

sig { returns(T::Array[DependencyFile]) }
def path_gemspecs
gemspec_files = T.let([], T::Array[Dependabot::DependencyFile])
Expand Down
26 changes: 26 additions & 0 deletions bundler/lib/dependabot/bundler/file_parser/file_preparer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def prepared_dependency_files
lockfile,
ruby_version_file,
tool_versions_file,
ruby_file_version_file,
*imported_ruby_files,
*specification_files
].compact
Expand Down Expand Up @@ -89,6 +90,31 @@ def tool_versions_file
dependency_files.find { |f| f.name == ".tool-versions" }
end

# Returns the custom Ruby version file specified by `ruby file:` in the Gemfile
sig { returns(T.nilable(Dependabot::DependencyFile)) }
def ruby_file_version_file
filename = ruby_file_version_filename
return unless filename

dependency_files.find { |f| f.name == filename }
end

sig { returns(T.nilable(String)) }
def ruby_file_version_filename
content = gemfile&.content
return unless content

match = content.match(/^\s*ruby\s+file:\s*['"]([^'"]+)['"]/)
filename = match&.captures&.first
return unless filename

pathname = Pathname.new(filename).cleanpath
return unless pathname.relative?
return if pathname.to_s.start_with?("..")

pathname.to_s
end

sig { returns(T::Array[Dependabot::DependencyFile]) }
def imported_ruby_files
dependency_files
Expand Down
36 changes: 36 additions & 0 deletions bundler/lib/dependabot/bundler/file_updater/lockfile_updater.rb
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ def write_temporary_dependency_files
write_gemspecs(top_level_gemspecs)
write_ruby_version_file
write_tool_versions_file
write_ruby_file_version_file
write_gemspecs(path_gemspecs)
write_specification_files
write_imported_ruby_files
Expand Down Expand Up @@ -161,6 +162,16 @@ def write_tool_versions_file
File.write(path, T.must(tool_versions_file).content)
end

# Write the custom Ruby version file specified by `ruby file:` to the temporary directory
sig { void }
def write_ruby_file_version_file
return unless ruby_file_version_file

path = T.must(ruby_file_version_file).name
FileUtils.mkdir_p(Pathname.new(path).dirname)
File.write(path, T.must(ruby_file_version_file).content)
end
Comment thread
wt-l00 marked this conversation as resolved.

sig { params(files: T::Array[Dependabot::DependencyFile]).void }
def write_gemspecs(files)
files.each do |file|
Expand Down Expand Up @@ -218,6 +229,31 @@ def tool_versions_file
dependency_files.find { |f| f.name == ".tool-versions" }
end

# Returns the custom Ruby version file specified by `ruby file:` in the Gemfile
sig { returns(T.nilable(Dependabot::DependencyFile)) }
def ruby_file_version_file
filename = ruby_file_version_filename
return unless filename

dependency_files.find { |f| f.name == filename }
end

sig { returns(T.nilable(String)) }
def ruby_file_version_filename
content = gemfile&.content
return unless content

match = content.match(/^\s*ruby\s+file:\s*['"]([^'"]+)['"]/)
filename = match&.captures&.first
return unless filename

pathname = Pathname.new(filename).cleanpath
return unless pathname.relative?
return if pathname.to_s.start_with?("..")

pathname.to_s
end

sig { params(lockfile_body: String).returns(String) }
def post_process_lockfile(lockfile_body)
lockfile_body = reorder_git_dependencies(lockfile_body)
Expand Down
26 changes: 26 additions & 0 deletions bundler/lib/dependabot/bundler/update_checker/file_preparer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ def prepared_dependency_files
lockfile,
ruby_version_file,
tool_versions_file,
ruby_file_version_file,
*imported_ruby_files,
*specification_files
].compact
Expand Down Expand Up @@ -200,6 +201,31 @@ def tool_versions_file
dependency_files.find { |f| f.name == ".tool-versions" }
end

# Returns the custom Ruby version file specified by `ruby file:` in the Gemfile
sig { returns(T.nilable(Dependabot::DependencyFile)) }
def ruby_file_version_file
filename = ruby_file_version_filename
return unless filename

dependency_files.find { |f| f.name == filename }
end

sig { returns(T.nilable(String)) }
def ruby_file_version_filename
content = gemfile&.content
return unless content

match = content.match(/^\s*ruby\s+file:\s*['"]([^'"]+)['"]/)
filename = match&.captures&.first
return unless filename

pathname = Pathname.new(filename).cleanpath
return unless pathname.relative?
return if pathname.to_s.start_with?("..")

pathname.to_s
end
Comment thread
wt-l00 marked this conversation as resolved.

sig { returns(T::Array[Dependabot::DependencyFile]) }
def path_gemspecs
all = dependency_files.select { |f| f.name.end_with?(".gemspec") }
Expand Down
42 changes: 42 additions & 0 deletions bundler/spec/dependabot/bundler/file_fetcher_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,48 @@
end
end

context "with a custom version file referenced via `ruby file:` option" do
before do
stub_request(:get, url + "?ref=sha")
.with(headers: { "Authorization" => "token token" })
.to_return(
status: 200,
body: fixture("github", "contents_ruby_with_custom_version_file.json"),
headers: { "content-type" => "application/json" }
)

stub_request(:get, url + "Gemfile?ref=sha")
.with(headers: { "Authorization" => "token token" })
.to_return(
status: 200,
body: fixture("github", "gemfile_with_ruby_file_option_content.json"),
headers: { "content-type" => "application/json" }
)

stub_request(:get, url + "Gemfile.lock?ref=sha")
.with(headers: { "Authorization" => "token token" })
.to_return(
status: 200,
body: fixture("github", "gemfile_lock_content.json"),
headers: { "content-type" => "application/json" }
)

stub_request(:get, url + "custom-ruby-version?ref=sha")
.with(headers: { "Authorization" => "token token" })
.to_return(
status: 200,
body: fixture("github", "custom_ruby_version_content.json"),
headers: { "content-type" => "application/json" }
)
end

it "fetches the custom version file specified by `ruby file:` option" do
expect(file_fetcher_instance.files.count).to eq(3)
expect(file_fetcher_instance.files.map(&:name))
.to include("custom-ruby-version")
end
end

context "with a gems.rb rather than a Gemfile" do
before do
stub_request(:get, url + "?ref=sha")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@
its(:content) { is_expected.to eq("ruby 2.2.0\n") }
end

describe "the updated custom ruby version file specified by `ruby file:` option" do
subject do
prepared_dependency_files.find { |f| f.name == "custom-ruby-version" }
end

let(:dependency_files) { bundler_project_dependency_files("ruby_file_option") }

its(:content) { is_expected.to eq("2.2.0\n") }
end

describe "the updated .specification file" do
subject do
prepared_dependency_files.find { |f| f.name == "plugins/example/.specification" }
Expand Down
18 changes: 18 additions & 0 deletions bundler/spec/dependabot/bundler/file_updater_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,24 @@
end
end

context "when the Gemfile loads a custom ruby version file via `ruby file:` option" do
let(:project_name) { "ruby_file_option" }
let(:updater) do
described_class.new(
dependency_files: dependency_files,
dependencies: [dependency],
credentials: [{
"type" => "git_source",
"host" => "github.com"
}]
)
end

it "locks the updated gem to the latest version" do
expect(file.content).to include "business (1.5.0)"
end
end

context "when the Gemfile.lock didn't have a BUNDLED WITH line" do
let(:project_name) { "no_bundled_with" }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,12 @@
its([:version]) { is_expected.to eq(Dependabot::Bundler::Version.new("1.5.0")) }
end

context "when the Gemfile loads a custom ruby version file via `ruby file:` option" do
let(:dependency_files) { bundler_project_dependency_files("ruby_file_option") }

its([:version]) { is_expected.to eq(Dependabot::Bundler::Version.new("1.5.0")) }
end

context "with a gemspec and a Gemfile" do
let(:dependency_files) { bundler_project_dependency_files("gemfile_small_example") }

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
[
{
"name": "Gemfile",
"path": "Gemfile",
"sha": "88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
"size": 100,
"url": "https://api.github.com/repos/gocardless/bump/contents/Gemfile?ref=master",
"html_url": "https://github.com/gocardless/bump/blob/master/Gemfile",
"git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
"download_url": "https://raw.githubusercontent.com/gocardless/bump/master/Gemfile",
"type": "file",
"_links": {
"self": "https://api.github.com/repos/gocardless/bump/contents/Gemfile?ref=master",
"git": "https://api.github.com/repos/gocardless/bump/git/blobs/88b4e0a1c8093fae2b4fa52534035f9f85ed0956",
"html": "https://github.com/gocardless/bump/blob/master/Gemfile"
}
},
{
"name": "Gemfile.lock",
"path": "Gemfile.lock",
"sha": "d429264c8c2f0f306a422900c2f41123e07c31b4",
"size": 100,
"url": "https://api.github.com/repos/gocardless/bump/contents/Gemfile.lock?ref=master",
"html_url": "https://github.com/gocardless/bump/blob/master/Gemfile.lock",
"git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/d429264c8c2f0f306a422900c2f41123e07c31b4",
"download_url": "https://raw.githubusercontent.com/gocardless/bump/master/Gemfile.lock",
"type": "file",
"_links": {
"self": "https://api.github.com/repos/gocardless/bump/contents/Gemfile.lock?ref=master",
"git": "https://api.github.com/repos/gocardless/bump/git/blobs/d429264c8c2f0f306a422900c2f41123e07c31b4",
"html": "https://github.com/gocardless/bump/blob/master/Gemfile.lock"
}
},
{
"name": "custom-ruby-version",
"path": "custom-ruby-version",
"sha": "005119baaa0653ca59d923010341d8341daa8c43",
"size": 6,
"url": "https://api.github.com/repos/gocardless/bump/contents/custom-ruby-version?ref=master",
"html_url": "https://github.com/gocardless/bump/blob/master/custom-ruby-version",
"git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/005119baaa0653ca59d923010341d8341daa8c43",
"download_url": "https://raw.githubusercontent.com/gocardless/bump/master/custom-ruby-version",
"type": "file",
"_links": {
"self": "https://api.github.com/repos/gocardless/bump/contents/custom-ruby-version?ref=master",
"git": "https://api.github.com/repos/gocardless/bump/git/blobs/005119baaa0653ca59d923010341d8341daa8c43",
"html": "https://github.com/gocardless/bump/blob/master/custom-ruby-version"
}
}
]
18 changes: 18 additions & 0 deletions bundler/spec/fixtures/github/custom_ruby_version_content.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "custom-ruby-version",
"path": "custom-ruby-version",
"sha": "005119baaa0653ca59d923010341d8341daa8c43",
"size": 6,
"url": "https://api.github.com/repos/gocardless/bump/contents/custom-ruby-version?ref=master",
"html_url": "https://github.com/gocardless/bump/blob/master/custom-ruby-version",
"git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/005119baaa0653ca59d923010341d8341daa8c43",
"download_url": "https://raw.githubusercontent.com/gocardless/bump/master/custom-ruby-version",
"type": "file",
"content": "My4yLjAK\n",
"encoding": "base64",
"_links": {
"self": "https://api.github.com/repos/gocardless/bump/contents/custom-ruby-version?ref=master",
"git": "https://api.github.com/repos/gocardless/bump/git/blobs/005119baaa0653ca59d923010341d8341daa8c43",
"html": "https://github.com/gocardless/bump/blob/master/custom-ruby-version"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "Gemfile",
"path": "Gemfile",
"sha": "aabbcc1122334455667788990011223344556677",
"size": 80,
"url": "https://api.github.com/repos/gocardless/bump/contents/Gemfile?ref=master",
"html_url": "https://github.com/gocardless/bump/blob/master/Gemfile",
"git_url": "https://api.github.com/repos/gocardless/bump/git/blobs/aabbcc1122334455667788990011223344556677",
"download_url": "https://raw.githubusercontent.com/gocardless/bump/master/Gemfile",
"type": "file",
"content": "c291cmNlICJodHRwczovL3J1YnlnZW1zLm9yZyIKCnJ1YnkgZmlsZTogImN1\nc3RvbS1ydWJ5LXZlcnNpb24iCgpnZW0gImJ1c2luZXNzIiwgIn4+IDEuMCIK\n",
"encoding": "base64",
"_links": {
"self": "https://api.github.com/repos/gocardless/bump/contents/Gemfile?ref=master",
"git": "https://api.github.com/repos/gocardless/bump/git/blobs/aabbcc1122334455667788990011223344556677",
"html": "https://github.com/gocardless/bump/blob/master/Gemfile"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
source "https://rubygems.org"

ruby file: "custom-ruby-version"

gem "business", "~> 1.4.0"
gem "statesman", "~> 1.2.0"
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
GEM
remote: https://rubygems.org/
specs:
business (1.4.0)
statesman (1.2.1)

PLATFORMS
ruby

DEPENDENCIES
business (~> 1.4.0)
statesman (~> 1.2.0)

BUNDLED WITH
2.2.0
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2.2.0
Loading