diff --git a/src/Command/CommandBase.php b/src/Command/CommandBase.php index 8c217f6d3..431d5e527 100644 --- a/src/Command/CommandBase.php +++ b/src/Command/CommandBase.php @@ -2075,6 +2075,30 @@ protected function runDrushCacheClear(Closure $outputCallback, Checklist $checkl } } + /** + * @throws \Acquia\Cli\Exception\AcquiaCliException + */ + protected function runDrushDatabaseUpdates(Closure $outputCallback, Checklist $checklist): void + { + if ($this->getDrushDatabaseConnectionStatus()) { + $checklist->addItem('Applying pending database updates via Drush'); + $process = $this->localMachineHelper->execute([ + 'drush', + 'updatedb', + '--yes', + '--no-interaction', + '--verbose', + ], $outputCallback, $this->dir, false); + if (!$process->isSuccessful()) { + throw new AcquiaCliException('Unable to apply database updates via Drush. {message}', ['message' => $process->getErrorOutput()]); + } + // @infection-ignore-all + $checklist->completePreviousItem(); + } else { + $this->logger->notice('Drush does not have an active database connection. Skipping updatedb'); + } + } + /** * @throws \Acquia\Cli\Exception\AcquiaCliException */ diff --git a/src/Command/Pull/PullDatabaseCommand.php b/src/Command/Pull/PullDatabaseCommand.php index 7027e6677..28d75f50b 100644 --- a/src/Command/Pull/PullDatabaseCommand.php +++ b/src/Command/Pull/PullDatabaseCommand.php @@ -65,9 +65,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int $sourceEnvironment = $this->determineEnvironment($input, $output, true); $this->pullDatabase($input, $output, $sourceEnvironment, $onDemand, $noImport, $multipleDbs); + $outputCallback = $this->getOutputCallback($output, $this->checklist); if (!$noScripts) { - $this->runDrushCacheClear($this->getOutputCallback($output, $this->checklist), $this->checklist); - $this->runDrushSqlSanitize($this->getOutputCallback($output, $this->checklist), $this->checklist); + $this->runDrushDatabaseUpdates($outputCallback, $this->checklist); + $this->runDrushCacheClear($outputCallback, $this->checklist); + $this->runDrushSqlSanitize($outputCallback, $this->checklist); } return Command::SUCCESS; diff --git a/tests/phpunit/src/Commands/Pull/PullCommandTestBase.php b/tests/phpunit/src/Commands/Pull/PullCommandTestBase.php index 2c1c5a605..1c3a61308 100644 --- a/tests/phpunit/src/Commands/Pull/PullCommandTestBase.php +++ b/tests/phpunit/src/Commands/Pull/PullCommandTestBase.php @@ -100,6 +100,22 @@ protected function mockExecuteDrushCacheRebuild( ->shouldBeCalled(); } + protected function mockExecuteDrushUpdateDb( + ObjectProphecy $localMachineHelper, + ObjectProphecy $process + ): void { + $localMachineHelper + ->execute([ + 'drush', + 'updatedb', + '--yes', + '--no-interaction', + '--verbose', + ], Argument::type('callable'), $this->projectDir, false) + ->willReturn($process->reveal()) + ->shouldBeCalled(); + } + protected function mockExecuteDrushSqlSanitize( ObjectProphecy $localMachineHelper, ObjectProphecy $process diff --git a/tests/phpunit/src/Commands/Pull/PullDatabaseCommandTest.php b/tests/phpunit/src/Commands/Pull/PullDatabaseCommandTest.php index 2aff85856..b17002ce2 100644 --- a/tests/phpunit/src/Commands/Pull/PullDatabaseCommandTest.php +++ b/tests/phpunit/src/Commands/Pull/PullDatabaseCommandTest.php @@ -9,6 +9,7 @@ use Acquia\Cli\Command\Pull\PullDatabaseCommand; use Acquia\Cli\Exception\AcquiaCliException; use Acquia\Cli\Helpers\SshHelper; +use Acquia\Cli\Output\Checklist; use Acquia\Cli\Transformer\EnvironmentTransformer; use AcquiaCloudApi\Response\SiteInstanceDatabaseBackupResponse; use AcquiaCloudApi\Response\SiteInstanceDatabaseConnectionResponse; @@ -71,6 +72,7 @@ public function testPullDatabases(): void $this->mockExecuteDrushExists($localMachineHelper); $this->mockExecuteDrushStatus($localMachineHelper, $this->projectDir); $process = $this->mockProcess(); + $this->mockExecuteDrushUpdateDb($localMachineHelper, $process); $this->mockExecuteDrushCacheRebuild($localMachineHelper, $process); $this->mockExecuteDrushSqlSanitize($localMachineHelper, $process); @@ -86,6 +88,35 @@ public function testPullDatabases(): void $this->assertStringContainsString('[0] Dev, dev (vcs: master)', $output); $this->assertStringContainsString('Choose a database [my_db (default)]:', $output); $this->assertStringContainsString('Using a database backup that is 1', $output); + + $checklistReflection = new \ReflectionProperty($this->command, 'checklist'); + $checklist = $checklistReflection->getValue($this->command); + $checklistMessages = array_column($checklist->getItems(), 'message'); + $this->assertContains('Applying pending database updates via Drush', $checklistMessages); + } + + public function testRunDrushDatabaseUpdatesFails(): void + { + $localMachineHelper = $this->mockLocalMachineHelper(); + (new \ReflectionProperty($this->command, 'drushHasActiveDatabaseConnection'))->setValue($this->command, true); + (new \ReflectionProperty($this->command, 'dir'))->setValue($this->command, $this->projectDir); + $this->mockExecuteDrushUpdateDb($localMachineHelper, $this->mockProcess(false)); + + $this->expectException(AcquiaCliException::class); + $this->expectExceptionMessage('Unable to apply database updates via Drush. error'); + (new \ReflectionMethod($this->command, 'runDrushDatabaseUpdates')) + ->invoke($this->command, fn() => null, new Checklist($this->output)); + } + + public function testRunDrushDatabaseUpdatesNoDbConnection(): void + { + $this->output->setVerbosity(BufferedOutput::VERBOSITY_VERBOSE); + (new \ReflectionProperty($this->command, 'drushHasActiveDatabaseConnection'))->setValue($this->command, false); + + (new \ReflectionMethod($this->command, 'runDrushDatabaseUpdates')) + ->invoke($this->command, fn() => null, new Checklist($this->output)); + + $this->assertStringContainsString('Skipping updatedb', $this->output->fetch()); } public function testPullProdDatabase(): void