Пример #1
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $output->writeln('Hello Terra!');
     // Ask for an app and environment.
     $this->getApp($input, $output);
     $this->getEnvironment($input, $output);
     $environment_factory = new EnvironmentFactory($this->environment, $this->app);
     $environment_factory->getConfig();
     // Run the tests
     // @TODO: Move to factory.
     $output->writeln('<info>TERRA</info> | <comment>Test: Start...</comment>');
     $output->writeln('<info>TERRA</info> | ' . $environment_factory->config['hooks']['test']);
     // Set environment variables for behat tests
     $env = array();
     $env['HOME'] = $_SERVER['HOME'];
     $behat_vars = array('extensions' => array('Behat\\MinkExtension' => array('base_url' => 'http://' . $environment_factory->getUrl())));
     // @TODO: This is NOT WORKING.  We MUST figure out how to override the base_url.
     $env['BEHAT_PARAMS'] = json_encode($behat_vars);
     $process = new Process($environment_factory->config['hooks']['test'], $environment_factory->getSourcePath(), $env);
     $process->run(function ($type, $buffer) {
         if (Process::ERR === $type) {
             echo $buffer;
         } else {
             echo $buffer;
         }
     });
     if (!$process->isSuccessful()) {
         $output->writeln('<info>TERRA</info> | <fg=red>Test Failed</> ' . $hook);
     } else {
         $output->writeln('<info>TERRA</info> | <info>Test Passed: </info> ' . $hook);
     }
     $output->writeln('');
 }
Пример #2
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     // Ask for an app and environment.
     $this->getApp($input, $output);
     $this->getEnvironment($input, $output);
     $environment_name = $this->environment->name;
     $app_name = $this->app->name;
     // Confirm removal of the app.
     $helper = $this->getHelper('question');
     $question = new ConfirmationQuestion("Are you sure you would like to remove the environment <question>{$app_name}:{$environment_name}</question>?  All files at {$this->environment->path} will be deleted, and all containers will be killed. [y/N] ", false);
     if (!$helper->ask($input, $output, $question)) {
         $output->writeln('<error>Cancelled</error>');
         return;
     } else {
         // Remove the environment from config registry.
         // @TODO: Move this to EnvironmentFactory class
         // Remove files
         $fs = new Filesystem();
         try {
             $fs->remove(array($this->environment->path));
             $output->writeln("<info>Files for environment {$app_name}:{$environment_name} has been deleted.</info>");
         } catch (IOExceptionInterface $e) {
             $output->writeln('<error>Unable to remove ' . $e->getPath() . '</error>');
         }
         // Destroy the environment
         $environmentFactory = new EnvironmentFactory($this->environment, $this->app);
         $environmentFactory->destroy();
         unset($this->app->environments[$environment_name]);
         $this->getApplication()->getTerra()->getConfig()->add('apps', $app_name, (array) $this->app);
         $this->getApplication()->getTerra()->getConfig()->save();
         $output->writeln("<info>Environment {$app_name}:{$environment_name} has been removed.</info>");
     }
 }
Пример #3
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     // If there are no apps, return
     if (count($this->getApplication()->getTerra()->getConfig()->get('apps')) == 0) {
         $output->writeln("<comment>There are no apps to remove!</comment>");
         $output->writeln("Use the command <info>terra app:add</info> to add your first app.");
         return;
     }
     $helper = $this->getHelper('question');
     $app_name = $input->getArgument('app_name');
     $environment_name = $input->getArgument('environment_name');
     // If no name specified provide options
     if (empty($app_name)) {
         $question = new ChoiceQuestion('Which app? ', array_keys($this->getApplication()->getTerra()->getConfig()->get('apps')), NULL);
         $app_name = $helper->ask($input, $output, $question);
     }
     $app = $this->getApplication()->getTerra()->getConfig()->get('apps', $app_name);
     // If no environments:
     if (count($app['environments']) == 0) {
         $output->writeln("<comment>There are no environments for the app {$app_name}!</comment>");
         $output->writeln("Use the command <info>terra environment:add</info> to add your first environment.");
         return;
     }
     // If no environment name specified provide options
     if (empty($environment_name)) {
         $question = new ChoiceQuestion('Which environment? ', array_keys($app['environments']), NULL);
         $environment_name = $helper->ask($input, $output, $question);
     }
     $environment = $app['environments'][$environment_name];
     // Confirm removal of the app.
     $question = new ConfirmationQuestion("Are you sure you would like to remove the environment <question>{$app_name}:{$environment_name}</question>?  All files at {$environment['path']} will be deleted, and all containers will be killed.", false);
     if (!$helper->ask($input, $output, $question)) {
         $output->writeln('<error>Cancelled</error>');
         return;
     } else {
         // Remove the environment from config registry.
         // @TODO: Move this to EnvironmentFactory class
         // Remove files
         $fs = new Filesystem();
         try {
             $fs->remove(array($environment['path']));
             $output->writeln("<info>Files for environment {$app_name}:{$environment_name} has been deleted.</info>");
         } catch (IOExceptionInterface $e) {
             $output->writeln("<error>Unable to remove " . $e->getPath() . "</error>");
         }
         // Run docker-compose kill
         $environmentFactory = new EnvironmentFactory($environment, $app);
         // @TODO: Remove ~/.terra/environments/* folder.
         if ($environmentFactory->destroy()) {
             $output->writeln("<info>Killed the docker containers.</info>");
         }
         unset($app['environments'][$environment_name]);
         $this->getApplication()->getTerra()->getConfig()->add('apps', $app_name, $app);
         $this->getApplication()->getTerra()->getConfig()->save();
         $output->writeln("<info>Environment {$app_name}:{$environment_name} has been removed.</info>");
     }
 }
