Skip to content

Commit

Permalink
CLI-822: Add --task-wait option to API commands (#1829)
Browse files Browse the repository at this point in the history
* CLI-822: Add --task-wait option to API commands

* catch command failures

* hide json on success

* add test

* clean up tests and kill mutant

* fix test

* kill mutant

* kill mutant

* windows...

* WINDOWS...
  • Loading branch information
danepowell authored Nov 19, 2024
1 parent a5acd1d commit 7298135
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 19 deletions.
17 changes: 13 additions & 4 deletions src/Command/Api/ApiBaseCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Closure;
use GuzzleHttp\Psr7\Utils;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
Expand Down Expand Up @@ -93,6 +94,10 @@ protected function interact(InputInterface $input, OutputInterface $output): voi
parent::interact($input, $output);
}

/**
* @throws \Acquia\Cli\Exception\AcquiaCliException
* @throws \JsonException
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
if ($this->getName() === 'api:base') {
Expand Down Expand Up @@ -123,10 +128,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$exitCode = 1;
}

$contents = json_encode($response, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT);
$this->output->writeln($contents);

return $exitCode;
if ($exitCode || !$this->getParamFromInput($input, 'task-wait')) {
$contents = json_encode($response, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT);
$this->output->writeln($contents);
return $exitCode;
}
$notificationUuid = CommandBase::getNotificationUuidFromResponse($response);
$success = $this->waitForNotificationToComplete($this->cloudApiClientService->getClient(), $notificationUuid, "Waiting for task $notificationUuid to complete");
return $success ? Command::SUCCESS : Command::FAILURE;
}

public function setMethod(string $method): void
Expand Down
5 changes: 5 additions & 0 deletions src/Command/Api/ApiCommandHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ private function addApiCommandParameters(array $schema, array $acquiaCloudSpec,
$inputDefinition = array_merge($inputDefinition, $bodyInputDefinition);
}

// Add --task-wait parameter for responses with notifications.
if (array_key_exists(202, $schema['responses'])) {
$inputDefinition[] = new InputOption('task-wait', null, InputOption::VALUE_NONE, 'Wait for this task to complete');
}

$command->setDefinition(new InputDefinition($inputDefinition));
if ($usage) {
$command->addUsage(rtrim($usage));
Expand Down
3 changes: 3 additions & 0 deletions src/Command/CommandBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -1892,6 +1892,9 @@ private function writeCompletedMessage(NotificationResponse $notification): void
$this->io->writeln("Duration: $duration seconds");
}

/**
* @throws \Acquia\Cli\Exception\AcquiaCliException
*/
protected static function getNotificationUuidFromResponse(object $response): string
{
if (property_exists($response, 'links')) {
Expand Down
56 changes: 41 additions & 15 deletions tests/phpunit/src/Commands/Api/ApiCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,38 @@ protected function createCommand(): CommandBase
return $this->injectCommand(ApiBaseCommand::class);
}

/**
* @group brokenProphecy
*/
public function testTaskWait(): void
{
$environmentId = '24-a47ac10b-58cc-4372-a567-0e02b2c3d470';
$branch = 'my-feature-branch';
$this->mockRequest('postEnvironmentsSwitchCode', $environmentId, null, 'Switching code');
$this->clientProphecy->addOption('json', ['branch' => $branch])->shouldBeCalled();
$this->clientProphecy->addOption('headers', ['Accept' => 'application/hal+json, version=2'])
->shouldBeCalled();
$this->mockRequest('getNotificationByUuid', 'bfd9a39b-a85e-4de3-8a70-042d1c7e607a');
$this->command = $this->getApiCommandByName('api:environments:code-switch');
$this->executeCommand([
'--task-wait' => true,
'branch' => $branch,
'environmentId' => $environmentId,
]);
$output = $this->getDisplay();
$this->assertStringContainsString('[OK] The task with notification uuid 1bd3487e-71d1-4fca-a2d9-5f969b3d35c1 completed', $output);
$expected = <<<EOD
Progress: 100
Completed: Mon Jul 29 20:47:13 UTC 2019
Task type: Application added to recents list
Duration: 0 seconds
EOD;
$this->assertStringContainsStringIgnoringLineEndings($expected, $output);
$this->assertEquals(0, $this->getStatusCode());
}

public function testArgumentsInteraction(): void
{
$this->clientProphecy->addOption('headers', ['Accept' => 'application/hal+json, version=2'])
->shouldBeCalled();
$this->mockRequest('getEnvironmentsLog', ['289576-53785bca-1946-4adc-a022-e50d24686c20', 'apache-access']);
$this->command = $this->getApiCommandByName('api:environments:log-download');
$this->executeCommand([], [
'289576-53785bca-1946-4adc-a022-e50d24686c20',
Expand Down Expand Up @@ -106,7 +133,14 @@ public function testApiCommandErrorResponse(): void
// Assert.
$output = $this->getDisplay();
$this->assertJson($output);
$this->assertStringContainsString($mockBody->message, $output);
$expected = <<<EOD
{
"error": "not_found",
"message": "The application you are trying to access does not exist, or you do not have permission to access it."
}
EOD;
$this->assertStringEqualsStringIgnoringLineEndings($expected, $output);
$this->assertEquals(1, $this->getStatusCode());
}

Expand All @@ -133,12 +167,12 @@ public function testApiCommandExecutionForHttpGet(): void
$this->assertArrayHasKey('uuid', $contents[0]);
}

/**
* @group brokenProphecy
*/
public function testObjectParam(): void
{
$this->clientProphecy->addOption('headers', ['Accept' => 'application/hal+json, version=2'])
->shouldBeCalled();
$this->mockRequest('putEnvironmentCloudActions', '24-a47ac10b-58cc-4372-a567-0e02b2c3d470');
$this->clientProphecy->addOption('json', ['cloud-actions' => (object)['fb4aa87a-8be2-42c6-bdf0-ef9d09a3de70' => true]]);
$this->command = $this->getApiCommandByName('api:environments:cloud-actions-update');
$this->executeCommand([
'cloud-actions' => '{"fb4aa87a-8be2-42c6-bdf0-ef9d09a3de70":true}',
Expand Down Expand Up @@ -578,9 +612,6 @@ public function testOrganizationMemberDeleteByUserEmail(): void
$this->assertStringContainsString("Organization member removed", $output);
}

/**
* @group brokenProphecy
*/
public function testOrganizationMemberDeleteInvalidEmail(): void
{
$membersResponse = self::getMockResponseFromSpec('/organizations/{organizationUuid}/members', 'get', 200);
Expand All @@ -589,11 +620,6 @@ public function testOrganizationMemberDeleteInvalidEmail(): void
$this->clientProphecy->request('get', '/organizations/' . $orgId . '/members')
->willReturn($membersResponse->_embedded->items)->shouldBeCalled();

$this->mockRequest('postOrganizationMemberDelete', [
$orgId,
$memberUuid,
], null, 'Member removed');

$this->command = $this->getApiCommandByName('api:organizations:member-delete');
$this->expectException(AcquiaCliException::class);
$this->expectExceptionMessage('No matching user found in this organization');
Expand Down

0 comments on commit 7298135

Please sign in to comment.