From 132c4c29df17484f5890eaa48a51fb64f081c57d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 21 Oct 2022 01:46:04 +0200 Subject: [PATCH] Fix crashes on Python libraries using multiple manifests If a library keeps a requirement duplicated in pyproject.toml/poetry.lock and a requirements.txt file, Dependabot updates will crash because we will try to widen requirements in the requirements file, which is not supported. Honestly, I don't know what users of this kind of setup expect so I opted for fixing the crash without changing the current behavior, namely, no updates. --- .../lib/dependabot/python/update_checker.rb | 15 +++++++ .../dependabot/python/update_checker_spec.rb | 41 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/python/lib/dependabot/python/update_checker.rb b/python/lib/dependabot/python/update_checker.rb index d21c4bb28aa..4819efa2d13 100644 --- a/python/lib/dependabot/python/update_checker.rb +++ b/python/lib/dependabot/python/update_checker.rb @@ -115,6 +115,17 @@ def updated_dependencies_after_full_unlock raise NotImplementedError end + def preferred_version_resolvable_with_unlock? + # Our requirements file updater doesn't currently support widening + # ranges, so avoid updating this dependency if widening ranges has been + # required and the dependency is present on a requirements file. + # Otherwise, we will crash later on. TODO: Consider what the correct + # behavior is in these cases. + return false if requirements_update_strategy == :widen_ranges && updating_requirements_file? + + super + end + def fetch_lowest_resolvable_security_fix_version fix_version = lowest_security_fix_version return latest_resolvable_version if fix_version.nil? @@ -299,6 +310,10 @@ def updating_in_file? requirement_files.any? { |f| f.end_with?(".in") } end + def updating_requirements_file? + requirement_files.any? { |f| f =~ /\.txt$|\.in$/ } + end + def requirement_files requirements.map { |r| r.fetch(:file) } end diff --git a/python/spec/dependabot/python/update_checker_spec.rb b/python/spec/dependabot/python/update_checker_spec.rb index da28f488713..c37dd3138c3 100644 --- a/python/spec/dependabot/python/update_checker_spec.rb +++ b/python/spec/dependabot/python/update_checker_spec.rb @@ -96,6 +96,47 @@ end it { is_expected.to be_falsey } end + + context "given a dependency in a poetry-based Python library, that's also in an additional requirements file" do + let(:dependency_files) { [pyproject, requirements_file] } + let(:pyproject_fixture_name) { "tilde_version.toml" } + + let(:dependency) do + Dependabot::Dependency.new( + name: "requests", + version: "1.2.3", + requirements: [{ + file: "pyproject.toml", + requirement: "^1.0.0", + groups: [], + source: nil + }, { + file: "requirements.txt", + requirement: "==1.2.8", + groups: [], + source: nil + }], + package_manager: "pip" + ) + end + + let(:pypi_url) { "https://pypi.org/simple/requests/" } + let(:pypi_response) do + fixture("pypi", "pypi_simple_response_requests.html") + end + + before do + stub_request(:get, "https://pypi.org/pypi/pendulum/json/"). + to_return( + status: 200, + body: fixture("pypi", "pypi_response_pendulum.json") + ) + end + + it "does not attempt an update, because updating requirements.txt file does not yet support widening ranges" do + expect(subject).to be_falsey + end + end end describe "#latest_version" do