Пример #4
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     // App
     $helper = $this->getHelper('question');
     $app_name = $input->getArgument('app');
     if (empty($app_name)) {
         $question = new ChoiceQuestion('For which app? ', array_keys($this->getApplication()->getTerra()->getConfig()->get('apps')), 0);
         $app_name = $helper->ask($input, $output, $question);
     }
     $app = $this->getApplication()->getTerra()->getConfig()->get('apps', $app_name);
     // Environment Name
     $environment_name = $input->getArgument('name');
     if (empty($environment_name)) {
         $question = new Question('Environment Name: ', '');
         $environment_name = $helper->ask($input, $output, $question);
     }
     // Path
     $path = $input->getArgument('path');
     if (empty($path)) {
         $default_path = realpath('.') . '/' . $app_name . '/' . $environment_name;
         $question = new Question("Path: ({$default_path})", '');
         $path = $helper->ask($input, $output, $question);
         if (empty($path)) {
             $path = $default_path;
         }
     }
     // Check for path
     $fs = new Filesystem();
     if (!$fs->isAbsolutePath($path)) {
         $path = getcwd() . '/' . $path;
     }
     // Environment object
     $environment = array('name' => $environment_name, 'path' => $path, 'document_root' => '', 'url' => '', 'version' => '');
     // Prepare the environment factory.
     // Clone the apps source code to the desired path.
     $environmentFactory = new EnvironmentFactory($environment, $this->getApplication()->getTerra()->getConfig()->get('apps', $app_name));
     // Save environment to config.
     if ($environmentFactory->init($path)) {
         // Load config from file.
         $environmentFactory->getConfig();
         $environment['document_root'] = $environmentFactory->config['document_root'];
         // Save current branch
         $environment['version'] = $environmentFactory->getRepo()->getCurrentBranch();
         // Save to registry.
         $this->getApplication()->getTerra()->getConfig()->add('apps', array($app_name, 'environments', $environment_name), $environment);
         $this->getApplication()->getTerra()->getConfig()->save();
         $output->writeln('<info>Environment saved to registry.</info>');
     } else {
         $output->writeln('<error>Unable to clone repository. Check app settings and try again.</error>');
     }
 }
Пример #5
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $output->writeln('Hello Terra!');
     // If there are no apps, return
     if (count($this->getApplication()->getTerra()->getConfig()->get('apps')) == 0) {
         $output->writeln('<comment>There are no apps!</comment>');
         $output->writeln('Use the command <info>terra app:add</info> to add your first app.');
         return;
     }
     $helper = $this->getHelper('question');
     $app_name = $input->getArgument('app_name');
     $environment_name = $input->getArgument('environment_name');
     $scale = $input->getArgument('scale');
     // If no name specified provide options
     if (empty($app_name)) {
         $question = new ChoiceQuestion('Which app? ', array_keys($this->getApplication()->getTerra()->getConfig()->get('apps')), null);
         $app_name = $helper->ask($input, $output, $question);
     }
     $app = $this->getApplication()->getTerra()->getConfig()->get('apps', $app_name);
     if (empty($app)) {
         $output->writeln('<error>No app by that name!</error>');
         $output->writeln('Use the command <info>terra app:add</info> to add your first app.');
         return;
     }
     // If no environments:
     if (count($app['environments']) == 0) {
         $output->writeln('<comment>There are no environments!</comment>');
         $output->writeln('Use the command <info>terra environment:add</info> to add your first environment.');
         return;
     }
     // If no environment name specified provide options
     if (empty($environment_name)) {
         $question = new ChoiceQuestion('Which environment? ', array_keys($app['environments']), null);
         $environment_name = $helper->ask($input, $output, $question);
     }
     $app = $this->getApplication()->getTerra()->getConfig()->get('apps', $app_name);
     $environment = $app['environments'][$environment_name];
     $environment_factory = new EnvironmentFactory($environment, $app);
     $environment_factory->writeConfig();
     $current_scale = $environment_factory->getScale();
     $output->writeln("Scaling Environment <comment>{$app_name} {$environment_name}</comment>...");
     $output->writeln("Current scale: <comment>{$current_scale}</comment>");
     // If no scale ask for scale.
     if (empty($scale)) {
         $question = new Question('How many app containers? ');
         $scale = $helper->ask($input, $output, $question);
     }
     $output->writeln("Target scale: <comment>{$scale}</comment>");
     $environment_factory->scale($scale);
     $output->writeln("Environment <comment>{$app_name} {$environment_name}</comment> scaled to <info>{$scale}</info>");
 }
Пример #6
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     // Ask for an app and environment.
     $this->getApp($input, $output);
     $this->getEnvironment($input, $output);
     $environment_name = $this->environment->name;
     $app_name = $this->app->name;
     // Attempt to disable the environment.
     $environment_factory = new EnvironmentFactory($this->environment, $this->app);
     if (!$environment_factory->disable()) {
         $output->writeln('<error>Something went wrong, environment not disabled.</error>');
         return;
     }
 }
