From 5fc0bc2e68c1e45fb74468c719d752a280c0cdeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CThavachelvam?= <“thavaahariharangit@git.com”> Date: Fri, 5 Jul 2024 14:29:59 +0100 Subject: [PATCH 01/13] Converting absolute versions to constraints to check updates. --- composer/helpers/v2/src/UpdateChecker.php | 30 +++++++++++++++++-- .../update_checker/version_resolver.rb | 3 +- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/composer/helpers/v2/src/UpdateChecker.php b/composer/helpers/v2/src/UpdateChecker.php index cb849941cc..931fce979b 100644 --- a/composer/helpers/v2/src/UpdateChecker.php +++ b/composer/helpers/v2/src/UpdateChecker.php @@ -8,13 +8,16 @@ use Composer\Factory; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory; use Composer\Installer; +use Composer\Package\Link; use Composer\Package\PackageInterface; +use Composer\Semver\Constraint\Constraint; +use Composer\Semver\VersionParser; final class UpdateChecker { public static function getLatestResolvableVersion(array $args): ?string { - [$workingDirectory, $dependencyName, $gitCredentials, $registryCredentials] = $args; + [$workingDirectory, $dependencyName, $gitCredentials, $registryCredentials, $latestAllowableVersion] = $args; $httpBasicCredentials = []; @@ -48,10 +51,31 @@ public static function getLatestResolvableVersion(array $args): ?string $io->loadConfiguration($config); } + $package = $composer->getPackage(); + $versionParser = new VersionParser(); + $version = $package->getPrettyVersion(); + + try { + // Try to normalize the version string + $normalizedVersion = $versionParser->normalize($version); + + // If the normalized version string is the same as the original version string, + // then the original version string represents an exact version + if ($normalizedVersion === $version) { + // The version string represents an exact version + // constraint added to check possible update for any version greater than or equal to the current version + $constraint = new Constraint('>=', $normalizedVersion); + $link = new Link($package->getName(), $dependencyName, $constraint, 'requires', $constraint->getPrettyString()); + $package->setRequires([$dependencyName => $link]); + } + } catch (\UnexpectedValueException $e) { + // The version string does not represent an exact version + } + $install = new Installer( $io, $config, - $composer->getPackage(), // @phpstan-ignore-line + $package, // @phpstan-ignore-line $composer->getDownloadManager(), $composer->getRepositoryManager(), $composer->getLocker(), @@ -75,7 +99,7 @@ public static function getLatestResolvableVersion(array $args): ?string // if no lock is present, we do not do a partial update as // this is not supported by the Installer if ($composer->getLocker()->isLocked()) { - $install->setUpdateAllowList([$dependencyName]); + $install->setUpdateAllowList([$dependencyName => $latestAllowableVersion]); } $install->run(); diff --git a/composer/lib/dependabot/composer/update_checker/version_resolver.rb b/composer/lib/dependabot/composer/update_checker/version_resolver.rb index 81fac90e6b..501e3522ea 100644 --- a/composer/lib/dependabot/composer/update_checker/version_resolver.rb +++ b/composer/lib/dependabot/composer/update_checker/version_resolver.rb @@ -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 From 2ccfd031e3e4ce6ffdf23a698848119461261379 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CThavachelvam?= <“thavaahariharangit@git.com”> Date: Fri, 5 Jul 2024 16:09:06 +0100 Subject: [PATCH 02/13] Setting the latest allowable version as contraint. --- composer/helpers/v2/src/UpdateChecker.php | 27 +++++------------------ 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/composer/helpers/v2/src/UpdateChecker.php b/composer/helpers/v2/src/UpdateChecker.php index 931fce979b..16e41c9bae 100644 --- a/composer/helpers/v2/src/UpdateChecker.php +++ b/composer/helpers/v2/src/UpdateChecker.php @@ -11,7 +11,6 @@ use Composer\Package\Link; use Composer\Package\PackageInterface; use Composer\Semver\Constraint\Constraint; -use Composer\Semver\VersionParser; final class UpdateChecker { @@ -25,6 +24,7 @@ public static function getLatestResolvableVersion(array $args): ?string $httpBasicCredentials[$credentials['host']] = [ 'username' => $credentials['username'], 'password' => $credentials['password'], + ]; } @@ -52,25 +52,10 @@ public static function getLatestResolvableVersion(array $args): ?string } $package = $composer->getPackage(); - $versionParser = new VersionParser(); - $version = $package->getPrettyVersion(); - - try { - // Try to normalize the version string - $normalizedVersion = $versionParser->normalize($version); - - // If the normalized version string is the same as the original version string, - // then the original version string represents an exact version - if ($normalizedVersion === $version) { - // The version string represents an exact version - // constraint added to check possible update for any version greater than or equal to the current version - $constraint = new Constraint('>=', $normalizedVersion); - $link = new Link($package->getName(), $dependencyName, $constraint, 'requires', $constraint->getPrettyString()); - $package->setRequires([$dependencyName => $link]); - } - } catch (\UnexpectedValueException $e) { - // The version string does not represent an exact version - } + + $constraint = new Constraint('==', $latestAllowableVersion); + $link = new Link($package->getName(), $dependencyName, $constraint); + $package->setRequires([$dependencyName => $link]); $install = new Installer( $io, @@ -99,7 +84,7 @@ public static function getLatestResolvableVersion(array $args): ?string // if no lock is present, we do not do a partial update as // this is not supported by the Installer if ($composer->getLocker()->isLocked()) { - $install->setUpdateAllowList([$dependencyName => $latestAllowableVersion]); + $install->setUpdateAllowList([$dependencyName]); } $install->run(); From 31de80d37e6dbe3d9507619e89792d55be9b4acc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CThavachelvam?= <“thavaahariharangit@git.com”> Date: Fri, 5 Jul 2024 16:13:11 +0100 Subject: [PATCH 03/13] Setting the latest allowable version as contraint. --- composer/helpers/v2/src/UpdateChecker.php | 1 - 1 file changed, 1 deletion(-) diff --git a/composer/helpers/v2/src/UpdateChecker.php b/composer/helpers/v2/src/UpdateChecker.php index 16e41c9bae..3d6c3be8a7 100644 --- a/composer/helpers/v2/src/UpdateChecker.php +++ b/composer/helpers/v2/src/UpdateChecker.php @@ -24,7 +24,6 @@ public static function getLatestResolvableVersion(array $args): ?string $httpBasicCredentials[$credentials['host']] = [ 'username' => $credentials['username'], 'password' => $credentials['password'], - ]; } From 2a4b7c5206719a6d04f88408a55431647fac05f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CThavachelvam?= <“thavaahariharangit@git.com”> Date: Fri, 5 Jul 2024 16:22:46 +0100 Subject: [PATCH 04/13] Setting the latest allowable version as contraint. --- composer/helpers/v2/src/UpdateChecker.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer/helpers/v2/src/UpdateChecker.php b/composer/helpers/v2/src/UpdateChecker.php index 3d6c3be8a7..a78c02996c 100644 --- a/composer/helpers/v2/src/UpdateChecker.php +++ b/composer/helpers/v2/src/UpdateChecker.php @@ -10,7 +10,7 @@ use Composer\Installer; use Composer\Package\Link; use Composer\Package\PackageInterface; -use Composer\Semver\Constraint\Constraint; +use Composer\Package\Version\VersionParser; final class UpdateChecker { @@ -51,8 +51,8 @@ public static function getLatestResolvableVersion(array $args): ?string } $package = $composer->getPackage(); - - $constraint = new Constraint('==', $latestAllowableVersion); + $versionParser = new VersionParser(); + $constraint = $versionParser->parseConstraints($latestAllowableVersion); $link = new Link($package->getName(), $dependencyName, $constraint); $package->setRequires([$dependencyName => $link]); From cf9310dc530a40e343cb6092c95b9e63076a867f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CThavachelvam?= <“thavaahariharangit@git.com”> Date: Fri, 5 Jul 2024 14:29:59 +0100 Subject: [PATCH 05/13] Converting absolute versions to constraints to check updates. --- composer/helpers/v2/src/UpdateChecker.php | 30 +++++++++++++++++-- .../update_checker/version_resolver.rb | 3 +- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/composer/helpers/v2/src/UpdateChecker.php b/composer/helpers/v2/src/UpdateChecker.php index cb849941cc..931fce979b 100644 --- a/composer/helpers/v2/src/UpdateChecker.php +++ b/composer/helpers/v2/src/UpdateChecker.php @@ -8,13 +8,16 @@ use Composer\Factory; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory; use Composer\Installer; +use Composer\Package\Link; use Composer\Package\PackageInterface; +use Composer\Semver\Constraint\Constraint; +use Composer\Semver\VersionParser; final class UpdateChecker { public static function getLatestResolvableVersion(array $args): ?string { - [$workingDirectory, $dependencyName, $gitCredentials, $registryCredentials] = $args; + [$workingDirectory, $dependencyName, $gitCredentials, $registryCredentials, $latestAllowableVersion] = $args; $httpBasicCredentials = []; @@ -48,10 +51,31 @@ public static function getLatestResolvableVersion(array $args): ?string $io->loadConfiguration($config); } + $package = $composer->getPackage(); + $versionParser = new VersionParser(); + $version = $package->getPrettyVersion(); + + try { + // Try to normalize the version string + $normalizedVersion = $versionParser->normalize($version); + + // If the normalized version string is the same as the original version string, + // then the original version string represents an exact version + if ($normalizedVersion === $version) { + // The version string represents an exact version + // constraint added to check possible update for any version greater than or equal to the current version + $constraint = new Constraint('>=', $normalizedVersion); + $link = new Link($package->getName(), $dependencyName, $constraint, 'requires', $constraint->getPrettyString()); + $package->setRequires([$dependencyName => $link]); + } + } catch (\UnexpectedValueException $e) { + // The version string does not represent an exact version + } + $install = new Installer( $io, $config, - $composer->getPackage(), // @phpstan-ignore-line + $package, // @phpstan-ignore-line $composer->getDownloadManager(), $composer->getRepositoryManager(), $composer->getLocker(), @@ -75,7 +99,7 @@ public static function getLatestResolvableVersion(array $args): ?string // if no lock is present, we do not do a partial update as // this is not supported by the Installer if ($composer->getLocker()->isLocked()) { - $install->setUpdateAllowList([$dependencyName]); + $install->setUpdateAllowList([$dependencyName => $latestAllowableVersion]); } $install->run(); diff --git a/composer/lib/dependabot/composer/update_checker/version_resolver.rb b/composer/lib/dependabot/composer/update_checker/version_resolver.rb index 81fac90e6b..501e3522ea 100644 --- a/composer/lib/dependabot/composer/update_checker/version_resolver.rb +++ b/composer/lib/dependabot/composer/update_checker/version_resolver.rb @@ -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 From 0e39ada2724ac85403a6f83f686c85854fe1e25f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CThavachelvam?= <“thavaahariharangit@git.com”> Date: Fri, 5 Jul 2024 16:09:06 +0100 Subject: [PATCH 06/13] Setting the latest allowable version as contraint. --- composer/helpers/v2/src/UpdateChecker.php | 27 +++++------------------ 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/composer/helpers/v2/src/UpdateChecker.php b/composer/helpers/v2/src/UpdateChecker.php index 931fce979b..16e41c9bae 100644 --- a/composer/helpers/v2/src/UpdateChecker.php +++ b/composer/helpers/v2/src/UpdateChecker.php @@ -11,7 +11,6 @@ use Composer\Package\Link; use Composer\Package\PackageInterface; use Composer\Semver\Constraint\Constraint; -use Composer\Semver\VersionParser; final class UpdateChecker { @@ -25,6 +24,7 @@ public static function getLatestResolvableVersion(array $args): ?string $httpBasicCredentials[$credentials['host']] = [ 'username' => $credentials['username'], 'password' => $credentials['password'], + ]; } @@ -52,25 +52,10 @@ public static function getLatestResolvableVersion(array $args): ?string } $package = $composer->getPackage(); - $versionParser = new VersionParser(); - $version = $package->getPrettyVersion(); - - try { - // Try to normalize the version string - $normalizedVersion = $versionParser->normalize($version); - - // If the normalized version string is the same as the original version string, - // then the original version string represents an exact version - if ($normalizedVersion === $version) { - // The version string represents an exact version - // constraint added to check possible update for any version greater than or equal to the current version - $constraint = new Constraint('>=', $normalizedVersion); - $link = new Link($package->getName(), $dependencyName, $constraint, 'requires', $constraint->getPrettyString()); - $package->setRequires([$dependencyName => $link]); - } - } catch (\UnexpectedValueException $e) { - // The version string does not represent an exact version - } + + $constraint = new Constraint('==', $latestAllowableVersion); + $link = new Link($package->getName(), $dependencyName, $constraint); + $package->setRequires([$dependencyName => $link]); $install = new Installer( $io, @@ -99,7 +84,7 @@ public static function getLatestResolvableVersion(array $args): ?string // if no lock is present, we do not do a partial update as // this is not supported by the Installer if ($composer->getLocker()->isLocked()) { - $install->setUpdateAllowList([$dependencyName => $latestAllowableVersion]); + $install->setUpdateAllowList([$dependencyName]); } $install->run(); From dabb8a430edafec6ac51b7f05519ceabc76aed99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CThavachelvam?= <“thavaahariharangit@git.com”> Date: Fri, 5 Jul 2024 16:13:11 +0100 Subject: [PATCH 07/13] Setting the latest allowable version as contraint. --- composer/helpers/v2/src/UpdateChecker.php | 1 - 1 file changed, 1 deletion(-) diff --git a/composer/helpers/v2/src/UpdateChecker.php b/composer/helpers/v2/src/UpdateChecker.php index 16e41c9bae..3d6c3be8a7 100644 --- a/composer/helpers/v2/src/UpdateChecker.php +++ b/composer/helpers/v2/src/UpdateChecker.php @@ -24,7 +24,6 @@ public static function getLatestResolvableVersion(array $args): ?string $httpBasicCredentials[$credentials['host']] = [ 'username' => $credentials['username'], 'password' => $credentials['password'], - ]; } From 79acb934ae95fe21c77598f996648105540350c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CThavachelvam?= <“thavaahariharangit@git.com”> Date: Fri, 5 Jul 2024 16:22:46 +0100 Subject: [PATCH 08/13] Setting the latest allowable version as contraint. --- composer/helpers/v2/src/UpdateChecker.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer/helpers/v2/src/UpdateChecker.php b/composer/helpers/v2/src/UpdateChecker.php index 3d6c3be8a7..a78c02996c 100644 --- a/composer/helpers/v2/src/UpdateChecker.php +++ b/composer/helpers/v2/src/UpdateChecker.php @@ -10,7 +10,7 @@ use Composer\Installer; use Composer\Package\Link; use Composer\Package\PackageInterface; -use Composer\Semver\Constraint\Constraint; +use Composer\Package\Version\VersionParser; final class UpdateChecker { @@ -51,8 +51,8 @@ public static function getLatestResolvableVersion(array $args): ?string } $package = $composer->getPackage(); - - $constraint = new Constraint('==', $latestAllowableVersion); + $versionParser = new VersionParser(); + $constraint = $versionParser->parseConstraints($latestAllowableVersion); $link = new Link($package->getName(), $dependencyName, $constraint); $package->setRequires([$dependencyName => $link]); From d282719537d0b105bd99d38dad88af05852d2884 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CThavachelvam?= <“thavaahariharangit@git.com”> Date: Sat, 6 Jul 2024 21:57:33 +0100 Subject: [PATCH 09/13] Combine existing constraint with latest allowable version constraint. --- composer/helpers/v2/src/UpdateChecker.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/composer/helpers/v2/src/UpdateChecker.php b/composer/helpers/v2/src/UpdateChecker.php index a78c02996c..0d3ac0ee61 100644 --- a/composer/helpers/v2/src/UpdateChecker.php +++ b/composer/helpers/v2/src/UpdateChecker.php @@ -52,7 +52,17 @@ public static function getLatestResolvableVersion(array $args): ?string $package = $composer->getPackage(); $versionParser = new VersionParser(); - $constraint = $versionParser->parseConstraints($latestAllowableVersion); + $version = $package->getVersion(); // Returns the version of this package + + try { + // If the version can be parsed without throwing an exception, it's an absolute version + $versionParser->normalize($version); + $constraintString = '>=' . $version; // if absolute look for an update. + } catch (\UnexpectedValueException $e) { + // If an exception is thrown, it's not an absolute version + $constraintString = $version; + } + $constraint = $versionParser->parseConstraints('==' . $latestAllowableVersion . ' ' . $constraintString); $link = new Link($package->getName(), $dependencyName, $constraint); $package->setRequires([$dependencyName => $link]); From a6caf5a96821220e49f7816706d505c679adbf5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CThavachelvam?= <“thavaahariharangit@git.com”> Date: Mon, 8 Jul 2024 00:20:04 +0100 Subject: [PATCH 10/13] After smoke test. --- composer/helpers/v2/src/UpdateChecker.php | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/composer/helpers/v2/src/UpdateChecker.php b/composer/helpers/v2/src/UpdateChecker.php index 0d3ac0ee61..79fcc53465 100644 --- a/composer/helpers/v2/src/UpdateChecker.php +++ b/composer/helpers/v2/src/UpdateChecker.php @@ -52,17 +52,18 @@ public static function getLatestResolvableVersion(array $args): ?string $package = $composer->getPackage(); $versionParser = new VersionParser(); - $version = $package->getVersion(); // Returns the version of this package - - try { - // If the version can be parsed without throwing an exception, it's an absolute version - $versionParser->normalize($version); - $constraintString = '>=' . $version; // if absolute look for an update. - } catch (\UnexpectedValueException $e) { - // If an exception is thrown, it's not an absolute version - $constraintString = $version; + $dependabotConstraint = '==' . $latestAllowableVersion; + $composerConstraint = ''; + if (isset($package->getRequires()[$dependencyName])) { + // Main Composer Constraint + $composerConstraint = $package->getRequires()[$dependencyName]->getPrettyConstraint(); + } elseif (isset($package->getDevRequires()[$dependencyName])) { + // Dev Composer Constraint + $composerConstraint = $package->getDevRequires()[$dependencyName]->getPrettyConstraint(); } - $constraint = $versionParser->parseConstraints('==' . $latestAllowableVersion . ' ' . $constraintString); + $constraintString = $dependabotConstraint . ' ' . $composerConstraint; + + $constraint = $versionParser->parseConstraints($constraintString); $link = new Link($package->getName(), $dependencyName, $constraint); $package->setRequires([$dependencyName => $link]); From 966b28fd96e7509ccabfe2efd4c0837273edf3ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CThavachelvam?= <“thavaahariharangit@git.com”> Date: Mon, 8 Jul 2024 08:40:39 +0100 Subject: [PATCH 11/13] Code cleanup. --- composer/helpers/v2/src/UpdateChecker.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/composer/helpers/v2/src/UpdateChecker.php b/composer/helpers/v2/src/UpdateChecker.php index 79fcc53465..93e0de7454 100644 --- a/composer/helpers/v2/src/UpdateChecker.php +++ b/composer/helpers/v2/src/UpdateChecker.php @@ -53,15 +53,17 @@ public static function getLatestResolvableVersion(array $args): ?string $package = $composer->getPackage(); $versionParser = new VersionParser(); $dependabotConstraint = '==' . $latestAllowableVersion; - $composerConstraint = ''; + $constraintString = $dependabotConstraint; + // combine new dependabot constraints with the existing composer constraints (if exists) if (isset($package->getRequires()[$dependencyName])) { // Main Composer Constraint $composerConstraint = $package->getRequires()[$dependencyName]->getPrettyConstraint(); + $constraintString = $dependabotConstraint . ' ' . $composerConstraint; } elseif (isset($package->getDevRequires()[$dependencyName])) { // Dev Composer Constraint $composerConstraint = $package->getDevRequires()[$dependencyName]->getPrettyConstraint(); + $constraintString = $dependabotConstraint . ' ' . $composerConstraint; } - $constraintString = $dependabotConstraint . ' ' . $composerConstraint; $constraint = $versionParser->parseConstraints($constraintString); $link = new Link($package->getName(), $dependencyName, $constraint); From 06bed2b7fb1beaba1b4977cbd7a1269fc118bf25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CThavachelvam?= <“thavaahariharangit@git.com”> Date: Mon, 8 Jul 2024 13:11:34 +0100 Subject: [PATCH 12/13] Unit test fixes. --- .../update_checker/version_resolver_spec.rb | 13 +++- .../composer/update_checker_spec.rb | 70 ++++++++++++++++--- 2 files changed, 71 insertions(+), 12 deletions(-) diff --git a/composer/spec/dependabot/composer/update_checker/version_resolver_spec.rb b/composer/spec/dependabot/composer/update_checker/version_resolver_spec.rb index 8e3a7c3734..64d57335e2 100644 --- a/composer/spec/dependabot/composer/update_checker/version_resolver_spec.rb +++ b/composer/spec/dependabot/composer/update_checker/version_resolver_spec.rb @@ -57,6 +57,7 @@ context "with a library using a >= PHP constraint" do let(:project_name) { "php_specified_in_library" } let(:dependency_name) { "phpdocumentor/reflection-docblock" } + let(:latest_allowable_version) { Gem::Version.new("3.3.2") } let(:dependency_version) { "2.0.4" } let(:string_req) { "2.0.4" } @@ -66,6 +67,7 @@ context "with an application using a >= PHP constraint" do let(:project_name) { "php_specified_without_lockfile" } let(:dependency_name) { "phpdocumentor/reflection-docblock" } + let(:latest_allowable_version) { Gem::Version.new("3.3.2") } let(:dependency_version) { "2.0.4" } let(:string_req) { "2.0.4" } @@ -73,6 +75,7 @@ context "when the minimum version is invalid" do let(:dependency_version) { "4.2.0" } + let(:latest_allowable_version) { Gem::Version.new("4.3.1") } let(:string_req) { "4.2.0" } it { is_expected.to be >= Dependabot::Composer::Version.new("4.3.1") } @@ -83,6 +86,7 @@ context "when the minimum version is invalid" do let(:project_name) { "php_specified_min_invalid_without_lockfile" } let(:dependency_name) { "phpdocumentor/reflection-docblock" } + let(:latest_allowable_version) { Gem::Version.new("3.2.2") } let(:dependency_version) { "2.0.4" } let(:string_req) { "2.0.4" } @@ -103,11 +107,16 @@ 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(:dependency_name) { "php-http/client-implementation" } let(:dependency_version) { nil } - it { is_expected.to eq(Dependabot::Composer::Version.new("1.0")) } + # Root composer.json requires php-http/client-implementation ==6.0.0 ^1.0, it could not be found in any version, + it "raises a Dependabot::DependencyFileNotResolvable error" do + expect { resolver.latest_resolvable_version } + .to raise_error(Dependabot::DependencyFileNotResolvable) do |error| + expect(error.message).to include("Your requirements could not be resolved to an installable set of packages.") + end + end end context "with a dependency that uses a stability flag" do diff --git a/composer/spec/dependabot/composer/update_checker_spec.rb b/composer/spec/dependabot/composer/update_checker_spec.rb index a95e973b53..34d5e144bd 100644 --- a/composer/spec/dependabot/composer/update_checker_spec.rb +++ b/composer/spec/dependabot/composer/update_checker_spec.rb @@ -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 @@ -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 @@ -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 @@ -244,7 +256,13 @@ }] end - it { is_expected.to be >= Gem::Version.new("5.2.45") } + # setting the latest allowable version to 1.22.0 + before do + allow(checker).to receive(:latest_version_from_registry) + .and_return(Gem::Version.new("5.4.36")) + end + + it { is_expected.to be >= Gem::Version.new("5.4.36") } context "when as a platform requirement" do let(:project_name) { "old_php_platform" } @@ -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 @@ -465,8 +489,12 @@ 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.1")) end + # setting the latest allowable version to 2.4.1 + it "is between 2.0.0 and 3.0.0" do expect(latest_resolvable_version).to be < Gem::Version.new("3.0.0") expect(latest_resolvable_version).to be > Gem::Version.new("2.0.0") @@ -487,8 +515,8 @@ end let(:ignored_versions) { [">= 2.8.0"] } - it "is the highest resolvable version" do - expect(latest_resolvable_version).to eq(Gem::Version.new("2.1.7")) + it "latest version 1.22.0 cannot be resolved." do + expect(latest_resolvable_version).to be_nil end context "when the blocking dependency is a git dependency" do @@ -516,9 +544,8 @@ context "when there is no lockfile" do let(:project_name) { "version_conflict_without_lockfile" } - it "raises a resolvability error" do - expect { latest_resolvable_version } - .to raise_error(Dependabot::DependencyFileNotResolvable) + it "when no lockfile then version cannot be resolved" do + expect(latest_resolvable_version).to be_nil end end end @@ -554,12 +581,26 @@ context "when there is no lockfile" do let(:project_name) { "version_conflict_on_update_without_lockfile" } - it { is_expected.to be_nil } + # Root composer.json requires longman/telegram-bot ==1.22.0 * + it "raises a resolvability error" do + expect { latest_resolvable_version } + .to raise_error(Dependabot::DependencyFileNotResolvable) do |error| + expect(error.message) + .to include("Your requirements could not be resolved to an installable set of packages.") + end + end context "when the conflict comes from a loose PHP version" do let(:project_name) { "version_conflict_library" } - it { is_expected.to be_nil } + # Root composer.json requires longman/telegram-bot ==1.22.0 * + it "raises a resolvability error" do + expect { latest_resolvable_version } + .to raise_error(Dependabot::DependencyFileNotResolvable) do |error| + expect(error.message) + .to include("Your requirements could not be resolved to an installable set of packages.") + end + end end end end @@ -722,7 +763,10 @@ }] end + # setting the latest allowable version to 3.0.2 before do + allow(checker).to receive(:latest_version_from_registry) + .and_return(Gem::Version.new("3.0.2")) stub_request(:get, "https://wpackagist.org/packages.json") .to_return( status: 200, @@ -746,7 +790,7 @@ }] end - it { is_expected.to be >= Gem::Version.new("5.2.30") } + it { is_expected.to be_nil } end context "when a sub-dependency would block the update" do @@ -762,6 +806,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 From 66a7b484bf9b7a62c4f8cb7ab5aa0f2691c80792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CThavachelvam?= <“thavaahariharangit@git.com”> Date: Tue, 9 Jul 2024 11:54:43 +0100 Subject: [PATCH 13/13] Updated as per review comments and handling dev requires separately. --- composer/helpers/v2/src/UpdateChecker.php | 23 ++++++++++++------- .../composer/update_checker_spec.rb | 18 +++++++++++---- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/composer/helpers/v2/src/UpdateChecker.php b/composer/helpers/v2/src/UpdateChecker.php index 93e0de7454..ca9718a44f 100644 --- a/composer/helpers/v2/src/UpdateChecker.php +++ b/composer/helpers/v2/src/UpdateChecker.php @@ -52,23 +52,30 @@ public static function getLatestResolvableVersion(array $args): ?string $package = $composer->getPackage(); $versionParser = new VersionParser(); + // constraint from dependabot $dependabotConstraint = '==' . $latestAllowableVersion; - $constraintString = $dependabotConstraint; // combine new dependabot constraints with the existing composer constraints (if exists) if (isset($package->getRequires()[$dependencyName])) { - // Main Composer Constraint + // Root Composer Constraint $composerConstraint = $package->getRequires()[$dependencyName]->getPrettyConstraint(); - $constraintString = $dependabotConstraint . ' ' . $composerConstraint; + $combinedConstraint = $dependabotConstraint . ' ' . $composerConstraint; + $constraint = $versionParser->parseConstraints($combinedConstraint); + $link = new Link($package->getName(), $dependencyName, $constraint); + $package->setRequires([$dependencyName => $link]); } elseif (isset($package->getDevRequires()[$dependencyName])) { // Dev Composer Constraint $composerConstraint = $package->getDevRequires()[$dependencyName]->getPrettyConstraint(); - $constraintString = $dependabotConstraint . ' ' . $composerConstraint; + $combinedConstraint = $dependabotConstraint . ' ' . $composerConstraint; + $constraint = $versionParser->parseConstraints($combinedConstraint); + $link = new Link($package->getName(), $dependencyName, $constraint); + $package->setDevRequires([$dependencyName => $link]); + } else { + // No Composer Constraint + $constraint = $versionParser->parseConstraints($dependabotConstraint); + $link = new Link($package->getName(), $dependencyName, $constraint); + $package->setRequires([$dependencyName => $link]); } - $constraint = $versionParser->parseConstraints($constraintString); - $link = new Link($package->getName(), $dependencyName, $constraint); - $package->setRequires([$dependencyName => $link]); - $install = new Installer( $io, $config, diff --git a/composer/spec/dependabot/composer/update_checker_spec.rb b/composer/spec/dependabot/composer/update_checker_spec.rb index 34d5e144bd..00437e2cf4 100644 --- a/composer/spec/dependabot/composer/update_checker_spec.rb +++ b/composer/spec/dependabot/composer/update_checker_spec.rb @@ -489,12 +489,11 @@ 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"}}') + # setting the latest allowable version to 2.4.1 allow(checker).to receive(:latest_version_from_registry) .and_return(Gem::Version.new("2.4.1")) end - # setting the latest allowable version to 2.4.1 - it "is between 2.0.0 and 3.0.0" do expect(latest_resolvable_version).to be < Gem::Version.new("3.0.0") expect(latest_resolvable_version).to be > Gem::Version.new("2.0.0") @@ -544,8 +543,19 @@ context "when there is no lockfile" do let(:project_name) { "version_conflict_without_lockfile" } - it "when no lockfile then version cannot be resolved" do - expect(latest_resolvable_version).to be_nil + # setting the latest allowable version to 2.1.7 + before do + allow(checker).to receive(:latest_version_from_registry) + .and_return(Gem::Version.new("2.1.7")) + end + + # Root composer.json requires monolog/monolog ==2.1.7 1.22.0 + it "raises a resolvability error" do + expect { latest_resolvable_version } + .to raise_error(Dependabot::DependencyFileNotResolvable) do |error| + expect(error.message) + .to include("Your requirements could not be resolved to an installable set of packages.") + end end end end