Skip to content

Commit

Permalink
Passing the latest allowable version as package constraints (#10018)
Browse files Browse the repository at this point in the history
* Passing the latest allowable version as package constraints

* Unit tests updated as per the new functionality change.

* Unit tests updated as per the new functionality change.

* Removing comments as per the review comment.

* Reintroduced the @phpstan-ignore-line comment due to a build failure.

---------

Co-authored-by: “Thavachelvam <“thavaahariharangit@git.com”>
  • Loading branch information
thavaahariharangit and “Thavachelvam authored Jun 17, 2024
1 parent fff2779 commit 11ce6b8
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 11 deletions.
18 changes: 16 additions & 2 deletions composer/helpers/v2/src/UpdateChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
use Composer\Factory;
use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory;
use Composer\Installer;
use Composer\Package\Link;
use Composer\Package\PackageInterface;
use Composer\Package\Version\VersionParser;

final class UpdateChecker
{
public static function getLatestResolvableVersion(array $args): ?string
{
[$workingDirectory, $dependencyName, $gitCredentials, $registryCredentials] = $args;
[$workingDirectory, $dependencyName, $gitCredentials, $registryCredentials, $latestAllowableVersion] = $args;

$httpBasicCredentials = [];

Expand Down Expand Up @@ -48,10 +50,22 @@ public static function getLatestResolvableVersion(array $args): ?string
$io->loadConfiguration($config);
}

$package = $composer->getPackage();

$versionParser = new VersionParser();

$constraint = $versionParser->parseConstraints($latestAllowableVersion); // your version constraint
$packageLink = new Link($package->getName(), $dependencyName, $constraint);

$requires = $package->getRequires();
$requires[$dependencyName] = $packageLink;

$package->setRequires($requires);

$install = new Installer(
$io,
$config,
$composer->getPackage(), // @phpstan-ignore-line
$package, // @phpstan-ignore-line
$composer->getDownloadManager(),
$composer->getRepositoryManager(),
$composer->getLocker(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ def run_update_checker
Dir.pwd,
dependency.name.downcase,
git_credentials,
registry_credentials
registry_credentials,
@latest_allowable_version.to_s
]
)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
let(:dependency_name) { "phpdocumentor/reflection-docblock" }
let(:dependency_version) { "2.0.4" }
let(:string_req) { "2.0.4" }
let(:latest_allowable_version) { Gem::Version.new("3.3.2") }

it { is_expected.to eq(Dependabot::Composer::Version.new("3.3.2")) }
end
Expand All @@ -68,12 +69,14 @@
let(:dependency_name) { "phpdocumentor/reflection-docblock" }
let(:dependency_version) { "2.0.4" }
let(:string_req) { "2.0.4" }
let(:latest_allowable_version) { Gem::Version.new("3.3.2") }

it { is_expected.to eq(Dependabot::Composer::Version.new("3.3.2")) }

context "when the minimum version is invalid" do
let(:dependency_version) { "4.2.0" }
let(:string_req) { "4.2.0" }
let(:latest_allowable_version) { Gem::Version.new("4.3.1") }

it { is_expected.to be >= Dependabot::Composer::Version.new("4.3.1") }
end
Expand All @@ -85,6 +88,7 @@
let(:dependency_name) { "phpdocumentor/reflection-docblock" }
let(:dependency_version) { "2.0.4" }
let(:string_req) { "2.0.4" }
let(:latest_allowable_version) { Gem::Version.new("3.2.2") }

it { is_expected.to eq(Dependabot::Composer::Version.new("3.2.2")) }
end
Expand All @@ -103,7 +107,7 @@
context "with a dependency that's provided by another dep" do
let(:project_name) { "provided_dependency" }
let(:string_req) { "^1.0" }
let(:latest_allowable_version) { Gem::Version.new("6.0.0") }
let(:latest_allowable_version) { Gem::Version.new("1.0.0") }
let(:dependency_name) { "php-http/client-implementation" }
let(:dependency_version) { nil }

Expand Down
70 changes: 63 additions & 7 deletions composer/spec/dependabot/composer/update_checker_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,12 @@
describe "#latest_resolvable_version" do
subject(:latest_resolvable_version) { checker.latest_resolvable_version }

# setting the latest allowable version to 1.22.0
before do
allow(checker).to receive(:latest_version_from_registry)
.and_return(Gem::Version.new("1.22.0"))
end

it "returns a non-normalized version, following semver" do
expect(latest_resolvable_version.segments.count).to eq(3)
end
Expand All @@ -209,7 +215,7 @@
context "when the user is ignoring the latest version" do
let(:ignored_versions) { [">= 1.22.0.a, < 4.0"] }

it { is_expected.to eq(Gem::Version.new("1.21.0")) }
it { is_expected.to eq(Gem::Version.new("1.22.0")) }
end

context "without a lockfile" do
Expand All @@ -228,6 +234,12 @@
}]
end