Пример #7
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     // Ask for an app and environment.
     $this->getApp($input, $output);
     $this->getEnvironment($input, $output);
     $environment_name = $this->environment->name;
     $app_name = $this->app->name;
     // Attempt to enable the environment.
     $environment_factory = new EnvironmentFactory($this->environment, $this->app);
     if (!$environment_factory->enable()) {
         $output->writeln('<error>Something went wrong, environment not enabled.</error>');
         return;
     }
     // Get new port, set new URL to environment object.
     $port = $environment_factory->getPort();
     $host = $environment_factory->getHost();
     $this->environment->url = "http://{$host}:{$port}";
     // When passing to saveEnvironment, it must have app and name properties (for now).
     $this->environment->app = $app_name;
     $this->environment->name = $environment_name;
     // Save environment metadata.
     $this->getApplication()->getTerra()->getConfig()->saveEnvironment($this->environment);
     if ($this->getApplication()->getTerra()->getConfig()->save()) {
         $output->writeln('<info>Environment enabled!</info>  Available at http://' . $environment_factory->getUrl() . ' and ' . $this->environment->url);
     } else {
         $output->writeln('<error>Environment info not saved.</error>');
     }
     // Write drush alias.
     $drush_alias_file_path = "{$_SERVER['HOME']}/.drush/{$app_name}.aliases.drushrc.php";
     if ($environment_factory->writeDrushAlias()) {
         $output->writeln("<info>Drush alias file created at {$drush_alias_file_path}</info>");
         $output->writeln("Wrote drush alias file to <comment>{$drush_alias_file_path}</comment>");
         $output->writeln("Use <info>drush @{$app_name}.{$environment_name}</info> to access the site.");
     } else {
         $output->writeln('<error>Unable to save drush alias.</error>');
     }
     // Run the enable hooks
     $output->writeln('');
     $output->writeln('Running <comment>ENABLE</comment> app hook...');
     $environment_factory->getConfig();
     // @TODO: Figure out how to only run this hook the first time!
     if (!empty($environment_factory->config['hooks']['enable_first'])) {
         // Output what we are running
         $formatter = $this->getHelper('formatter');
         $errorMessages = array($environment_factory->config['hooks']['enable_first']);
         $formattedBlock = $formatter->formatBlock($errorMessages, 'question');
         $output->writeln($formattedBlock);
         chdir($environment_factory->getSourcePath());
         $process = new Process($environment_factory->config['hooks']['enable_first']);
         $process->setTimeout(null);
         $process->run(function ($type, $buffer) {
             if (Process::ERR === $type) {
                 echo $buffer;
             } else {
                 echo $buffer;
             }
         });
     }
 }
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     // Check if "app" argument is an action.
     if ($input->getArgument('app_name') == 'add' || $input->getArgument('app_name') == 'remove') {
         // Move argument from app_name to action
         $input->setArgument('action', $input->getArgument('app_name'));
         $input->setArgument('app_name', '');
         // Move argument from env_name to domain
         $input->setArgument('domain', $input->getArgument('environment_name'));
         $input->setArgument('environment_name', '');
     }
     // Ask for an app.
     $helper = $this->getHelper('question');
     $this->getApp($input, $output);
     // Ask for an environment.
     $helper = $this->getHelper('question');
     $this->getEnvironment($input, $output);
     // If action argument is empty, show the list.
     if (empty($input->getArgument('action'))) {
         $environment = new EnvironmentFactory($this->environment, $this->app);
         $rows[] = array('http://' . $environment->getHost() . ':' . $environment->getPort());
         $rows[] = array('http://' . $environment->getUrl());
         // Get all domains
         foreach ($environment->environment->domains as $domain) {
             $rows[] = array('http://' . $domain);
         }
         $table = $this->getHelper('table');
         $table->setHeaders(array("Domains for {$this->app->name} {$this->environment->name}"))->setRows($rows);
         $table->render($output);
         return;
     } elseif ($input->getArgument('action') == 'add') {
         $this->executeAddDomain($input, $output);
     } elseif ($input->getArgument('action') == 'remove') {
         $this->executeRemoveDomain($input, $output);
     }
     // Offer to re-enable the environment
     $helper = $this->getHelper('question');
     $question = new ConfirmationQuestion("Re-enable the environment <info>{$this->app->name}:{$this->environment->name}</info> [y/N]? ", FALSE);
     if ($helper->ask($input, $output, $question)) {
         // Run environment:enable command.
         $command = $this->getApplication()->find('environment:enable');
         $arguments = array('app_name' => $this->app->name, 'environment_name' => $this->environment->name);
         $input = new ArrayInput($arguments);
         $command->run($input, $output);
     }
 }
Пример #9
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $output->writeln('Hello Terra!');
     // Ask for an app and environment.
     $this->getApp($input, $output);
     $this->getEnvironment($input, $output);
     $environment_name = $this->environment->name;
     $app_name = $this->app->name;
     $environment_factory = new EnvironmentFactory($this->environment, $this->app);
     $environment_factory->writeConfig();
     $current_scale = $environment_factory->getScale();
     $output->writeln("Scaling Environment <comment>{$app_name} {$environment_name}</comment>...");
     $output->writeln("Current scale: <comment>{$current_scale}</comment>");
     // If no scale ask for scale.
     if (empty($scale)) {
         $question = new Question('How many app containers? ');
         $helper = $this->getHelper('question');
         $scale = $helper->ask($input, $output, $question);
     }
     $output->writeln("Target scale: <comment>{$scale}</comment>");
     $environment_factory->scale($scale);
     $output->writeln("Environment <comment>{$app_name} {$environment_name}</comment> scaled to <info>{$scale}</info>");
     // Output the new URL.
     $local_url = 'http://' . $environment_factory->getHost() . ':' . $environment_factory->getPort();
     $output->writeln('<info>Environment enabled!</info>  Available at http://' . $environment_factory->getUrl() . ' and ' . $local_url);
 }
Пример #10
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     // If there are no apps, return
     if (count($this->getApplication()->getTerra()->getConfig()->get('apps')) == 0) {
         $output->writeln("<comment>There are no apps to remove!</comment>");
         $output->writeln("Use the command <info>terra app:add</info> to add your first app.");
         return;
     }
     $helper = $this->getHelper('question');
     $app_name = $input->getArgument('app_name');
     $environment_name = $input->getArgument('environment_name');
     // If no name specified provide options
     if (empty($app_name)) {
         $question = new ChoiceQuestion('Which app? ', array_keys($this->getApplication()->getTerra()->getConfig()->get('apps')), NULL);
         $app_name = $helper->ask($input, $output, $question);
     }
     $app = $this->getApplication()->getTerra()->getConfig()->get('apps', $app_name);
     // If no environments:
     if (count($app['environments']) == 0) {
         $output->writeln("<comment>There are no environments for the app {$app_name}!</comment>");
         $output->writeln("Use the command <info>terra environment:add</info> to add your first environment.");
         return;
     }
     // If no environment name specified provide options
     if (empty($environment_name)) {
         $question = new ChoiceQuestion('Which environment? ', array_keys($app['environments']), NULL);
         $environment_name = $helper->ask($input, $output, $question);
     }
     $environment = $app['environments'][$environment_name];
     $environment_factory = new EnvironmentFactory($environment, $app);
     $output->writeln($environment_factory->enable());
     $port = $environment_factory->getPort();
     $port = array_pop(explode(':', $port));
     $app['environments'][$environment_name]['url'] = "http://localhost:{$port}";
     $this->getApplication()->getTerra()->getConfig()->add('apps', $app_name, $app);
     if ($this->getApplication()->getTerra()->getConfig()->save()) {
         $output->writeln('<info>Environment enabled!</info>  Available at http://' . $environment_factory->getUrl());
     } else {
         $output->writeln('<error>Environment info not saved.</error>');
     }
 }
