Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

magento/magento2-functional-testing-framework#60: Build interactive configuration tool for populating .env properties #69

Merged
merged 2 commits into from
Mar 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
MAGENTO_BASE_URL=http://devdocs.magento.com/

#*** Set the Admin Username and Password for your Magento instance ***#
MAGENTO_BACKEND_NAME=
MAGENTO_ADMIN_USERNAME=
MAGENTO_ADMIN_PASSWORD=
MAGENTO_BACKEND_NAME=admin
MAGENTO_ADMIN_USERNAME=admin
MAGENTO_ADMIN_PASSWORD=123123q

#*** Path to CLI entry point and command parameter name. Uncomment and change if folder structure differs from standard Magento installation
#MAGENTO_CLI_COMMAND_PATH=dev/tests/acceptance/utils/command.php
Expand Down
1 change: 1 addition & 0 deletions RoboFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ function cloneFiles()
*/
function buildProject()
{
$this->writeln("<error>This command will be removed in MFTF v3.0.0. Please use bin/mftf build:project instead.</error>\n");
$this->cloneFiles();
$this->_exec('vendor'. DIRECTORY_SEPARATOR .'bin'. DIRECTORY_SEPARATOR .'codecept build');
}
Expand Down
30 changes: 30 additions & 0 deletions bin/mftf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env php

<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

if (PHP_SAPI !== 'cli') {
echo 'bin/mftf must be run as a CLI application';
exit(1);
}

try {
require_once __DIR__ . '/../bootstrap.php';
$application = new Symfony\Component\Console\Application();
$application->setName('Magento Functional Testing Framework CLI');
$application->setVersion('1.0.0');
$application->add(new Magento\FunctionalTestingFramework\Console\SetupEnvCommand());
$application->add(new Magento\FunctionalTestingFramework\Console\BuildProjectCommand());
$application->run();
} catch (\Exception $e) {
while ($e) {
echo $e->getMessage();
echo $e->getTraceAsString();
echo "\n\n";
$e = $e->getPrevious();
}
exit(1);
}
8 changes: 8 additions & 0 deletions bootstrap.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

require_once 'vendor/autoload.php';
define('BP', __DIR__);
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php
// @codingStandardsIgnoreFile
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types = 1);

namespace Magento\FunctionalTestingFramework\Console;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Process\Process;
use Magento\FunctionalTestingFramework\Util\Env\EnvProcessor;

