From babf3bad4202827e003ac352dd7b6c7044c6572d Mon Sep 17 00:00:00 2001 From: Akash Karangale <56954201+akashkska@users.noreply.github.com> Date: Tue, 5 Mar 2024 04:45:59 +0530 Subject: [PATCH] GL-2039: Added prompt for nodejs and php project selection. (#1683) * GL-2039: Added prompt for nodejs and php project selection. * GL-2039: Updated getlist for pipeline migrate command to use drupal project as default. * GL-2039: Updated file improving test checks. * GL-2039: Updated test file to resolve error in test checks. * GL-2039: Resolved review commnets and added testcases. * kill mutant * GL-2039: Replace if-else with sw-case to resolve mutation warning. * GL-2039: Tried adding testcase to kill mutant. * GL-2039: Updated testcases and alternate logic. * GL-2039: Add assertion to kill mutant FalseValue and TrueValue. * GL-2039: Applied fix for mutant TRUEVAL and FLASEVAL. * Revert "GL-2039: Applied fix for mutant TRUEVAL and FLASEVAL." This reverts commit 6ed1e9f617849edc774e30ea1b770b3f0e762975. * GL-2039: Applied fix for mutant TRUEVAL and FLASEVAL. * Revert "GL-2039: Applied fix for mutant TRUEVAL and FLASEVAL." This reverts commit 0dac450ad6b83df7307ce3d7b520a6953f7f4e6a. * GL-2039-1: Added test file for ci-cd variables. * GL-2039-1: Refactor testcase. * GL-2039-1: Addressed integer increment mutant. * GL-2039-1: Added default value instead of fetching it from array. * GL-2039-1: Added assertion to kill MethodCallRemoval mutant. * GL-2039: modified testcase. --------- Co-authored-by: Dane Powell --- .../CodeStudio/CodeStudioCiCdVariables.php | 61 +++++++++- .../CodeStudio/CodeStudioWizardCommand.php | 80 +++++++++++-- tests/phpunit/src/CommandTestBase.php | 11 +- .../CodeStudioCiCdVariablesTest.php | 29 +++++ .../CodeStudioPipelinesMigrateCommandTest.php | 47 +++++++- .../CodeStudioWizardCommandTest.php | 112 +++++++++++++++++- tests/phpunit/src/Commands/WizardTestBase.php | 10 ++ 7 files changed, 327 insertions(+), 23 deletions(-) create mode 100644 tests/phpunit/src/Commands/CodeStudio/CodeStudioCiCdVariablesTest.php diff --git a/src/Command/CodeStudio/CodeStudioCiCdVariables.php b/src/Command/CodeStudio/CodeStudioCiCdVariables.php index f81893f59..0ac7319fb 100644 --- a/src/Command/CodeStudio/CodeStudioCiCdVariables.php +++ b/src/Command/CodeStudio/CodeStudioCiCdVariables.php @@ -10,13 +10,64 @@ class CodeStudioCiCdVariables { * @return array */ public static function getList(): array { - return array_column(self::getDefaults(), 'key'); + //getlist is being utilised in pipeline-migrate command. By default command is supporting drupal project but going forward need to support both drupal and nodejs project. + return array_column(self::getDefaultsForPhp(), 'key'); } /** - * @return array - */ - public static function getDefaults(?string $cloudApplicationUuid = NULL, ?string $cloudKey = NULL, ?string $cloudSecret = NULL, ?string $projectAccessTokenName = NULL, ?string $projectAccessToken = NULL, ?string $phpVersion = NULL): array { + * @return array + */ + public static function getDefaultsForNode(?string $cloudApplicationUuid = NULL, ?string $cloudKey = NULL, ?string $cloudSecret = NULL, ?string $projectAccessTokenName = NULL, ?string $projectAccessToken = NULL, ?string $nodeVersion = NULL): array { + return [ + [ + 'key' => 'ACQUIA_APPLICATION_UUID', + 'masked' => TRUE, + 'protected' => FALSE, + 'value' => $cloudApplicationUuid, + 'variable_type' => 'env_var', + ], + [ + 'key' => 'ACQUIA_CLOUD_API_TOKEN_KEY', + 'masked' => TRUE, + 'protected' => FALSE, + 'value' => $cloudKey, + 'variable_type' => 'env_var', + ], + [ + 'key' => 'ACQUIA_CLOUD_API_TOKEN_SECRET', + 'masked' => TRUE, + 'protected' => FALSE, + 'value' => $cloudSecret, + 'variable_type' => 'env_var', + ], + [ + 'key' => 'ACQUIA_GLAB_TOKEN_NAME', + 'masked' => TRUE, + 'protected' => FALSE, + 'value' => $projectAccessTokenName, + 'variable_type' => 'env_var', + ], + [ + 'key' => 'ACQUIA_GLAB_TOKEN_SECRET', + 'masked' => TRUE, + 'protected' => FALSE, + 'value' => $projectAccessToken, + 'variable_type' => 'env_var', + ], + [ + 'key' => 'NODE_VERSION', + 'masked' => TRUE, + 'protected' => FALSE, + 'value' => $nodeVersion, + 'variable_type' => 'env_var', + ], + ]; + } + + /** + * @return array + */ + public static function getDefaultsForPhp(?string $cloudApplicationUuid = NULL, ?string $cloudKey = NULL, ?string $cloudSecret = NULL, ?string $projectAccessTokenName = NULL, ?string $projectAccessToken = NULL, ?string $phpVersion = NULL): array { return [ [ 'key' => 'ACQUIA_APPLICATION_UUID', @@ -55,7 +106,7 @@ public static function getDefaults(?string $cloudApplicationUuid = NULL, ?string ], [ 'key' => 'PHP_VERSION', - 'masked' => FALSE, + 'masked' => TRUE, 'protected' => FALSE, 'value' => $phpVersion, 'variable_type' => 'env_var', diff --git a/src/Command/CodeStudio/CodeStudioWizardCommand.php b/src/Command/CodeStudio/CodeStudioWizardCommand.php index e8f7d479d..604759eb2 100644 --- a/src/Command/CodeStudio/CodeStudioWizardCommand.php +++ b/src/Command/CodeStudio/CodeStudioWizardCommand.php @@ -42,14 +42,31 @@ protected function execute(InputInterface $input, OutputInterface $output): int // But, we specifically need an API Token key-pair of Code Studio. // So we reauthenticate to be sure we're using the provided credentials. $this->reAuthenticate($cloudKey, $cloudSecret, $this->cloudCredentials->getBaseUri(), $this->cloudCredentials->getAccountsUri()); + $phpVersion = NULL; + $nodeVersion = NULL; + $projectType = $this->getListOfProjectType(); + $projectSelected = $this->io->choice('Select a project type', $projectType, "Drupal_project"); - $phpVersions = [ - 'PHP_version_8.1' => "8.1", - 'PHP_version_8.2' => "8.2", - ]; - $project = $this->io->choice('Select a PHP version', array_values($phpVersions), $phpVersions['PHP_version_8.1']); - $project = array_search($project, $phpVersions, TRUE); - $phpVersion = $phpVersions[$project]; + switch ($projectSelected) { + case "Drupal_project": + $phpVersions = [ + 'PHP_version_8.1' => "8.1", + 'PHP_version_8.2' => "8.2", + ]; + $project = $this->io->choice('Select a PHP version', array_values($phpVersions), "8.1"); + $project = array_search($project, $phpVersions, TRUE); + $phpVersion = $phpVersions[$project]; + break; + case "Node_project": + $nodeVersions = [ + 'NODE_version_18.17.1' => "18.17.1", + 'NODE_version_20.5.1' => "20.5.1", + ]; + $project = $this->io->choice('Select a NODE version', array_values($nodeVersions), "18.17.1"); + $project = array_search($project, $nodeVersions, TRUE); + $nodeVersion = $nodeVersions[$project]; + break; + } $appUuid = $this->determineCloudApplication(); @@ -97,7 +114,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int $projectAccessTokenName = 'acquia-codestudio'; $projectAccessToken = $this->createProjectAccessToken($project, $projectAccessTokenName); $this->updateGitLabProject($project); - $this->setGitLabCiCdVariables($project, $appUuid, $cloudKey, $cloudSecret, $projectAccessTokenName, $projectAccessToken, $phpVersion); + switch ($projectSelected) { + case "Drupal_project": + $this->setGitLabCiCdVariablesForPhpProject($project, $appUuid, $cloudKey, $cloudSecret, $projectAccessTokenName, $projectAccessToken, $phpVersion); + break; + case "Node_project": + $this->setGitLabCiCdVariablesForNodeProject($project, $appUuid, $cloudKey, $cloudSecret, $projectAccessTokenName, $projectAccessToken, $nodeVersion); + break; + } $this->createScheduledPipeline($project); $this->io->success([ @@ -143,6 +167,17 @@ private function getGitLabProjectAccessTokenByName(array $project, string $name) return NULL; } + /** + * @return array|null ? + */ + private function getListOfProjectType(): ?array { + $array = [ + 'Drupal_project', + 'Node_project', + ]; + return $array; + } + private function createProjectAccessToken(array $project, string $projectAccessTokenName): string { $this->io->writeln("Creating project access token..."); @@ -163,9 +198,34 @@ private function createProjectAccessToken(array $project, string $projectAccessT return $projectAccessToken['token']; } - private function setGitLabCiCdVariables(array $project, string $cloudApplicationUuid, string $cloudKey, string $cloudSecret, string $projectAccessTokenName, string $projectAccessToken, string $phpVersion): void { + private function setGitLabCiCdVariablesForPhpProject(array $project, string $cloudApplicationUuid, string $cloudKey, string $cloudSecret, string $projectAccessTokenName, string $projectAccessToken, string $phpVersion): void { + $this->io->writeln("Setting GitLab CI/CD variables for {$project['path_with_namespace']}.."); + $gitlabCicdVariables = CodeStudioCiCdVariables::getDefaultsForPhp($cloudApplicationUuid, $cloudKey, $cloudSecret, $projectAccessTokenName, $projectAccessToken, $phpVersion); + $gitlabCicdExistingVariables = $this->gitLabClient->projects() + ->variables($project['id']); + $gitlabCicdExistingVariablesKeyed = []; + foreach ($gitlabCicdExistingVariables as $variable) { + $key = $variable['key']; + $gitlabCicdExistingVariablesKeyed[$key] = $variable; + } + + foreach ($gitlabCicdVariables as $variable) { + $this->checklist->addItem("Setting GitLab CI/CD variables for {$variable['key']}"); + if (!array_key_exists($variable['key'], $gitlabCicdExistingVariablesKeyed)) { + $this->gitLabClient->projects() + ->addVariable($project['id'], $variable['key'], $variable['value'], $variable['protected'], NULL, ['masked' => $variable['masked'], 'variable_type' => $variable['variable_type']]); + } + else { + $this->gitLabClient->projects() + ->updateVariable($project['id'], $variable['key'], $variable['value'], $variable['protected'], NULL, ['masked' => $variable['masked'], 'variable_type' => $variable['variable_type']]); + } + $this->checklist->completePreviousItem(); + } + } + + private function setGitLabCiCdVariablesForNodeProject(array $project, string $cloudApplicationUuid, string $cloudKey, string $cloudSecret, string $projectAccessTokenName, string $projectAccessToken, string $nodeVersion): void { $this->io->writeln("Setting GitLab CI/CD variables for {$project['path_with_namespace']}.."); - $gitlabCicdVariables = CodeStudioCiCdVariables::getDefaults($cloudApplicationUuid, $cloudKey, $cloudSecret, $projectAccessTokenName, $projectAccessToken, $phpVersion); + $gitlabCicdVariables = CodeStudioCiCdVariables::getDefaultsForNode($cloudApplicationUuid, $cloudKey, $cloudSecret, $projectAccessTokenName, $projectAccessToken, $nodeVersion); $gitlabCicdExistingVariables = $this->gitLabClient->projects() ->variables($project['id']); $gitlabCicdExistingVariablesKeyed = []; diff --git a/tests/phpunit/src/CommandTestBase.php b/tests/phpunit/src/CommandTestBase.php index 5fb2eebde..1a86adc6e 100644 --- a/tests/phpunit/src/CommandTestBase.php +++ b/tests/phpunit/src/CommandTestBase.php @@ -648,7 +648,7 @@ protected function getMockGitLabVariables(): array { 'key' => 'ACQUIA_APPLICATION_UUID', 'masked' => TRUE, 'protected' => FALSE, - 'value' => '2b3f7cf0-6602-4590-948b-3b07b1b005ef', + 'value' => 'a47ac10b-58cc-4372-a567-0e02b2c3d470', 'variable_type' => 'env_var', ], 1 => [ @@ -656,7 +656,14 @@ protected function getMockGitLabVariables(): array { 'key' => 'ACQUIA_CLOUD_API_TOKEN_KEY', 'masked' => TRUE, 'protected' => FALSE, - 'value' => '111aae74-e81a-4052-b4b9-a27a62e6b6a6', + 'value' => '17feaf34-5d04-402b-9a67-15d5161d24e1', + 'variable_type' => 'env_var', + ], + 2 => [ + 'key' => 'ACQUIA_CLOUD_API_TOKEN_SECRET', + 'masked' => TRUE, + 'protected' => FALSE, + 'value' => 'X1u\/PIQXtYaoeui.4RJSJpGZjwmWYmfl5AUQkAebYE=', 'variable_type' => 'env_var', ], ]; diff --git a/tests/phpunit/src/Commands/CodeStudio/CodeStudioCiCdVariablesTest.php b/tests/phpunit/src/Commands/CodeStudio/CodeStudioCiCdVariablesTest.php new file mode 100644 index 000000000..197eec768 --- /dev/null +++ b/tests/phpunit/src/Commands/CodeStudio/CodeStudioCiCdVariablesTest.php @@ -0,0 +1,29 @@ +getDefaultsForNode(); + $this->testBooleanValues($variables); + $variables = $codeStudioCiCdVariablesObj->getDefaultsForPhp(); + $this->testBooleanValues($variables); + } + + protected function testBooleanValues(array $variables): void { + foreach ($variables as $variable) { + $maskedValue = $variable['masked']; + $this->assertEquals(TRUE, $maskedValue); + $protectedValue = $variable['protected']; + $this->assertEquals(FALSE, $protectedValue); + } + } + +} diff --git a/tests/phpunit/src/Commands/CodeStudio/CodeStudioPipelinesMigrateCommandTest.php b/tests/phpunit/src/Commands/CodeStudio/CodeStudioPipelinesMigrateCommandTest.php index 1c5a0e5a1..1c03be2db 100644 --- a/tests/phpunit/src/Commands/CodeStudio/CodeStudioPipelinesMigrateCommandTest.php +++ b/tests/phpunit/src/Commands/CodeStudio/CodeStudioPipelinesMigrateCommandTest.php @@ -4,7 +4,6 @@ namespace Acquia\Cli\Tests\Commands\CodeStudio; -use Acquia\Cli\Command\CodeStudio\CodeStudioCiCdVariables; use Acquia\Cli\Command\CodeStudio\CodeStudioPipelinesMigrateCommand; use Acquia\Cli\Command\CommandBase; use Acquia\Cli\Tests\Commands\Ide\IdeRequiredTestTrait; @@ -92,7 +91,51 @@ public function testCommand(mixed $mockedGitlabProjects, mixed $inputs, mixed $a $this->mockRequest('getAccount'); $this->mockGitLabPermissionsRequest($this::$applicationUuid); $projects = $this->mockGetGitLabProjects($this::$applicationUuid, $this->gitLabProjectId, $mockedGitlabProjects); - $projects->variables($this->gitLabProjectId)->willReturn(CodeStudioCiCdVariables::getDefaults()); + $gitlabCicdVariables = [ + [ + 'key' => 'ACQUIA_APPLICATION_UUID', + 'masked' => TRUE, + 'protected' => FALSE, + 'value' => NULL, + 'variable_type' => 'env_var', + ], + [ + 'key' => 'ACQUIA_CLOUD_API_TOKEN_KEY', + 'masked' => TRUE, + 'protected' => FALSE, + 'value' => NULL, + 'variable_type' => 'env_var', + ], + [ + 'key' => 'ACQUIA_CLOUD_API_TOKEN_SECRET', + 'masked' => TRUE, + 'protected' => FALSE, + 'value' => NULL, + 'variable_type' => 'env_var', + ], + [ + 'key' => 'ACQUIA_GLAB_TOKEN_NAME', + 'masked' => TRUE, + 'protected' => FALSE, + 'value' => NULL, + 'variable_type' => 'env_var', + ], + [ + 'key' => 'ACQUIA_GLAB_TOKEN_SECRET', + 'masked' => TRUE, + 'protected' => FALSE, + 'value' => NULL, + 'variable_type' => 'env_var', + ], + [ + 'key' => 'PHP_VERSION', + 'masked' => FALSE, + 'protected' => FALSE, + 'value' => NULL, + 'variable_type' => 'env_var', + ], + ]; + $projects->variables($this->gitLabProjectId)->willReturn($gitlabCicdVariables); $projects->update($this->gitLabProjectId, Argument::type('array')); $gitlabClient->projects()->willReturn($projects); $localMachineHelper->getFilesystem()->willReturn(new Filesystem())->shouldBeCalled(); diff --git a/tests/phpunit/src/Commands/CodeStudio/CodeStudioWizardCommandTest.php b/tests/phpunit/src/Commands/CodeStudio/CodeStudioWizardCommandTest.php index 40d475eaa..ee709894a 100644 --- a/tests/phpunit/src/Commands/CodeStudio/CodeStudioWizardCommandTest.php +++ b/tests/phpunit/src/Commands/CodeStudio/CodeStudioWizardCommandTest.php @@ -95,6 +95,8 @@ public function providerTestCommand(): array { [ // 'Would you like to create a new Code Studio project? 'y', + // Select a project type Drupal_project + '0', // Select PHP version 8.1 '0', // Do you want to continue? @@ -115,6 +117,8 @@ public function providerTestCommand(): array { [ // 'Would you like to create a new Code Studio project? 'y', + // Select a project type Drupal_project + '0', // Select PHP version 8.2 '1', // Do you want to continue? @@ -128,6 +132,50 @@ public function providerTestCommand(): array { '--secret' => $this->secret, ], ], + [ + // No projects. + [], + // Inputs. + [ + // 'Would you like to create a new Code Studio project? + 'y', + // Select a project type Node_project + '1', + // Select NODE version 18.17.1 + '0', + // Do you want to continue? + 'y', + // Would you like to perform a one time push of code from Acquia Cloud to Code Studio now? (yes/no) [yes]: + 'y', + ], + // Args. + [ + '--key' => $this->key, + '--secret' => $this->secret, + ], + ], + [ + // No projects. + [], + // Inputs. + [ + // 'Would you like to create a new Code Studio project? + 'y', + // Select a project type Node_project + '1', + // Select NODE version 20.5.1 + '1', + // Do you want to continue? + 'y', + // Would you like to perform a one time push of code from Acquia Cloud to Code Studio now? (yes/no) [yes]: + 'y', + ], + // Args. + [ + '--key' => $this->key, + '--secret' => $this->secret, + ], + ], [ // No projects. [], @@ -157,6 +205,8 @@ public function providerTestCommand(): array { $this->key, // Enter Cloud secret, $this->secret, + // Select a project type Drupal_project + '0', // Select PHP version 8.1 '0', // Do you want to continue? @@ -176,6 +226,29 @@ public function providerTestCommand(): array { $this->key, // Enter Cloud secret, $this->secret, + // Select a project type Node_project + '1', + // Select NODE version 18.17.1 + '0', + // Do you want to continue? + 'y', + ], + // Args + [], + ], + [ + // No projects. + [], + // Inputs + [ + // 'Would you like to create a new Code Studio project? + 'y', + // Enter Cloud Key + $this->key, + // Enter Cloud secret, + $this->secret, + // Select a project type Drupal_project + '0', // Select PHP version 8.2 '1', // Do you want to continue? @@ -184,6 +257,27 @@ public function providerTestCommand(): array { // Args [], ], + [ + // No projects. + [], + // Inputs + [ + // 'Would you like to create a new Code Studio project? + 'y', + // Enter Cloud Key + $this->key, + // Enter Cloud secret, + $this->secret, + // Select a project type Node_project + '1', + // Select NODE version 20.5.1 + '1', + // Do you want to continue? + 'y', + ], + // Args + [], + ], ]; } @@ -256,9 +350,13 @@ public function testCommand(array $mockedGitlabProjects, array $inputs, array $a /** @var Filesystem|ObjectProphecy $fileSystem */ $fileSystem = $this->prophet->prophesize(Filesystem::class); - // Set properties and execute. $this->executeCommand($args, $inputs); + $output = $this->getDisplay(); + $output_strings = $this->getOutputStrings(); + foreach ($output_strings as $output_string) { + self::assertStringContainsString($output_string, $output); + } // Assertions. @@ -417,9 +515,15 @@ protected function mockGitLabNamespaces(ObjectProphecy $gitlabClient): void { } protected function mockGitLabVariables(int $gitlabProjectId, ObjectProphecy $projects): void { - $projects->variables($gitlabProjectId)->willReturn($this->getMockGitLabVariables()); - $projects->addVariable($gitlabProjectId, Argument::type('string'), Argument::type('string'), Argument::type('bool'), NULL, Argument::type('array'))->shouldBeCalled(); - $projects->updateVariable($this->gitLabProjectId, Argument::type('string'), Argument::type('string'), FALSE, NULL, ["masked" => TRUE, "variable_type" => "env_var"])->shouldBeCalled(); + $variables = $this->getMockGitLabVariables(); + $projects->variables($gitlabProjectId)->willReturn($variables); + foreach ($variables as $variable) { + $projects->addVariable($this->gitLabProjectId, Argument::type('string'), Argument::type('string'), FALSE, NULL, ['masked' => $variable['masked'], 'variable_type' => $variable['variable_type']])->shouldBeCalled(); + } + // $projects->addVariable($gitlabProjectId, Argument::type('string'), Argument::type('string'), Argument::type('bool'), NULL, Argument::type('array'))->shouldBeCalled(); + foreach ($variables as $variable) { + $projects->updateVariable($this->gitLabProjectId, $variable['key'], $variable['value'], FALSE, NULL, ['masked' => TRUE, 'variable_type' => 'env_var'])->shouldBeCalled(); + } } } diff --git a/tests/phpunit/src/Commands/WizardTestBase.php b/tests/phpunit/src/Commands/WizardTestBase.php index a4d2daefb..e12109de3 100644 --- a/tests/phpunit/src/Commands/WizardTestBase.php +++ b/tests/phpunit/src/Commands/WizardTestBase.php @@ -153,4 +153,14 @@ protected function runTestSshKeyAlreadyUploaded(): void { $this->executeCommand(); } + /** + * @return string[] + * An array of strings to inspect the output for. + */ + protected function getOutputStrings(): array { + return [ + "Setting GitLab CI/CD variables for", + ]; + } + }