Пример #11
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $output->writeln("Hello Terra!");
     // If there are no apps, return
     if (count($this->getApplication()->getTerra()->getConfig()->get('apps')) == 0) {
         $output->writeln("<comment>There are no apps!</comment>");
         $output->writeln("Use the command <info>terra app:add</info> to add your first app.");
         return;
     }
     $helper = $this->getHelper('question');
     $app_name = $input->getArgument('app_name');
     $environment_name = $input->getArgument('environment_name');
     // If no name specified provide options
     if (empty($app_name)) {
         $question = new ChoiceQuestion('Which app? ', array_keys($this->getApplication()->getTerra()->getConfig()->get('apps')), NULL);
         $app_name = $helper->ask($input, $output, $question);
     }
     $app = $this->getApplication()->getTerra()->getConfig()->get('apps', $app_name);
     // If no environments:
     if (count($app['environments']) == 0) {
         $output->writeln("<comment>There are no environments!</comment>");
         $output->writeln("Use the command <info>terra environment:add</info> to add your first environment.");
         return;
     }
     // If no environment name specified provide options
     if (empty($environment_name)) {
         $question = new ChoiceQuestion('Which environment? ', array_keys($app['environments']), NULL);
         $environment_name = $helper->ask($input, $output, $question);
     }
     $environment = $app['environments'][$environment_name];
     $environment_factory = new EnvironmentFactory($environment, $app);
     $environment['scale'] = $environment_factory->getScale();
     $environment['url'] .= PHP_EOL . 'http://' . $environment_factory->getUrl();
     $table = $this->getHelper('table');
     $table->setHeaders(array('Name', 'Code Path', 'URL', 'Version', 'Scale'));
     $rows = array($environment);
     $table->setRows($rows);
     $table->render($output);
     $output->writeln("Docker Compose Path: " . $environment_factory->getDockerComposePath());
 }
Пример #12
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     // Ask for an app and environment.
     $this->getApp($input, $output);
     $this->getEnvironment($input, $output);
     // Get desired version.
     $question = new Question('What version would you like to deploy? This can be any git ref. (branch, tag, or sha) ', '');
     $git_ref = $this->getAnswer($input, $output, $question, 'git_ref');
     // Notify user.
     $output->writeln("Deploying App <info>{$this->app->name}</info> environment <comment>{$this->environment->name}</comment> to version <question> {$git_ref} </question> ...");
     // Ask for confirmation.
     $helper = $this->getHelper('question');
     $question = new ConfirmationQuestion("Are you sure? This will checkout the version and run the deploy hooks in .terra.yml [y\\N] ", false);
     if (!$helper->ask($input, $output, $question)) {
         $output->writeln('<error>Deploy Cancelled</error>');
         return;
     }
     // Run the deployment.
     $environment = new EnvironmentFactory($this->environment, $this->app);
     $this->environment->version = $environment->deploy($git_ref);
     // Save the new version to the config.
     $this->getApplication()->getTerra()->getConfig()->add('apps', array($this->app->name, 'environments', $this->environment->name), (array) $this->environment);
     $this->getApplication()->getTerra()->getConfig()->save();
 }
Пример #13
0
 protected function prepareBehat(InputInterface $input, OutputInterface $output, EnvironmentFactory $environment_factory)
 {
     $output->writeln("I noticed you don't have behat tests for your project.");
     $helper = $this->getHelper('question');
     $question = new ConfirmationQuestion('Would you like to add behat tests? [y\\N] ');
     if ($helper->ask($input, $output, $question)) {
         $question = new Question('Where would you like to add your tests? (tests) ', 'tests');
         $tests_path = $helper->ask($input, $output, $question);
         // Create tests path
         $fs = new Filesystem();
         try {
             $fs->mkdir($environment_factory->getSourcePath() . '/' . $tests_path);
         } catch (IOException $e) {
             throw \Exception($e->getMessage());
         }
         $output->writeln("<info>SUCCESS</info> Created {$tests_path}.");
         // Create composer.json and behat.yml
         $composer_path = $environment_factory->getSourcePath() . '/' . $tests_path . '/composer.json';
         $behat_yml_path = $environment_factory->getSourcePath() . '/' . $tests_path . '/behat.yml';
         try {
             $fs->dumpFile($composer_path, $this->getBehatDrupalComposer());
             $url = "http://{$environment_factory->getHost()}:{$environment_factory->getPort()}";
             $fs->dumpFile($behat_yml_path, $this->getBehatYml($url));
             $output->writeln("<info>SUCCESS</info> Created composer.json and behat.yml.");
         } catch (IOException $e) {
             throw \Exception($e->getMessage());
         }
         $behat_path = $this->environment->path . '/' . $tests_path;
         // Run composer install
         $output->writeln("<info>RUNNING</info> composer install");
         $output->writeln("in: {$behat_path}");
         $process = new Process('composer install', $behat_path);
         $process->setTimeout(NULL);
         $process->run(function ($type, $buffer) {
             if (Process::ERR === $type) {
                 echo $buffer;
             } else {
                 echo $buffer;
             }
         });
         $output->writeln("");
         // Run behat --init
         $output->writeln("<info>RUNNING</info> bin/behat --init");
         $output->writeln("in: {$behat_path}");
         $process = new Process('bin/behat --init', $behat_path);
         $process->run(function ($type, $buffer) {
             if (Process::ERR === $type) {
                 echo $buffer;
             } else {
                 echo $buffer;
             }
         });
         // Set behat_path in .terra.yml
         $output->writeln("<comment>NOTE You should add `behat_path: {$tests_path}` to .terra.yml.</>");
     }
 }