# setting the latest allowable version to 4.3.0
before do
allow(checker).to receive(:latest_version_from_registry)
.and_return(Gem::Version.new("4.3.0"))
end

it { is_expected.to be >= Gem::Version.new("4.3.0") }
end

Expand All @@ -244,26 +256,32 @@
}]
end

# setting the latest allowable version to 5.2.45
before do
allow(checker).to receive(:latest_version_from_registry)
.and_return(Gem::Version.new("5.2.45"))
end

it { is_expected.to be >= Gem::Version.new("5.2.45") }

context "when as a platform requirement" do
let(:project_name) { "old_php_platform" }

it { is_expected.to eq(Gem::Version.new("5.4.36")) }
it { is_expected.to eq(Gem::Version.new("5.2.45")) }

context "when an extension is specified that we don't have" do
let(:project_name) { "missing_extension" }

it "pretends the missing extension is there" do
expect(latest_resolvable_version)
.to eq(Dependabot::Composer::Version.new("5.4.36"))
.to eq(Dependabot::Composer::Version.new("5.2.45"))
end
end

context "when the platform requirement only specifies an extension" do
let(:project_name) { "bad_php" }

it { is_expected.to eq(Gem::Version.new("5.4.36")) }
it { is_expected.to eq(Gem::Version.new("5.2.45")) }
end
end
end
Expand All @@ -281,6 +299,12 @@
}]
end

# setting the latest allowable version to 5.2.45
before do
allow(checker).to receive(:latest_version_from_registry)
.and_return(Gem::Version.new("5.2.45"))
end

it { is_expected.to be >= Gem::Version.new("5.2.45") }
end
end
Expand Down Expand Up @@ -465,6 +489,8 @@
v1_metadata_url = "https://repo.packagist.org/p/#{dependency_name.downcase}.json"
# v1 url doesn't always return 404 for missing packages
stub_request(:get, v1_metadata_url).to_return(status: 200, body: '{"error":{"code":404,"message":"Not Found"}}')
allow(checker).to receive(:latest_version_from_registry)
.and_return(Gem::Version.new("2.4.2"))
end

it "is between 2.0.0 and 3.0.0" do
Expand All @@ -487,6 +513,12 @@
end
let(:ignored_versions) { [">= 2.8.0"] }

# set latest allowable version from registry to 2.1.7
before do
allow(checker).to receive(:latest_version_from_registry)
.and_return(Gem::Version.new("2.1.7"))
end

it "is the highest resolvable version" do
expect(latest_resolvable_version).to eq(Gem::Version.new("2.1.7"))
end
Expand Down Expand Up @@ -554,12 +586,16 @@
context "when there is no lockfile" do
let(:project_name) { "version_conflict_on_update_without_lockfile" }

it { is_expected.to be_nil }
it "raises a helpful error" do
expect { latest_resolvable_version }.to raise_error(Dependabot::DependencyFileNotResolvable)
end

context "when the conflict comes from a loose PHP version" do
let(:project_name) { "version_conflict_library" }

it { is_expected.to be_nil }
it "raises a helpful error" do
expect { latest_resolvable_version }.to raise_error(Dependabot::DependencyFileNotResolvable)
end
end
end
end
Expand Down Expand Up @@ -650,6 +686,12 @@
}]
end

# set latest allowable version from registry to 1.3.0
before do
allow(checker).to receive(:latest_version_from_registry)
.and_return(Gem::Version.new("1.3.0"))
end

# Alternatively, this could raise an error. Either behaviour would be
# fine - the below is just what we get with Composer at the moment
# because we disabled downloading the files in
Expand Down Expand Up @@ -728,6 +770,8 @@
status: 200,
body: fixture("wpackagist_response.json")
)
allow(checker).to receive(:latest_version_from_registry)
.and_return(Gem::Version.new("3.0.2"))
end

it { is_expected.to be >= Gem::Version.new("3.0.2") }
Expand All @@ -746,7 +790,13 @@
}]
end

it { is_expected.to be >= Gem::Version.new("5.2.30") }
# set latest allowable version from registry to 5.2.7
before do
allow(checker).to receive(:latest_version_from_registry)
.and_return(Gem::Version.new("5.2.7"))
end

it { is_expected.to be >= Gem::Version.new("5.2.7") }
end

context "when a sub-dependency would block the update" do
Expand All @@ -762,6 +812,12 @@
}]
end

# setting the latest allowable version to 5.6.23
before do
allow(checker).to receive(:latest_version_from_registry)
.and_return(Gem::Version.new("5.6.23"))
end

# 5.5.0 series and up require an update to illuminate/contracts
it { is_expected.to be >= Gem::Version.new("5.6.23") }
end
Expand Down

0 comments on commit 11ce6b8

Please sign in to comment.