class BuildProjectCommand extends Command
{
/**
* Env processor manages .env files.
*
* @var \Magento\FunctionalTestingFramework\Util\Env\EnvProcessor
*/
private $envProcessor;

/**
* Configures the current command.
*
* @return void
*/
protected function configure()
{
$this->setName('build:project');
$this->setDescription('Generate configuration files for the project. Build the Codeception project.');
$this->envProcessor = new EnvProcessor(BP . DIRECTORY_SEPARATOR . '.env');
$env = $this->envProcessor->getEnv();
foreach ($env as $key => $value) {
$this->addOption($key, null, InputOption::VALUE_REQUIRED, '', $value);
}
}

/**
* Executes the current command.
*
* @param InputInterface $input
* @param OutputInterface $output
* @return void
* @throws \Symfony\Component\Console\Exception\LogicException
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$fileSystem = new Filesystem();
$fileSystem->copy(
BP . DIRECTORY_SEPARATOR . 'codeception.dist.yml',
BP . DIRECTORY_SEPARATOR . 'codeception.yml'
);
$output->writeln("codeception.yml configuration successfully applied.\n");
$fileSystem->copy(
BP . DIRECTORY_SEPARATOR . 'dev' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR .
'functional' . DIRECTORY_SEPARATOR . 'MFTF.suite.dist.yml',
BP . DIRECTORY_SEPARATOR . 'dev' . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR .
'functional' . DIRECTORY_SEPARATOR . 'MFTF.suite.yml'
);
$output->writeln("MFTF.suite.yml configuration successfully applied.\n");

$setupEnvCommand = new SetupEnvCommand();
$commandInput = [];
$options = $input->getOptions();
$env = array_keys($this->envProcessor->getEnv());
foreach ($options as $key => $value) {
if (in_array($key, $env)) {
$commandInput['--' . $key] = $value;
}
}
$commandInput = new ArrayInput($commandInput);
$setupEnvCommand->run($commandInput, $output);

$process = new Process('vendor/bin/codecept build');
$process->run();
if ($process->isSuccessful()) {
$output->writeln("Codeception build run successfully.\n");
}

$output->writeln('<info>The project built successfully.</info>');
}
}
64 changes: 64 additions & 0 deletions src/Magento/FunctionalTestingFramework/Console/SetupEnvCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php
// @codingStandardsIgnoreFile
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types = 1);

namespace Magento\FunctionalTestingFramework\Console;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Exception\InvalidOptionException;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Magento\FunctionalTestingFramework\Util\Env\EnvProcessor;

class SetupEnvCommand extends Command
{
/**
* Env processor manages .env files.
*
* @var \Magento\FunctionalTestingFramework\Util\Env\EnvProcessor
*/
private $envProcessor;

/**
* Configures the current command.
*
* @return void
*/
protected function configure()
{
$this->setName('setup:env');
$this->setDescription("Generate .env file.");
$this->envProcessor = new EnvProcessor(BP . DIRECTORY_SEPARATOR . '.env');
$env = $this->envProcessor->getEnv();
foreach ($env as $key => $value) {
$this->addOption($key, null, InputOption::VALUE_REQUIRED, '', $value);
}
}

/**
* Executes the current command.
*
* @param InputInterface $input
* @param OutputInterface $output
* @return void
* @throws \Symfony\Component\Console\Exception\LogicException
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$config = $this->envProcessor->getEnv();
$userEnv = [];
foreach ($config as $key => $value) {
if ($input->getOption($key) === '') {
throw new InvalidOptionException(sprintf("Parameter $key cannot be empty.", $key));
}
$userEnv[$key] = $input->getOption($key);
}
$this->envProcessor->putEnvFile($userEnv);
$output->writeln(".env configuration successfully applied.\n");
}
}
99 changes: 99 additions & 0 deletions src/Magento/FunctionalTestingFramework/Util/Env/EnvProcessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php
// @codingStandardsIgnoreFile
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types = 1);

namespace Magento\FunctionalTestingFramework\Util\Env;

/**
* Helper class EnvProcessor for reading and writing .env files.
*
* @package Magento\FunctionalTestingFramework\Util\Env
*/
class EnvProcessor
{
/**
* File .env location.
*
* @var string
*/
private $envFile = '';

/**
* File .env.example location.
*
* @var string
*/
private $envExampleFile = '';

/**
* Array of environment variables form file.
*
* @var array
*/
private $env = [];

/**
* EnvProcessor constructor.
* @param string $envFile
*/
public function __construct(
string $envFile = ''
) {
$this->envFile = $envFile;
$this->envExampleFile = $envFile . '.example';
}

/**
* Serves for parsing '.env.example' file into associative array.
*
* @return array
*/
public function parseEnvFile(): array
{
$envLines = file(
$this->envExampleFile,
FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES
);
$env = [];
foreach ($envLines as $line) {
// do not use commented out lines
if (strpos($line, '#') !== 0) {
list($key, $value) = explode('=', $line);
$env[$key] = $value;
}
}
return $env;
}

/**
* Serves for putting array with environment variables into .env file.
*
* @param array $config
* @return void
*/
public function putEnvFile(array $config = [])
{
$envData = '';
foreach ($config as $key => $value) {
$envData .= $key . '=' . $value . PHP_EOL;
}
file_put_contents($this->envFile, $envData);
}

/**
* Retrieves '.env.example' file as associative array.
*
* @return array
*/
public function getEnv(): array
{
if (empty($this->env)) {
$this->env = $this->parseEnvFile();
}
return $this->env;
}
}