Пример #14
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     // Ask for an app.
     $helper = $this->getHelper('question');
     $this->getApp($input, $output);
     // Ask for environment name
     $environment_name = $input->getArgument('environment_name');
     while (empty($environment_name) || isset($this->app->environments[$environment_name]) || !preg_match('/^[a-zA-Z0-9]+$/', $environment_name)) {
         $question = new Question('Environment name? ');
         $environment_name = $helper->ask($input, $output, $question);
         if (!preg_match('/^[a-zA-Z0-9]+$/', $environment_name)) {
             $output->writeln("<error> ERROR </error> Environment <comment>{$environment_name}</comment> cannot contain spaces or special characters.");
         }
         // Look for environment with this name
         if (isset($this->app->environments[$environment_name])) {
             $output->writeln("<error> ERROR </error> Environment <comment>{$environment_name}</comment> already exists in app <comment>{$this->app->name}</comment>");
         }
     }
     // Path
     $path = $input->getArgument('path');
     if (empty($path)) {
         // Load apps base path from Config.
         $config_path = $this->getApplication()->getTerra()->getConfig()->get('apps_basepath');
         // If it already exists, use "realpath" to load it.
         if (file_exists($config_path)) {
             $default_path = realpath($config_path) . '/' . $this->app->name . '/' . $environment_name;
         } else {
             // Offer to create the apps path.
             $question = new ConfirmationQuestion("Create default apps path at {$config_path}? [y\\N] ", false);
             if ($helper->ask($input, $output, $question)) {
                 mkdir($config_path);
                 $default_path = $_SERVER['HOME'] . '/Apps/' . $this->app->name . '/' . $environment_name;
             }
         }
         $question = new Question("Path: ({$default_path}) ", $default_path);
         $path = $helper->ask($input, $output, $question);
         if (empty($path)) {
             $path = $default_path;
         }
     }
     // Check for path
     $fs = new Filesystem();
     if (!$fs->isAbsolutePath($path)) {
         $path = getcwd() . '/' . $path;
     }
     $branch_name = $input->getArgument('branch');
     while (empty($branch_name)) {
         $output->writeln("<info>Getting the default branch for <comment>{$this->app->repo}</comment> </info>");
         // command to get default branch
         $process = new Process("git ls-remote " . $this->app->repo . " | awk '{if (a[\$1]) { print \$2 } a[\$1] = \$2}' | grep heads | awk -F\"/\" '{print \$3 }'");
         try {
             $process->mustRun();
         } catch (ProcessFailedException $e) {
             $output->writeln("<error> ERROR </error> Unable to find default git branch. <comment>{$e->getMessage()}</comment>");
         }
         $default_branch = trim($process->getOutput());
         $question = new Question("Version? [{$default_branch}]", $default_branch);
         $branch_name = $helper->ask($input, $output, $question);
         // Check if the remote branch exists
         if ($branch_name) {
             $output->writeln("<info>Checking if branch <comment>{$branch_name}</comment> exists in <comment>{$this->app->repo}</comment> </info>");
             $process = new Process('git ls-remote ' . $this->app->repo . ' | grep -sw "' . $branch_name . '"');
             $process->run();
             if (!$process->isSuccessful()) {
                 $output->writeln("<error> ERROR </error> Branch <comment>{$branch_name}</comment> not found in repote repo <comment>{$this->app->repo}</comment>");
                 return;
             }
         }
     }
     // Environment object
     $environment = array('app' => $this->app->name, 'name' => $environment_name, 'path' => $path, 'document_root' => '', 'url' => '', 'version' => $branch_name);
     // Prepare the environment factory.
     // Clone the apps source code to the desired path.
     $environmentFactory = new EnvironmentFactory($environment, $this->app);
     // Save environment to config.
     if ($environmentFactory->init($path)) {
         // Load config from file.
         $environmentFactory->getConfig();
         $environment['document_root'] = isset($environmentFactory->config['document_root']) ? $environmentFactory->config['document_root'] : '';
         // Save current branch
         $environment['version'] = $environmentFactory->getRepo()->getCurrentBranch();
         // Save to registry.
         $this->getApplication()->getTerra()->getConfig()->saveEnvironment($environment);
         $this->getApplication()->getTerra()->getConfig()->save();
         $output->writeln('<info>Environment saved to registry.</info>');
     } else {
         $output->writeln('<error>Unable to clone repository. Check app settings and try again.</error>');
         return;
     }
     // Offer to enable the environment
     $question = new ConfirmationQuestion("Enable this environment? [y\\N] ", false);
     if ($input->getOption('enable') || $helper->ask($input, $output, $question)) {
         // Run environment:add command.
         $command = $this->getApplication()->find('environment:enable');
         $arguments = array('app_name' => $this->app->name, 'environment_name' => $environment_name);
         $input = new ArrayInput($arguments);
         $command->run($input, $output);
     }
 }
Пример #15
0
 protected function prepareBehat(InputInterface $input, OutputInterface $output, EnvironmentFactory $environment_factory)
 {
     $output->writeln("I noticed you don't have behat tests for your project.");
     $helper = $this->getHelper('question');
     $question = new ConfirmationQuestion('Would you like to add behat tests? [y\\N] ');
     if ($helper->ask($input, $output, $question)) {
         $question = new Question('Where would you like to add your tests? (tests) ', 'tests');
         $tests_path = $helper->ask($input, $output, $question);
         // Create tests path
         $tests_path = $environment_factory->getSourcePath() . '/' . $tests_path;
         $fs = new Filesystem();
         try {
             $fs->mkdir($environment_factory->getSourcePath() . '/' . $tests_path);
         } catch (IOException $e) {
             throw \Exception($e->getMessage());
         }
         $output->writeln("<info>SUCCESS</info> Created {$tests_path}.");
         // Create composer.json and behat.yml
         $composer_path = $environment_factory->getSourcePath() . '/' . $tests_path . '/composer.json';
         $behat_yml_path = $environment_factory->getSourcePath() . '/' . $tests_path . '/behat.yml';
         try {
             $fs->dumpFile($composer_path, $this->getBehatDrupalComposer());
             $fs->dumpFile($behat_yml_path, $this->getBehatYml($environment_factory->getUrl()));
             $output->writeln("<info>SUCCESS</info> Created composer.json and behat.yml.");
         } catch (IOException $e) {
             throw \Exception($e->getMessage());
         }
         // Run composer install
         $process = new Process('composer install', $tests_path);
         // Run behat --init
         // Set behat_path in .terra.yml
     }
 }
