Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix poetry secondary source bug #4323

Merged
merged 8 commits into from
Jan 7, 2022
15 changes: 13 additions & 2 deletions python/lib/dependabot/python/file_updater/pyproject_preparer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,18 @@ def replace_sources(credentials)
pyproject_object = TomlRB.parse(pyproject_content)
poetry_object = pyproject_object.fetch("tool").fetch("poetry")

sources = pyproject_sources + config_variable_sources(credentials)
poetry_object["source"] = sources if sources.any?
sources_hash = pyproject_sources.map { |source| [source["url"], source] }.to_h

config_variable_sources(credentials).each do |source|
if sources_hash.key?(source["original_url"])
sources_hash[source["original_url"]]["url"] = source["url"]
else
source.delete("original_url")
sources_hash[source["url"]] = source
end
end

poetry_object["source"] = sources_hash.values unless sources_hash.empty?

TomlRB.dump(pyproject_object)
end
Expand Down Expand Up @@ -105,6 +115,7 @@ def config_variable_sources(credentials)
select { |cred| cred["type"] == "python_index" }.
map do |c|
{
"original_url" => c["index-url"],
"url" => AuthedUrlBuilder.authed_url(credential: c),
"name" => SecureRandom.hex[0..3],
"default" => c["replaces-base"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,4 +233,50 @@
end
end
end

describe "#prepared_project_file" do
subject(:prepared_project) { updater.send(:prepared_pyproject) }

context "with a python_index with auth details" do
let(:pyproject_fixture_name) { "private_secondary_source.toml" }
let(:lockfile_fixture_name) { "private_secondary_source.lock" }
let(:dependency_name) { "luigi" }
let(:dependency) do
Dependabot::Dependency.new(
name: dependency_name,
version: "2.8.9",
previous_version: "2.8.8",
package_manager: "pip",
requirements: [{
requirement: "2.8.9",
file: "pyproject.toml",
source: nil,
groups: ["dependencies"]
}],
previous_requirements: [{
requirement: "2.8.8",
file: "pyproject.toml",
source: nil,
groups: ["dependencies"]
}]
)
end
let(:credentials) do
[{
"type" => "python_index",
"index-url" => "https://some.internal.registry.com/pypi/",
"username" => "test",
"password" => "test"
}]
end

it "prepares a pyproject file without credentials in" do
repo_obj = TomlRB.parse(prepared_project, symbolize_keys: true)[:tool][:poetry][:source]
expect(repo_obj[0][:url]).to eq(credentials[0]["index-url"])

user_pass = "#{credentials[0]['user']}:#{credentials[0]['password']}@"
expect(repo_obj[0][:url]).to_not include(user_pass)
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,33 @@
it { is_expected.to include("default = true") }
end
end
context "with a private repository as a python_index" do
subject(:parsed_sources) { TomlRB.parse(replace_sources, symbolize_keys: true)[:tool][:poetry][:source] }
let(:pyproject_fixture_name) { "private_secondary_source.toml" }
let(:credentials) do
[{
"type" => "python_index",
"index-url" => "https://some.internal.registry.com/pypi/"
}]
end

it { is_expected.to contain_exactly({ name: "custom", secondary: true, url: credentials[0]["index-url"] }) }

context "that includes auth details" do
let(:credentials) do
[{
"type" => "python_index",
"index-url" => "https://some.internal.registry.com/pypi/",
"token" => "username:password"
}]
end

it {
is_expected.to contain_exactly({ name: "custom", secondary: true,
url: "https://username:password@some.internal.registry.com/pypi/" })
}
end
end
end

describe "#sanitize" do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,13 @@
end
end

context "set in a pyproject.toml" do
let(:pyproject_fixture_name) { "private_source.toml" }
let(:dependency_files) { [pyproject] }
let(:pypi_url) { "https://some.internal.registry.com/pypi/luigi/" }
it { is_expected.to eq(Gem::Version.new("2.6.0")) }
end

context "set in credentials" do
let(:credentials) do
[{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[tool.poetry]
name = "PythonProjects"
version = "2.0.0"
homepage = "https://github.com/roghu/py3_projects"
license = "MIT"
readme = "README.md"
authors = ["Dependabot <support@dependabot.com>"]
description = "Various small python projects."

[tool.poetry.dependencies]
python = "^3.7"
luigi = { version = "^2.8.8", source = "custom" }

[[tool.poetry.source]]
name = "custom"
url = "https://some.internal.registry.com/pypi/"
secondary = true
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
[[package]]
name = "docutils"
version = "0.18.1"
description = "Docutils -- Python Documentation Utilities"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"

[[package]]
name = "enum34"
version = "1.1.10"
description = "Python 3.4 Enum backported to 3.3, 3.2, 3.1, 2.7, 2.6, 2.5, and 2.4"
category = "main"
optional = false
python-versions = "*"

[[package]]
name = "lockfile"
version = "0.12.2"
description = "Platform-independent file locking module"
category = "main"
optional = false
python-versions = "*"

[[package]]
name = "luigi"
version = "2.8.8"
description = "Workflow mgmgt + task scheduling + dependency resolution"
category = "main"
optional = false
python-versions = "*"

[package.dependencies]
enum34 = ">1.1.0"
python-daemon = "<2.2.0"
python-dateutil = ">=2.7.5,<3"
tornado = ">=4.0,<5"

[package.extras]
prometheus = ["prometheus-client (==0.5.0)"]
toml = ["toml (<2.0.0)"]

[package.source]
type = "legacy"
url = "http://localhost:8080/simple"
reference = "custom"

[[package]]
name = "python-daemon"
version = "2.1.2"
description = "Library to implement a well-behaved Unix daemon process."
category = "main"
optional = false
python-versions = "*"

[package.dependencies]
docutils = "*"
lockfile = ">=0.10"

[[package]]
name = "python-dateutil"
version = "2.8.2"
description = "Extensions to the standard Python datetime module"
category = "main"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"

[package.dependencies]
six = ">=1.5"

[[package]]
name = "six"
version = "1.16.0"
description = "Python 2 and 3 compatibility utilities"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"

[[package]]
name = "tornado"
version = "4.5.3"
description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed."
category = "main"
optional = false
python-versions = "*"

[metadata]
lock-version = "1.1"
python-versions = "^3.7"
content-hash = "6217e8de9f5f3e12db2d2155d2e878cecb9a590ac6d1b19c85df9f64d3d57853"