diff --git a/src/Domain/Ci/Job/IntegratedTestOnNextMajorLatestMinorDevCiJob.php b/src/Domain/Ci/Job/IntegratedTestOnNextMajorLatestMinorDevCiJob.php index 17ca52477..ed1d5a480 100644 --- a/src/Domain/Ci/Job/IntegratedTestOnNextMajorLatestMinorDevCiJob.php +++ b/src/Domain/Ci/Job/IntegratedTestOnNextMajorLatestMinorDevCiJob.php @@ -72,7 +72,8 @@ protected function jobName(): CiJobEnum { * {@inheritdoc} */ public function exitEarly(): bool { - return !$this->matchingCoreVersionExists($this->drupalCoreVersionResolver, $this->output); + $next_minor_dev = $this->drupalCoreVersionResolver->getNextMinorDevCandidate(); + return !$this->drupalCoreVersionResolver->existsArbitrary($next_minor_dev) || !$this->matchingCoreVersionExists($this->drupalCoreVersionResolver, $this->output); } /** diff --git a/src/Domain/Composer/Version/DrupalCoreVersionResolver.php b/src/Domain/Composer/Version/DrupalCoreVersionResolver.php index c2cd8ea71..d276c78a0 100644 --- a/src/Domain/Composer/Version/DrupalCoreVersionResolver.php +++ b/src/Domain/Composer/Version/DrupalCoreVersionResolver.php @@ -156,6 +156,30 @@ public function resolvePredefined(DrupalCoreVersionEnum $version): string { } } + /** + * Determines if a given arbitrary version resolves to a version that exists. + * + * @param string $version + * The core version constraint. + * @param string $preferred_stability + * The stability, both minimum and preferred. Available options (in order of + * stability) are dev, alpha, beta, RC, and stable. + * @param bool $dev + * TRUE to allow dev stability results or FALSE not to. + * + * @return bool + * TRUE if the version exists or FALSE if not. + */ + public function existsArbitrary(string $version, string $preferred_stability = 'stable', bool $dev = TRUE): bool { + try { + $this->resolveArbitrary($version, $preferred_stability, $dev); + } + catch (OrcaVersionNotFoundException $e) { + return FALSE; + } + return TRUE; + } + /** * Finds the Drupal core version matching the given arbitrary criteria. * @@ -332,6 +356,17 @@ private function findNextMinorUnresolved(): string { return "{$current_minor}.0"; } + /** + * Gets a possible next minor dev value. + * + * @return string + * The next minor dev candidate string. + */ + public function getNextMinorDevCandidate(): string { + $next_minor = $this->findNextMinorUnresolved(); + return $this->convertToDev($next_minor); + } + /** * Finds the next minor dev version of Drupal core. * @@ -345,8 +380,14 @@ private function findNextMinorDev(): string { return $this->nextMinorDev; } - $next_minor = $this->findNextMinorUnresolved(); - $this->nextMinorDev = $this->convertToDev($next_minor); + $next_minor_dev = $this->getNextMinorDevCandidate(); + + if ($this->existsArbitrary($next_minor_dev)) { + $this->nextMinorDev = $this->resolveArbitrary($next_minor_dev); + } + else { + $this->nextMinorDev = $this->findNextMajorLatestMinorDev(); + } return $this->nextMinorDev; } diff --git a/tests/Domain/Ci/Job/IntegratedTestOnNextMajorLatestMinorDevCiJobTest.php b/tests/Domain/Ci/Job/IntegratedTestOnNextMajorLatestMinorDevCiJobTest.php index 4c9c32fb7..4a35d0065 100644 --- a/tests/Domain/Ci/Job/IntegratedTestOnNextMajorLatestMinorDevCiJobTest.php +++ b/tests/Domain/Ci/Job/IntegratedTestOnNextMajorLatestMinorDevCiJobTest.php @@ -10,6 +10,7 @@ use Acquia\Orca\Helper\EnvFacade; use Acquia\Orca\Helper\Process\ProcessRunner; use Acquia\Orca\Tests\Domain\Ci\Job\_Helper\CiJobTestBase; +use Prophecy\Argument; use Symfony\Component\Console\Output\OutputInterface; /** @@ -53,12 +54,29 @@ public function testInstall(): void { '--dev', ]) ->shouldBeCalledOnce(); + $this->drupalCoreVersionResolver + ->getNextMinorDevCandidate() + ->shouldBeCalledOnce() + ->willReturn(Argument::type('string')); + $this->drupalCoreVersionResolver + ->existsArbitrary(Argument::any()) + ->shouldBeCalledOnce() + ->willReturn(TRUE); + $job = $this->createJob(); $this->runInstallPhase($job); } public function testNoDrupalCoreVersionFound(): void { + $this->drupalCoreVersionResolver + ->getNextMinorDevCandidate() + ->shouldBeCalled() + ->willReturn(Argument::type('string')); + $this->drupalCoreVersionResolver + ->existsArbitrary(Argument::any()) + ->shouldBeCalled() + ->willReturn(TRUE); $this->assertExitsEarlyIfNoDrupalCoreVersionFound(); } @@ -77,6 +95,14 @@ public function testInstallOverrideProfile(): void { "--profile={$profile}", ]) ->shouldBeCalledOnce(); + $this->drupalCoreVersionResolver + ->getNextMinorDevCandidate() + ->shouldBeCalled() + ->willReturn(Argument::type('string')); + $this->drupalCoreVersionResolver + ->existsArbitrary(Argument::any()) + ->shouldBeCalled() + ->willReturn(TRUE); $job = $this->createJob(); $this->runInstallPhase($job); @@ -97,6 +123,14 @@ public function testInstallOverrideProjectTemplate(): void { "--project-template={$project_template}", ]) ->shouldBeCalledOnce(); + $this->drupalCoreVersionResolver + ->getNextMinorDevCandidate() + ->shouldBeCalled() + ->willReturn(Argument::type('string')); + $this->drupalCoreVersionResolver + ->existsArbitrary(Argument::any()) + ->shouldBeCalled() + ->willReturn(TRUE); $job = $this->createJob(); $this->runInstallPhase($job); @@ -112,6 +146,14 @@ public function testScript(): void { "--sut={$this->validSutName()}", ]) ->shouldBeCalledOnce(); + $this->drupalCoreVersionResolver + ->getNextMinorDevCandidate() + ->shouldBeCalled() + ->willReturn(Argument::type('string')); + $this->drupalCoreVersionResolver + ->existsArbitrary(Argument::any()) + ->shouldBeCalled() + ->willReturn(TRUE); $job = $this->createJob(); $this->runScriptPhase($job); @@ -128,6 +170,14 @@ public function testScriptOverrideProfile(): void { '--sut-only', ]) ->shouldBeCalledOnce(); + $this->drupalCoreVersionResolver + ->getNextMinorDevCandidate() + ->shouldBeCalled() + ->willReturn(Argument::type('string')); + $this->drupalCoreVersionResolver + ->existsArbitrary(Argument::any()) + ->shouldBeCalled() + ->willReturn(TRUE); $job = $this->createJob(); $this->runScriptPhase($job); diff --git a/tests/Domain/Composer/Version/DrupalCoreVersionResolverTest.php b/tests/Domain/Composer/Version/DrupalCoreVersionResolverTest.php index 8b76c4ef6..1ca786b06 100644 --- a/tests/Domain/Composer/Version/DrupalCoreVersionResolverTest.php +++ b/tests/Domain/Composer/Version/DrupalCoreVersionResolverTest.php @@ -15,10 +15,14 @@ use Prophecy\Prophecy\ObjectProphecy; /** - * @property \Acquia\Orca\Domain\Composer\Version\DrupalDotOrgApiClient|\Prophecy\Prophecy\ObjectProphecy $drupalDotOrgApiClient - * @property \Acquia\Orca\Domain\Composer\Version\VersionSelectorFactory|\Prophecy\Prophecy\ObjectProphecy $selectorFactory - * @property \Composer\Package\PackageInterface|\Prophecy\Prophecy\ObjectProphecy $package - * @property \Composer\Package\Version\VersionSelector|\Prophecy\Prophecy\ObjectProphecy $selector + * @property \Acquia\Orca\Domain\Composer\Version\DrupalDotOrgApiClient|\Prophecy\Prophecy\ObjectProphecy + * $drupalDotOrgApiClient + * @property \Acquia\Orca\Domain\Composer\Version\VersionSelectorFactory|\Prophecy\Prophecy\ObjectProphecy + * $selectorFactory + * @property \Composer\Package\PackageInterface|\Prophecy\Prophecy\ObjectProphecy + * $package + * @property \Composer\Package\Version\VersionSelector|\Prophecy\Prophecy\ObjectProphecy + * $selector */ class DrupalCoreVersionResolverTest extends TestCase { @@ -30,6 +34,8 @@ class DrupalCoreVersionResolverTest extends TestCase { protected PackageInterface|ObjectProphecy $package; + protected PackageInterface|ObjectProphecy $package2; + protected VersionSelector|ObjectProphecy $selector; private const CURRENT = '9.1.0'; @@ -44,6 +50,7 @@ protected function setUp(): void { ->getPrettyVersion() ->willReturn(self::CURRENT); $package = $this->package->reveal(); + $this->selector = $this->prophesize(VersionSelector::class); $this->selector ->findBestCandidate('drupal/core', Argument::any(), Argument::any()) @@ -289,20 +296,77 @@ public function testResolvePredefinedNextMinor(): void { self::assertSame('9.2.0-alpha1', $actual); } - public function testResolvePredefinedNextMinorDev(): void { - $this->expectGetCurrentToBeCalledOnce(); - $this->package + public function testResolvePredefinedNextMinorDevNotExists(): void { + $current_stable = '10.1.1'; + $current_dev = '10.2.x-dev'; + $next_major = '^11'; + $next_minor_dev = '11.x-dev'; + + $current_stable_package = $this->prophesize(PackageInterface::class); + $current_stable_package ->getPrettyVersion() - ->willReturn('9.1.x-dev'); - $this->selector->findBestCandidate('drupal/core', '*', 'stable') - ->willReturn($this->package->reveal()); - $resolver = $this->createDrupalCoreVersionResolver(); + ->willReturn($current_stable) + ->shouldBeCalled(); + $this->selector + ->findBestCandidate('drupal/core', '*', 'stable') + ->willReturn($current_stable_package->reveal()) + ->shouldBeCalled(); + + $this->selector + ->findBestCandidate('drupal/core', $current_dev, 'stable') + ->shouldBeCalled() + ->willReturn(FALSE); + + $next_minor_dev_package = $this->prophesize(PackageInterface::class); + $next_minor_dev_package + ->getPrettyVersion() + ->shouldBeCalled() + ->willReturn($next_minor_dev); + $this->selector + ->findBestCandidate('drupal/core', $next_major, 'dev') + ->shouldBeCalled() + ->willReturn($next_minor_dev_package->reveal()); + + $sut = $this->createDrupalCoreVersionResolver(); + + $actual = $sut->resolvePredefined(DrupalCoreVersionEnum::NEXT_MINOR_DEV()); + // Call again to test value caching. + $sut->resolvePredefined(DrupalCoreVersionEnum::NEXT_MINOR_DEV()); + + self::assertSame($next_minor_dev, $actual); + } + + public function testResolvePredefinedNextMinorDevExists(): void { + $current_stable = '10.1.1'; + $current_dev = '10.2.x-dev'; + + $current_stable_package = $this->prophesize(PackageInterface::class); + $current_stable_package + ->getPrettyVersion() + ->willReturn($current_stable) + ->shouldBeCalled(); + $this->selector + ->findBestCandidate('drupal/core', '*', 'stable') + ->willReturn($current_stable_package->reveal()) + ->shouldBeCalled(); + + $current_dev_package = $this->prophesize(PackageInterface::class); + $current_dev_package + ->getPrettyVersion() + ->shouldBeCalled() + ->willReturn($current_dev); + $this->selector + ->findBestCandidate('drupal/core', $current_dev, 'stable') + ->shouldBeCalled() + ->willReturn($current_dev_package->reveal()); + + $sut = $this->createDrupalCoreVersionResolver(); - $actual = $resolver->resolvePredefined(DrupalCoreVersionEnum::NEXT_MINOR_DEV()); + $actual = $sut->resolvePredefined(DrupalCoreVersionEnum::NEXT_MINOR_DEV()); // Call again to test value caching. - $resolver->resolvePredefined(DrupalCoreVersionEnum::NEXT_MINOR_DEV()); + $sut->resolvePredefined(DrupalCoreVersionEnum::NEXT_MINOR_DEV()); - self::assertSame('9.2.x-dev', $actual); + self::assertSame($current_dev, $actual); } public function testResolvePredefinedNextMajorLatestMinorBetaOrLater(): void {