Пример #16
0
 /**
  * Outputs the status of an environment.
  *
  * @param \Symfony\Component\Console\Input\InputInterface   $input
  * @param \Symfony\Component\Console\Output\OutputInterface $output
  * @param $app
  * @param $environment
  *
  */
 protected function environmentStatus(InputInterface $input, OutputInterface $output)
 {
     // If there are no apps, return
     if (count($this->getApplication()->getTerra()->getConfig()->get('apps')) == 0) {
         $output->writeln('<comment>There are no apps!</comment>');
         $output->writeln('Use the command <info>terra app:add</info> to add your first app.');
         return;
     }
     $app_name = $input->getArgument('app_name');
     $environment_name = $input->getArgument('environment_name');
     $app = $this->getApplication()->getTerra()->getConfig()->get('apps', $app_name);
     // If no environments:
     if (count($app['environments']) == 0) {
         $output->writeln('<comment>There are no environments!</comment>');
         $output->writeln('Use the command <info>terra environment:add</info> to add your first environment.');
         return;
     }
     // If no environment by that name...
     if (!isset($app['environments'][$environment_name])) {
         $output->writeln("<error>There is no environment named {$environment_name} in the app {$app_name}</error>");
         return;
     }
     $environment = $app['environments'][$environment_name];
     $environment_factory = new EnvironmentFactory($environment, $app);
     $environment['scale'] = $environment_factory->getScale();
     $environment['url'] = 'http://' . $environment_factory->getHost() . ':' . $environment_factory->getPort();
     $environment['url'] .= PHP_EOL . 'http://' . $environment_factory->getUrl();
     $table = $this->getHelper('table');
     $table->setHeaders(array('Name', 'Code Path', 'docroot', 'URLs', 'Version', 'Scale'));
     $rows = array($environment);
     $table->setRows($rows);
     $table->render($output);
     $output->writeln('Docker Compose Path: ' . $environment_factory->getDockerComposePath());
 }
Пример #17
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     // Ask for an app.
     $helper = $this->getHelper('question');
     $this->getApp($input, $output);
     // Ask for environment name
     $environment_name = $input->getArgument('environment_name');
     while (empty($environment_name) || isset($this->app->environments[$environment_name])) {
         $question = new Question('Environment name? ');
         $environment_name = $helper->ask($input, $output, $question);
         // Check for spaces or characters.
         if (!preg_match('/^[a-zA-Z0-9]+$/', $environment_name)) {
             $output->writeln("<error> ERROR </error> Environment name cannot contain spaces or special characters.");
             $environment_name = '';
             continue;
         }
         // Look for environment with this name.
         if (isset($this->app->environments[$environment_name])) {
             $output->writeln("<error> ERROR </error> Environment <comment>{$environment_name}</comment> already exists in app <comment>{$this->app->name}</comment>");
         }
     }
     // Path
     $path = $input->getArgument('path');
     if (empty($path)) {
         // Load apps base path from Config.
         $config_path = $this->getApplication()->getTerra()->getConfig()->get('apps_basepath');
         // If it already exists, use "realpath" to load it.
         if (file_exists($config_path)) {
             $default_path = realpath($config_path) . '/' . $this->app->name . '/' . $environment_name;
         } else {
             // Offer to create the apps path.
             $question = new ConfirmationQuestion("Create default apps path at {$config_path}? [y\\N] ", false);
             if ($helper->ask($input, $output, $question)) {
                 mkdir($config_path);
                 $default_path = $_SERVER['HOME'] . '/Apps/' . $this->app->name . '/' . $environment_name;
             }
         }
         $question = new Question("Path: ({$default_path}) ", $default_path);
         $path = $helper->ask($input, $output, $question);
     }
     // Check for path
     $fs = new Filesystem();
     if (!$fs->isAbsolutePath($path)) {
         // Don't save the "." to the environments path.
         if ($path == '.') {
             $path = getcwd();
         } else {
             $path = getcwd() . '/' . $path;
         }
     }
     // Environment object
     $environment = array('app' => $this->app->name, 'name' => $environment_name, 'path' => $path, 'document_root' => '', 'url' => '', 'version' => $input->getOption('ref'), 'domains' => array());
     // Prepare the environment factory.
     // Clone the apps source code to the desired path.
     $environmentFactory = new EnvironmentFactory($environment, $this->app);
     // Save environment to config.
     if ($environmentFactory->init($path)) {
         // Load config from file.
         $environmentFactory->getConfig();
         $environment['document_root'] = isset($environmentFactory->config['document_root']) ? $environmentFactory->config['document_root'] : '';
         // Save current branch
         $environment['version'] = $environmentFactory->getRepo()->getCurrentBranch();
         // Save to registry.
         $this->getApplication()->getTerra()->getConfig()->saveEnvironment($environment);
         $this->getApplication()->getTerra()->getConfig()->save();
         $output->writeln('<info>Environment saved to registry.</info>');
     } else {
         $output->writeln('<error>Unable to clone repository. Check app settings and try again.</error>');
         return;
     }
     // Offer to enable the environment
     $question = new ConfirmationQuestion("Enable this environment? [y\\N] ", false);
     if ($input->getOption('enable') || $helper->ask($input, $output, $question)) {
         // Run environment:add command.
         $command = $this->getApplication()->find('environment:enable');
         $arguments = array('app_name' => $this->app->name, 'environment_name' => $environment_name);
         $input = new ArrayInput($arguments);
         $command->run($input, $output);
     }
 }
Пример #18
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     // If there are no apps, return
     if (count($this->getApplication()->getTerra()->getConfig()->get('apps')) == 0) {
         $output->writeln('<comment>There are no apps to remove!</comment>');
         $output->writeln('Use the command <info>terra app:add</info> to add your first app.');
         return;
     }
     $helper = $this->getHelper('question');
     $app_name = $input->getArgument('app_name');
     $environment_name = $input->getArgument('environment_name');
     // If no name specified provide options
     if (empty($app_name)) {
         $question = new ChoiceQuestion('Which app? ', array_keys($this->getApplication()->getTerra()->getConfig()->get('apps')), null);
         $app_name = $helper->ask($input, $output, $question);
     }
     $app = $this->getApplication()->getTerra()->getConfig()->get('apps', $app_name);
     // If no environments:
     if (count($app['environments']) == 0) {
         $output->writeln("<comment>There are no environments for the app {$app_name}!</comment>");
         $output->writeln('Use the command <info>terra environment:add</info> to add your first environment.');
         return;
     }
     // If no environment name specified provide options
     if (empty($environment_name)) {
         $question = new ChoiceQuestion('Which environment? ', array_keys($app['environments']), null);
         $environment_name = $helper->ask($input, $output, $question);
     }
     $environment = $app['environments'][$environment_name];
     // Attempt to enable the environment.
     $environment_factory = new EnvironmentFactory($environment, $app);
     if (!$environment_factory->enable()) {
         $output->writeln('<error>Something went wrong, environment not enabled.</error>');
         return;
     }
     // Get new port, set new URL to environment object.
     $port = $environment_factory->getPort();
     $host = $environment_factory->getHost();
     $app['environments'][$environment_name]['url'] = "http://{$host}:{$port}";
     // Save environment metadata.
     $this->getApplication()->getTerra()->getConfig()->add('apps', array($app_name, 'environments', $environment_name), $app['environments'][$environment_name]);
     // Save config to files.
     if ($this->getApplication()->getTerra()->getConfig()->save()) {
         $output->writeln('<info>Environment enabled!</info>  Available at http://' . $environment_factory->getUrl() . ' and ' . $app['environments'][$environment_name]['url']);
     } else {
         $output->writeln('<error>Environment info not saved.</error>');
     }
     // Write drush alias.
     $drush_alias_file_path = "{$_SERVER['HOME']}/.drush/{$app_name}.aliases.drushrc.php";
     if ($environment_factory->writeDrushAlias()) {
         $output->writeln("<info>Drush alias file created at {$drush_alias_file_path}</info>");
         $output->writeln("Wrote drush alias file to <comment>{$drush_alias_file_path}</comment>");
         $output->writeln("Use <info>drush @{$app_name}.{$environment_name}</info> to access the site.");
     } else {
         $output->writeln('<error>Unable to save drush alias.</error>');
     }
     // Run the enable hooks
     $output->writeln('');
     $output->writeln('Running <comment>ENABLE</comment> app hook...');
     $environment_factory->getConfig();
     if (!empty($environment_factory->config['hooks']['enable'])) {
         // Output what we are running
         $formatter = $this->getHelper('formatter');
         $errorMessages = array($environment_factory->config['hooks']['enable']);
         $formattedBlock = $formatter->formatBlock($errorMessages, 'question');
         $output->writeln($formattedBlock);
         chdir($environment_factory->getSourcePath());
         $process = new Process($environment_factory->config['hooks']['enable']);
         $process->run(function ($type, $buffer) {
             if (Process::ERR === $type) {
                 echo $buffer;
             } else {
                 echo $buffer;
             }
         });
     }
 }
Пример #19
0
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     // Ask for an app and environment.
     $this->getApp($input, $output);
     $this->getEnvironment($input, $output);
     // Don't continue unless we have an environment.
     if (empty($this->environment)) {
         return;
     }
     // Get Environment and Config
     $environment_factory = new EnvironmentFactory($this->environment, $this->app);
     $environment_factory->getConfig();
     // Get argument override
     $rebuild_source_argument = $input->getOption('source');
     // Check for config
     if (empty($environment_factory->config['rebuild_source'])) {
         if (empty($rebuild_source_argument)) {
             throw new \Exception("To run the 'environment:rebuild' command you must have 'rebuild_source: @drushalias' in your app's .terra.yml file (or specify the source drush alias with 'environment:rebuild --rebuild_source=@alias').");
         }
     } else {
         $rebuild_source_config = $environment_factory->config['rebuild_source'];
         $output->writeln("Found <comment>rebuild_source: {$rebuild_source_config}</comment> in <fg=cyan>.terra.yml</> file...");
     }
     // Get source and target aliases
     $source_alias = $rebuild_source_argument ? $rebuild_source_argument : $environment_factory->config['rebuild_source'];
     $target_alias = $environment_factory->getDrushAlias();
     // Mention to user where the alias is coming from.
     if ($rebuild_source_argument) {
         $output->writeln("Using terra command option for source alias: <fg=cyan>{$rebuild_source_argument}</>");
     }
     // Check that source doesn't equal target
     if ($source_alias == $target_alias) {
         throw new \Exception("You cannot use the same source and target (Source: {$source_alias} Target:{$target_alias}). Please check your config and try again.");
     }
     // Check ssh & sql access to both.
     $output->writeln('');
     $errors = FALSE;
     foreach (array($source_alias, $target_alias) as $alias) {
         $output->writeln("Checking access to alias <fg=cyan>{$alias}</> ...");
         $cmd = "drush {$alias} ssh 'echo \$SSH_CLIENT'";
         // SSH Check
         $process = new Process($cmd);
         $process->setTimeout(NULL);
         $process->run();
         if ($process->isSuccessful()) {
             $output->writeln("<info>SUCCESS</info> Connected to {$alias} via SSH. <comment>{$cmd}</comment>");
         } else {
             $output->writeln("<error>FAILURE</error> Unable to connect to {$alias} via SSH. <comment>{$cmd}</comment>");
             $errors = TRUE;
         }
         // SQL
         $cmd = "drush {$alias} sql-query 'SHOW TABLES'";
         $process = new Process($cmd);
         $process->setTimeout(NULL);
         $process->run();
         if ($process->isSuccessful()) {
             $output->writeln("<info>SUCCESS</info> Connected to {$alias} via MySQL. <comment>{$cmd}</comment>");
         } else {
             $output->writeln("<error>FAILURE</error> Unable to connect to {$alias} via MySQL. <comment>{$cmd}</comment>");
             $errors = TRUE;
         }
         $output->writeln('');
     }
     // If errors, don't continue
     if ($errors) {
         throw new \Exception('We were unable to connect to both of your environments. Please check your config & try again.');
     }
     // Database Sync Confirmation
     $helper = $this->getHelper('question');
     $question = new ConfirmationQuestion("Are you sure you want to destroy <fg=red>{$target_alias}</> and replace it with data from <fg=cyan>{$source_alias}</>? [y\\N] ", false);
     if (!$helper->ask($input, $output, $question)) {
         $output->writeln('<error>Database sync Cancelled</error>');
     } else {
         // Database Sync
         $cmd = "drush {$source_alias} sql-dump --gzip | gzip -cd | drush {$target_alias} sqlc";
         $output->writeln('');
         $output->writeln('Running...');
         $output->writeln("<comment>{$cmd}</comment>");
         $process = new Process($cmd);
         $process->setTimeout(NULL);
         $process->run();
         if ($process->isSuccessful()) {
             $output->writeln("<info>SUCCESS</info> Database Copied successfully!");
         } else {
             $output->writeln("<error>FAILURE</error> Database Copy Failed!");
         }
     }
     // Files Sync Confirmation
     $helper = $this->getHelper('question');
     $question = new ConfirmationQuestion("Copy files from <fg=cyan>{$source_alias}</> to <fg=red>{$target_alias}</>? Any existing files will be overwritten [y\\N] ", false);
     if (!$helper->ask($input, $output, $question)) {
         $output->writeln('<error>Files sync cancelled</error>');
         return;
     }
     // Files Sync
     // Get Source Path
     $source_files_path = $environment_factory->runDrushCommand('vget file_public_path --format=string', $source_alias);
     $target_files_path = $environment_factory->runDrushCommand('vget file_public_path --format=string');
     // If either variable is blank, assume default
     if (strpos($source_files_path, 'No matching') === 0) {
         $source_files_path = 'sites/default/files';
     }
     if (strpos($target_files_path, 'No matching') === 0) {
         $target_files_path = 'sites/default/files';
     }
     $default_source = "{$source_alias}:{$source_files_path}/";
     $default_target = $environment_factory->getSourcePath() . '/' . $environment_factory->config['document_root'] . '/' . $target_files_path . '/';
     $source_question = new Question("Source path? [{$default_source}] ", $default_source);
     $destination_question = new Question("Destination path? [{$default_target}] ", $default_target);
     $source = $helper->ask($input, $output, $source_question);
     $target = $helper->ask($input, $output, $destination_question);
     $cmd = "drush -y rsync {$source} {$target}";
     $output->writeln('');
     $output->writeln('Running...');
     $output->writeln("<comment>{$cmd}</comment>");
     $process = new Process($cmd);
     $process->setTimeout(NULL);
     $process->run();
     if ($process->isSuccessful()) {
         $output->writeln("<info>SUCCESS</info> Files copied successfully!");
     } else {
         $output->writeln("<error>FAILURE</error> Files did not copy successfully!");
     }
     // Rebuild Hooks
     if (isset($environment_factory->config['hooks']['rebuild'])) {
         $output->writeln('');
         $output->writeln('Running <fg=cyan>rebuild</> hooks from .terra.yml...');
         $output->writeln("<comment>{$environment_factory->config['hooks']['rebuild']}</comment>");
         $process = new Process($environment_factory->config['hooks']['rebuild'], $environment_factory->getSourcePath());
         $process->setTimeout(NULL);
         $process->run(function ($type, $buffer) {
             if (Process::ERR === $type) {
                 echo $buffer;
             } else {
                 echo $buffer;
             }
         });
         if ($process->isSuccessful()) {
             $output->writeln("<info>SUCCESS</info> Rebuild hooks completed successfully.");
         } else {
             $output->writeln("<error>FAILURE</error> Rebuild hooks did not complete successfully.");
         }
         $output->writeln('');
     }
 }
Пример #20
0
 /**
  * Using the config item "behat_path", run composer update and bin/behat in the behat path.
  *
  * @param InputInterface $input
  * @param OutputInterface $output
  */
 protected function executeBehatTests(InputInterface $input, OutputInterface $output)
 {
     $output->writeln('Running Behat Tests...');
     $environment_factory = new EnvironmentFactory($this->environment, $this->app);
     $environment_factory->getConfig();
     // 1. Look for behat.yml
     $behat_path = $this->environment->path . '/' . $environment_factory->config['behat_path'];
     $behat_yml_path = $behat_path . '/behat.yml';
     if (!file_exists($behat_path)) {
         throw new \Exception("Path {$behat_path} not found. Check your app's .terra.yml file.");
     } elseif (!file_exists($behat_yml_path)) {
         throw new \Exception("Behat.yml file not found at {$behat_yml_path}. Check your app's .terra.yml file.");
     }
     $output->writeln('Found behat.yml file at ' . $behat_yml_path);
     // 2. Load it, replace necessary items, and clone it to a temporary file.
     $behat_yml = Yaml::parse(file_get_contents($behat_yml_path));
     // Set Base URL
     $behat_yml['default']['extensions']['Behat\\MinkExtension']['base_url'] = 'http://' . $environment_factory->getUrl();
     $behat_yml['default']['extensions']['Drupal\\DrupalExtension']['drush']['alias'] = $environment_factory->getDrushAlias();
     // If driver is drupal, add root.
     if ($behat_yml['default']['extensions']['Drupal\\DrupalExtension']['api_driver'] == 'drupal') {
         $behat_yml['default']['extensions']['Drupal\\DrupalExtension']['drupal']['root'] = $environment_factory->getDocumentRoot();
     }
     $behat_yml_new = Yaml::dump($behat_yml, 5, 2);
     $behat_path_new = 'behat.terra.yml';
     $fs = new Filesystem();
     $fs->dumpFile($behat_path_new, $behat_yml_new);
     $output->writeln('Generated new behat.yml file at ' . $behat_path_new);
     // 3. Run `composer install` in behat_path.
     $output->writeln('');
     $output->writeln('<fg=cyan>TERRA</> | <comment>Running: composer install</comment>');
     $process = new Process('composer install', $behat_path);
     $process->setTimeout(NULL);
     $process->run(function ($type, $buffer) {
         if (Process::ERR === $type) {
             echo $buffer;
         } else {
             echo $buffer;
         }
     });
     $output->writeln('');
     $output->writeln('<fg=cyan>TERRA</> | <comment>Behat Tests: Start</comment>');
     // 4. Run `bin/behat --colors --config=$PATH` in behat_path.
     // "expand:true" expands scenario outlines, making them readable.
     $cmd = 'bin/behat --colors --format-settings=\'{"expand": true}\' --config=' . $behat_path_new;
     if ($input->getOption('name')) {
         $cmd .= ' --name=' . $input->getOption('name');
     }
     $output->writeln("Running: {$cmd}");
     $output->writeln("in: {$behat_path}");
     $output->writeln('');
     $process = new Process($cmd, $behat_path);
     $process->setTimeout(NULL);
     $process->run(function ($type, $buffer) {
         if (Process::ERR === $type) {
             echo $buffer;
         } else {
             echo $buffer;
         }
     });
     $output->writeln('');
     if (!$process->isSuccessful()) {
         $output->writeln('<fg=cyan>TERRA</> | <fg=red>Test Failed</> ');
         return 1;
     } else {
         $output->writeln('<fg=cyan>TERRA</> | <info>Test Passed!</info> ');
         return 0;
     }
 }