diff --git a/Mage/Command/AbstractCommand.php b/Mage/Command/AbstractCommand.php index f69b0ef..0d45d5f 100644 --- a/Mage/Command/AbstractCommand.php +++ b/Mage/Command/AbstractCommand.php @@ -26,6 +26,34 @@ abstract class AbstractCommand */ protected $config = null; + /** + * Command's help message + * + * @var string + */ + private $helpMessage; + + /** + * Usage examples. + * + * @var array + */ + private $usageExamples = array(); + + /** + * Command's syntax message + * + * @var string + */ + private $syntaxMessage; + + /** + * Command name + * + * @var string + */ + private $name; + /** * Runs the Command * @return integer exit code @@ -52,4 +80,112 @@ abstract class AbstractCommand { return $this->config; } + + /** + * Sets command name + * + * @param string $name Command name + * @return $this + */ + public function setName($name) + { + $this->name = $name; + + return $this; + } + + /** + * Sets command's help message + * + * @param string $message Command's help message + * @return $this + */ + public function setHelpMessage($message) + { + $this->helpMessage = $message; + + return $this; + } + + /** + * Adds command's usage example + * + * @param string $snippet Example's snippet + * @param string $description Example's description + * @return $this + */ + public function addUsageExample($snippet, $description = '') + { + array_push($this->usageExamples, array($snippet, $description)); + + return $this; + } + + /** + * Sets command's syntax message + * + * @param string $message Syntax message + * @return $this + */ + public function setSyntaxMessage($message) + { + $this->syntaxMessage = $message; + + return $this; + } + + /** + * Returns formatted command info + * + * @return string + */ + public function getInfoMessage() + { + $indent = str_repeat(" ", 4); + + $output = ""; + if (!empty($this->name)) { + $output .= "\n"; + $output .= "Command: "; + $output .= $this->name; + } + + if (!empty($this->helpMessage)) { + $output .= "\n"; + $output .= "{$this->helpMessage}\n"; + } + + if (!empty($this->syntaxMessage)) { + $output .= "\n"; + $output .= "Syntax:\n"; + $output .= "$indent{$this->syntaxMessage}"; + $output .= "\n"; + } + + if (!empty($this->usageExamples)) { + $output .= "\n"; + $output .= "Usage examples:\n"; + foreach ($this->usageExamples as $example) { + $snippet = $example[0]; + $description = $example[1]; + $output .= "$indent* "; + if (!empty($description)) { + $description = rtrim($description, ': ') . ":"; + $output .= $description; + $output .= "\n$indent$indent"; + } + + $output .= "$snippet"; + $output .= "\n"; + } + } + + if (empty($output)) { + $output .= "\n"; + $output .= "Sorry, there's no help for this command at the moment."; + $output .= "\n"; + } + + return $output; + } } diff --git a/Mage/Command/BuiltIn/AddCommand.php b/Mage/Command/BuiltIn/AddCommand.php index 26d9a37..7932e5c 100644 --- a/Mage/Command/BuiltIn/AddCommand.php +++ b/Mage/Command/BuiltIn/AddCommand.php @@ -23,6 +23,21 @@ use Exception; */ class AddCommand extends AbstractCommand { + public function __construct() + { + $this->setName('Add command') + ->setHelpMessage('Generates new config for Magallanes. For now, only adding a environment is possible') + ->setSyntaxMessage('mage add [environment] [--name=env_name] [--enableReleases]') + ->addUsageExample( + 'mage add environment --name=production', + 'Add a production environment' + ) + ->addUsageExample( + 'mage add environment --name=qa --enableReleases', + 'Add a QA environment and enable releasing' + ); + } + /** * Adds new Configuration Elements * @see \Mage\Command\AbstractCommand::run() diff --git a/Mage/Command/BuiltIn/CompileCommand.php b/Mage/Command/BuiltIn/CompileCommand.php index ab92fd2..38a8049 100644 --- a/Mage/Command/BuiltIn/CompileCommand.php +++ b/Mage/Command/BuiltIn/CompileCommand.php @@ -33,6 +33,10 @@ class CompileCommand extends AbstractCommand } $this->compiler = $compiler; + + $this->setName('Compile command') + ->setHelpMessage('Compiles Magallanes to mage.phar file') + ->setSyntaxMessage('mage compile'); } /** diff --git a/Mage/Command/BuiltIn/DeployCommand.php b/Mage/Command/BuiltIn/DeployCommand.php index 9105792..df75a08 100644 --- a/Mage/Command/BuiltIn/DeployCommand.php +++ b/Mage/Command/BuiltIn/DeployCommand.php @@ -103,6 +103,22 @@ class DeployCommand extends AbstractCommand implements RequiresEnvironment */ protected static $failedTasks = 0; + public function __construct() + { + $this->setName('Deploy command') + ->setHelpMessage('Deploys the project into target environment') + ->setSyntaxMessage('mage deploy to:[environment_name]') + ->addUsageExample( + 'mage deploy to:production', + 'Deploy the project into production environment' + ) + ->addUsageExample( + 'mage deploy to:production --overrideRelease', + 'Deploy the project into production environment ' + . 'but skip SkipOnOverride aware tasks' + ); + } + /** * Returns the Status of the Deployment * @@ -199,7 +215,7 @@ class DeployCommand extends AbstractCommand implements RequiresEnvironment Console::output('Total time: ' . $timeText . '.', 1, 2); // Send Notifications - $this->sendNotification(self::$failedTasks > 0 ? false : true); + $this->sendNotification(self::$failedTasks > 0 ? false : true, new Mailer()); // Unlock if (file_exists(getcwd() . '/.mage/~working.lock')) { @@ -209,11 +225,11 @@ class DeployCommand extends AbstractCommand implements RequiresEnvironment if (self::$failedTasks === 0) { $exitCode = 0; } - + if (self::$deployStatus === self::FAILED) { $exitCode = 1; } - + return $exitCode; } @@ -251,7 +267,7 @@ class DeployCommand extends AbstractCommand implements RequiresEnvironment // Change Branch Back if ($config->deployment('scm', false)) { - array_unshift($tasksToRun, 'scm/change-branch'); + array_push($tasksToRun, 'scm/change-branch'); $config->addParameter('_changeBranchRevert'); } @@ -567,25 +583,35 @@ class DeployCommand extends AbstractCommand implements RequiresEnvironment /** * Send Email Notification if enabled * @param boolean $result + * @param mixed $mailer * @return boolean */ - protected function sendNotification($result) + protected function sendNotification($result, $mailer) { $projectName = $this->getConfig()->general('name', false); $projectEmail = $this->getConfig()->general('email', false); $notificationsEnabled = $this->getConfig()->general('notifications', false); + $emailOptions = $this->getConfig()->general('email_options', array()); // We need notifications enabled, and a project name and email to send the notification if (!$projectName || !$projectEmail || !$notificationsEnabled) { return false; } - $mailer = new Mailer; $mailer->setAddress($projectEmail) ->setProject($projectName) ->setLogFile(Console::getLogFile()) - ->setEnvironment($this->getConfig()->getEnvironment()) - ->send($result); + ->setEnvironment($this->getConfig()->getEnvironment()); + + if (isset($emailOptions['cc'])) { + $mailer->setCc($emailOptions['cc']); + } + + if (isset($emailOptions['bcc'])) { + $mailer->setBcc($emailOptions['bcc']); + } + + $mailer->send($result); return true; } diff --git a/Mage/Command/BuiltIn/InitCommand.php b/Mage/Command/BuiltIn/InitCommand.php index 326f0e9..a363583 100644 --- a/Mage/Command/BuiltIn/InitCommand.php +++ b/Mage/Command/BuiltIn/InitCommand.php @@ -20,6 +20,20 @@ use Mage\Console; */ class InitCommand extends AbstractCommand { + public function __construct() + { + $this->setName('Initialize command') + ->setHelpMessage('Initialize Magallanes project, create .mage directory with starter configs') + ->setSyntaxMessage('mage init --name=[project_name] [--email=[author_email]]') + ->addUsageExample( + 'mage init --name="My awesome project"', + 'Initialize "My awesome project" configuration' + ) + ->addUsageExample( + 'mage init --name="My project" --email="john.smith@example.com"', + 'Initialize "My project" configuration with email notification enabled for john.smith@example.com' + ); + } /** * Command for Initalize a new Configuration Proyect diff --git a/Mage/Command/BuiltIn/InstallCommand.php b/Mage/Command/BuiltIn/InstallCommand.php index 530e1d7..ffa1dbe 100644 --- a/Mage/Command/BuiltIn/InstallCommand.php +++ b/Mage/Command/BuiltIn/InstallCommand.php @@ -20,6 +20,24 @@ use Mage\Console; */ class InstallCommand extends AbstractCommand { + public function __construct() + { + $this->setName('Install command') + ->setHelpMessage( + 'Installs Magallanes system-widely.' + . ' By default, Magallanes\' going to be installed in /opt/magallanes' + ) + ->setSyntaxMessage('mage install [--installDir=[install_directory]] [--systemWide]') + ->addUsageExample( + 'mage install --installDir=/src/projects/Magellanes', + 'Install Magallanes at /src/projects/Magallanes directory' + ) + ->addUsageExample( + 'mage install --systemWide', + 'Install Magallanes at default directory and creates a symlink in /usr/bin/mage' + ); + } + /** * Installs Magallanes * @see \Mage\Command\AbstractCommand::run() diff --git a/Mage/Command/BuiltIn/ListCommand.php b/Mage/Command/BuiltIn/ListCommand.php index d7dd082..b0ff426 100644 --- a/Mage/Command/BuiltIn/ListCommand.php +++ b/Mage/Command/BuiltIn/ListCommand.php @@ -23,6 +23,17 @@ use Exception; */ class ListCommand extends AbstractCommand { + public function __construct() + { + $this->setName('List command') + ->setHelpMessage('List available configurations. For now, only environments listing available') + ->setSyntaxMessage('mage list [environments]') + ->addUsageExample( + 'mage list environments', + 'List currently configured environments' + ); + } + /** * Command for Listing Configuration Elements * @see \Mage\Command\AbstractCommand::run() diff --git a/Mage/Command/BuiltIn/LockCommand.php b/Mage/Command/BuiltIn/LockCommand.php index 09df123..9e00862 100644 --- a/Mage/Command/BuiltIn/LockCommand.php +++ b/Mage/Command/BuiltIn/LockCommand.php @@ -21,6 +21,21 @@ use Mage\Console; */ class LockCommand extends AbstractCommand implements RequiresEnvironment { + public function __construct() + { + $this->setName('Lock command') + ->setHelpMessage( + "Locks the deployment to given environment and creates a lock file " + . "with lock reason and lock performer.\n" + . "You are going to be prompted to provide this information" + ) + ->setSyntaxMessage('mage lock to:[environment_name]') + ->addUsageExample( + 'mage lock to:production', + 'Create a lock to production environment deployment' + ); + } + /** * Locks the Deployment to a Environment * @see \Mage\Command\AbstractCommand::run() diff --git a/Mage/Command/BuiltIn/ReleasesCommand.php b/Mage/Command/BuiltIn/ReleasesCommand.php index 3a40439..ddbb712 100644 --- a/Mage/Command/BuiltIn/ReleasesCommand.php +++ b/Mage/Command/BuiltIn/ReleasesCommand.php @@ -22,6 +22,36 @@ use Mage\Console; */ class ReleasesCommand extends AbstractCommand implements RequiresEnvironment { + public function __construct() + { + $this->setName('Releases management command') + ->setHelpMessage('Manages releases') + ->setSyntaxMessage( + 'mage releases [list|rollback [--release=[release_id]]] ' + . 'to:[environment_name] [--deleteCurrent]' + ) + ->addUsageExample( + 'mage releases list to:production', + 'List releases on production environment' + ) + ->addUsageExample( + 'mage releases rollback --release=20120101172148 to:production', + 'Rollback 20120101172148 release on production environment' + ) + ->addUsageExample( + 'mage releases rollback --release=-1 to:production', + 'Rollback list release -1 release on production environment' + ) + ->addUsageExample( + 'mage releases rollback --release=0 to:production', + 'Rollback last release on production environment' + ) + ->addUsageExample( + 'mage releases rollback -1 to:production --deleteCurrent', + 'Rollbacks the last release -1 release and removes current release' + ); + } + /** * List the Releases, Rollback to a Release * @see \Mage\Command\AbstractCommand::run() diff --git a/Mage/Command/BuiltIn/RollbackCommand.php b/Mage/Command/BuiltIn/RollbackCommand.php index dea92b0..88db0f9 100644 --- a/Mage/Command/BuiltIn/RollbackCommand.php +++ b/Mage/Command/BuiltIn/RollbackCommand.php @@ -22,6 +22,24 @@ use Mage\Console; */ class RollbackCommand extends AbstractCommand implements RequiresEnvironment { + public function __construct() + { + $this->setName('Rollback command') + ->setHelpMessage('Rollbacks the release by given release id or index') + ->setSyntaxMessage('mage rollback [releaseId] to:[environment_name]') + ->addUsageExample( + 'mage rollback 20120101172148 to:production', + 'Rollbacks the 20120101172148 release on production environment' + ) + ->addUsageExample( + 'mage rollback -1 to:production', + 'Rollbacks the last release -1 release' + ) + ->addUsageExample( + 'mage rollback -1 to:production --deleteCurrent', + 'Rollbacks the last release -1 release and removes current release' + ); + } /** * Rollback a release * @see \Mage\Command\AbstractCommand::run() diff --git a/Mage/Command/BuiltIn/UnlockCommand.php b/Mage/Command/BuiltIn/UnlockCommand.php index 2c7d324..874ccef 100644 --- a/Mage/Command/BuiltIn/UnlockCommand.php +++ b/Mage/Command/BuiltIn/UnlockCommand.php @@ -21,6 +21,17 @@ use Mage\Console; */ class UnlockCommand extends AbstractCommand implements RequiresEnvironment { + public function __construct() + { + $this->setName('Unlock command') + ->setHelpMessage('Unlocks deployment for given environment') + ->setSyntaxMessage('mage unlock to:[environment_name]') + ->addUsageExample( + 'mage unlock to:production', + 'Removes the lock form production environment deployment' + ); + } + /** * Unlocks an Environment * @see \Mage\Command\AbstractCommand::run() diff --git a/Mage/Command/BuiltIn/UpdateCommand.php b/Mage/Command/BuiltIn/UpdateCommand.php index 30cff52..699c90a 100644 --- a/Mage/Command/BuiltIn/UpdateCommand.php +++ b/Mage/Command/BuiltIn/UpdateCommand.php @@ -21,6 +21,13 @@ use Mage\Console; */ class UpdateCommand extends AbstractCommand { + public function __construct() + { + $this->setName('Update command') + ->setHelpMessage('Updates the SCM base code') + ->setSyntaxMessage('mage update'); + } + /** * Updates the SCM Base Code * @see \Mage\Command\AbstractCommand::run() diff --git a/Mage/Command/BuiltIn/UpgradeCommand.php b/Mage/Command/BuiltIn/UpgradeCommand.php index a9861ac..c6083ee 100644 --- a/Mage/Command/BuiltIn/UpgradeCommand.php +++ b/Mage/Command/BuiltIn/UpgradeCommand.php @@ -20,6 +20,13 @@ use Mage\Console; */ class UpgradeCommand extends AbstractCommand { + public function __construct() + { + $this->setName('Upgrade command') + ->setHelpMessage('Upgrades Magallanes') + ->setSyntaxMessage('mage upgrade'); + } + /** * Source for downloading * @var string diff --git a/Mage/Command/BuiltIn/VersionCommand.php b/Mage/Command/BuiltIn/VersionCommand.php index 0c7938c..665e559 100644 --- a/Mage/Command/BuiltIn/VersionCommand.php +++ b/Mage/Command/BuiltIn/VersionCommand.php @@ -20,6 +20,12 @@ use Mage\Console; */ class VersionCommand extends AbstractCommand { + public function __construct() + { + $this->setName('Version command') + ->setHelpMessage('Displays the current version of Magallanes') + ->setSyntaxMessage('mage version'); + } /** * Display the Magallanes Version * @see \Mage\Command\AbstractCommand::run() diff --git a/Mage/Compiler.php b/Mage/Compiler.php index ad209fc..4792b3e 100644 --- a/Mage/Compiler.php +++ b/Mage/Compiler.php @@ -21,7 +21,6 @@ use RecursiveDirectoryIterator; */ class Compiler { - /** * Compiles the library * diff --git a/Mage/Console.php b/Mage/Console.php index d9fcbb2..daccf00 100644 --- a/Mage/Console.php +++ b/Mage/Console.php @@ -132,10 +132,14 @@ class Console try { $command = Factory::get($commandName, $config); - if ($command instanceof RequiresEnvironment) { - if ($config->getEnvironment() === false) { - throw new Exception('You must specify an environment for this command.'); - } + if ($config->getParameter('help')) { + self::output($command->getInfoMessage(), 2); + + return 0; + } + + if ($command instanceof RequiresEnvironment && $config->getEnvironment() === false) { + throw new Exception('You must specify an environment for this command.'); } // Run the Command @@ -204,7 +208,7 @@ class Console $return = 1; $log = array(); - exec($command . ' 2>&1', $log, $return); + exec(escapeshellcmd($command . ' 2>&1'), $log, $return); $log = implode(PHP_EOL, $log); if (!$return) { diff --git a/Mage/Mailer.php b/Mage/Mailer.php index 1751c85..8a9abe1 100644 --- a/Mage/Mailer.php +++ b/Mage/Mailer.php @@ -14,6 +14,7 @@ namespace Mage; * Mailer Helper. * * @author Andrés Montañez + * @author César Suárez */ class Mailer { @@ -24,6 +25,8 @@ class Mailer protected $project; protected $environment; protected $logFile; + protected $cc; + protected $bcc; public function setAddress($address) { @@ -49,6 +52,18 @@ class Mailer return $this; } + public function setBcc($bcc) + { + $this->bcc = $bcc; + return $this; + } + + public function setCc($cc) + { + $this->cc = $cc; + return $this; + } + public function send($result) { $boundary = md5(date('r', time())); @@ -61,6 +76,14 @@ class Mailer . self::EOL . 'Content-Type: multipart/mixed; boundary=Mage-mixed-' . $boundary; + if ($this->cc) { + $headers .= self::EOL . 'Cc: ' . $this->cc; + } + + if ($this->bcc) { + $headers .= self::EOL . 'Bcc: ' . $this->bcc; + } + $subject = str_replace( array('{project}', '{environment}', '{result}'), array($this->project, $this->environment, $result ? 'SUCCESS' : 'FAILURE'), @@ -83,6 +106,6 @@ class Mailer . $attachment . self::EOL . '--Mage-mixed-' . $boundary . '--' . self::EOL; - mail($this->address, $subject, $message, $headers); + return mail($this->address, $subject, $message, $headers); } } diff --git a/Mage/Task/AbstractTask.php b/Mage/Task/AbstractTask.php index 5edd4fa..ec1d4e0 100644 --- a/Mage/Task/AbstractTask.php +++ b/Mage/Task/AbstractTask.php @@ -222,6 +222,7 @@ abstract class AbstractTask */ final protected function runCommand($command, &$output = null) { + $command = ltrim($this->getEnvVarsString() . ' ' . $command); if ($this->getStage() == self::STAGE_DEPLOY || $this->getStage() == self::STAGE_POST_RELEASE) { return $this->runCommandRemote($command, $output); } else { @@ -305,4 +306,56 @@ abstract class AbstractTask } return $result; } + + /** + * Returns the array of environment variables + * Returned array contains both system variables and variables set in config + * WARNING: To access system's variables you need to set proper value in your php.ini at variables_order key + * @see http://php.net/manual/en/ini.core.php#ini.variables-order + * + * @return array + */ + protected function getEnvVariables() + { + $configVars = array_merge( + $this->getConfig()->general('env', array()), + $this->getConfig()->environmentConfig('env', array()), + $this->getConfig()->getParameter('env', array()), + array( + 'variables' => $this->getConfig()->getParameter('env.variables', array()) + ) + ); + + if (isset($configVars['variables'])) { + $configVars = $configVars['variables']; + } + + $envVariables = array_merge( + $_ENV, + $configVars + ); + + return $envVariables; + } + + /** + * Returns ready to inject environment string + * The string is build from env vars array in schema: + * key1=value1 key2=value3 ... + * + * @return string + */ + protected function getEnvVarsString() + { + $envVarsArray = $this->getEnvVariables(); + $envVars = array_map( + function ($key, $value) { + return "$key=$value"; + }, + array_keys($envVarsArray), + $this->getEnvVariables() + ); + + return join(' ', $envVars); + } } diff --git a/Mage/Task/BuiltIn/Deployment/ReleaseTask.php b/Mage/Task/BuiltIn/Deployment/ReleaseTask.php index 7d6b72d..d45909d 100644 --- a/Mage/Task/BuiltIn/Deployment/ReleaseTask.php +++ b/Mage/Task/BuiltIn/Deployment/ReleaseTask.php @@ -90,18 +90,16 @@ class ReleaseTask extends AbstractTask implements IsReleaseAware, SkipOnOverride if (!empty($infoArray[3])) { $group = $infoArray[3]; } - $userGroup = $user . ':' . $group; } + $userGroup = $user . ':' . $group; } - if ($resultFetch && $userGroup != '') { - $command = 'chown -R ' . $userGroup . ' ' . $currentCopy - . ' && ' - . 'chown ' . $userGroup . ' ' . $releasesDirectory; - $result = $this->runCommandRemote($command); - if (!$result) { - return $result; - } + $command = 'chown -R ' . $userGroup . ' ' . $currentCopy + . ' && ' + . 'chown ' . $userGroup . ' ' . $releasesDirectory; + $result = $this->runCommandRemote($command); + if (!$result) { + return $result; } // Switch symlink and change owner diff --git a/Mage/Task/BuiltIn/Filesystem/ApplyFaclsTask.php b/Mage/Task/BuiltIn/Filesystem/ApplyFaclsTask.php index 3f40ee7..116f826 100644 --- a/Mage/Task/BuiltIn/Filesystem/ApplyFaclsTask.php +++ b/Mage/Task/BuiltIn/Filesystem/ApplyFaclsTask.php @@ -33,7 +33,7 @@ class ApplyFaclsTask extends AbstractTask implements IsReleaseAware throw new SkipException('Parameter acl_param not set.'); } - $folders = $this->getParameter('folders', []); + $folders = $this->getParameter('folders', array()); $recursive = $this->getParameter('recursive', false) ? ' -R ' : ' '; foreach ($folders as $folder) { diff --git a/Mage/Task/BuiltIn/General/ManuallyTask.php b/Mage/Task/BuiltIn/General/ManuallyTask.php index 64870d3..a69c1a1 100644 --- a/Mage/Task/BuiltIn/General/ManuallyTask.php +++ b/Mage/Task/BuiltIn/General/ManuallyTask.php @@ -32,7 +32,6 @@ use Mage\Task\AbstractTask; */ class ManuallyTask extends AbstractTask { - /** * (non-PHPdoc) * @see \Mage\Task\AbstractTask::getName() diff --git a/README.md b/README.md index 9fe1b3b..ad7dfb9 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Simply add the following dependency to your project’s composer.json file: ```js "require-dev": { // ... - "andres-montanez/magallanes": "~1.0.*" + "andres-montanez/magallanes": "~1.0" // ... } ``` @@ -39,7 +39,7 @@ $ bin/mage version ### System-wide installation with composer ### ```bash -$ composer global require "andres-montanez/magallanes=~1.0.*" +$ composer global require "andres-montanez/magallanes=~1.0" ``` Make sure you have ~/.composer/vendor/bin/ in your path. diff --git a/composer.json b/composer.json index 5be1dd8..fc1679b 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ "require-dev": { "phpunit/phpunit": "4.3.5", "satooshi/php-coveralls": ">=0.6.1", - "malkusch/php-mock": "dev-php-5.3" + "php-mock/php-mock": "^0.1" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 7d89680..f3ff639 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "caa09089c7b57461ed42e97a4449f2c6", + "hash": "38a662749dc90d3cd6bb06c095ec14f1", "packages": [], "packages-dev": [ { @@ -154,17 +154,17 @@ "time": "2014-08-11 04:32:36" }, { - "name": "malkusch/php-mock", - "version": "dev-php-5.3", + "name": "php-mock/php-mock", + "version": "0.1.1", "source": { "type": "git", - "url": "https://github.com/malkusch/php-mock.git", - "reference": "37b301b4b479601232f3919920451c6e777c3264" + "url": "https://github.com/php-mock/php-mock.git", + "reference": "b48b05bfd43d8b051103a4515ab5613cb90e71da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/malkusch/php-mock/zipball/37b301b4b479601232f3919920451c6e777c3264", - "reference": "37b301b4b479601232f3919920451c6e777c3264", + "url": "https://api.github.com/repos/php-mock/php-mock/zipball/b48b05bfd43d8b051103a4515ab5613cb90e71da", + "reference": "b48b05bfd43d8b051103a4515ab5613cb90e71da", "shasum": "" }, "require": { @@ -199,7 +199,7 @@ "stub", "test" ], - "time": "2014-12-01 18:01:18" + "time": "2015-04-14 18:12:12" }, { "name": "phpunit/php-code-coverage", @@ -1256,9 +1256,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "malkusch/php-mock": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/docs/example-config/.mage/config/environment/production.yml b/docs/example-config/.mage/config/environment/production.yml index 97a3fcc..1af997f 100644 --- a/docs/example-config/.mage/config/environment/production.yml +++ b/docs/example-config/.mage/config/environment/production.yml @@ -22,3 +22,6 @@ tasks: - sampleTask - sampleTaskRollbackAware verbose_logging: true +env: + variables: + symfony_env: prod diff --git a/docs/example-config/.mage/config/general.yml b/docs/example-config/.mage/config/general.yml index c3a9b6d..3accc0e 100644 --- a/docs/example-config/.mage/config/general.yml +++ b/docs/example-config/.mage/config/general.yml @@ -7,3 +7,7 @@ verbose_logging: false scm: type: git url: git://github.com/andres-montanez/Zend-Framework-Twig-example-app.git +env: + variables: + node_path: "/bin/node" + symfony_env: prod diff --git a/tests/MageTest/Command/AbstractCommandTest.php b/tests/MageTest/Command/AbstractCommandTest.php index fed7df5..c700c49 100644 --- a/tests/MageTest/Command/AbstractCommandTest.php +++ b/tests/MageTest/Command/AbstractCommandTest.php @@ -44,4 +44,227 @@ class AbstractCommandTest extends BaseTest $configMock = $this->getMock('Mage\Config'); $this->doTestGetter($this->abstractCommand, 'config', $configMock); } + + public function infoMessageProvider() + { + return array( + 'happy_path' => array( + 'name' => 'Example command', + 'helpMessage' => 'This command does everything you want to', + 'examples' => array( + array( + 'snippet' => 'mage example', + 'description' => 'Default command' + ), + array( + 'snippet' => 'mage example light', + 'description' => 'Runs the command with lights' + ) + ), + 'syntax' => 'mage example [light]', + 'output' => "\n" + . "Command: Example command\n" + . "This command does everything you want to\n" + . "\n" + . "Syntax:\n" + . " mage example [light]\n" + . "\n" + . "Usage examples:\n" + . " * Default command:\n" + . " mage example\n" + . " * Runs the command with lights:\n" + . " mage example light\n" + ), + 'no_help_message' => array( + 'name' => 'Example command', + 'helpMessage' => '', + 'examples' => array( + array( + 'snippet' => 'mage example', + 'description' => 'Default command' + ), + array( + 'snippet' => 'mage example light', + 'description' => 'Runs the command with lights' + ) + ), + 'syntax' => 'mage example [light]', + 'output' => "\n" + . "Command: Example command\n" + . "Syntax:\n" + . " mage example [light]\n" + . "\n" + . "Usage examples:\n" + . " * Default command:\n" + . " mage example\n" + . " * Runs the command with lights:\n" + . " mage example light\n" + ), + 'no_examples' => array( + 'name' => 'Example command', + 'helpMessage' => 'This command does everything you want to', + 'examples' => array(), + 'syntax' => 'mage example [light]', + 'output' => "\n" + . "Command: Example command\n" + . "This command does everything you want to\n" + . "\n" + . "Syntax:\n" + . " mage example [light]\n" + ), + "no_syntax" => array( + 'name' => 'Example command', + 'helpMessage' => 'This command does everything you want to', + 'examples' => array( + array( + 'snippet' => 'mage example', + 'description' => 'Default command' + ), + array( + 'snippet' => 'mage example light', + 'description' => 'Runs the command with lights' + ) + ), + 'syntax' => '', + 'output' => "\n" + . "Command: Example command\n" + . "This command does everything you want to\n" + . "\n" + . "Usage examples:\n" + . " * Default command:\n" + . " mage example\n" + . " * Runs the command with lights:\n" + . " mage example light\n" + ), + "stripping_colons" => array( + 'name' => 'Example command', + 'helpMessage' => 'This command does everything you want to', + 'examples' => array( + array( + 'snippet' => 'mage example', + 'description' => 'Default command : ' + ), + array( + 'snippet' => 'mage example light', + 'description' => 'Runs the command with lights: ' + ) + ), + 'syntax' => 'mage example [light]', + 'output' => "\n" + . "Command: Example command\n" + . "This command does everything you want to\n" + . "\n" + . "Syntax:\n" + . " mage example [light]\n" + . "\n" + . "Usage examples:\n" + . " * Default command:\n" + . " mage example\n" + . " * Runs the command with lights:\n" + . " mage example light\n" + ), + "only_help" => array( + 'name' => 'Example command', + 'helpMessage' => 'This command does everything you want to', + 'examples' => array(), + 'syntax' => '', + 'output' => "\n" + . "Command: Example command\n" + . "This command does everything you want to\n" + ), + "only_examples" => array( + 'name' => 'Example command', + 'helpMessage' => '', + 'examples' => array( + array( + 'snippet' => 'mage example', + 'description' => 'Default command' + ), + array( + 'snippet' => 'mage example light', + 'description' => 'Runs the command with lights' + ) + ), + 'syntax' => '', + 'output' => "\n" + . "Command: Example command\n" + . "Usage examples:\n" + . " * Default command:\n" + . " mage example\n" + . " * Runs the command with lights:\n" + . " mage example light\n" + ), + "only_syntax" => array( + 'name' => 'Example command', + 'helpMessage' => '', + 'examples' => array(), + 'syntax' => 'mage example [light]', + 'output' => "\n" + . "Command: Example command\n" + . "Syntax:\n" + . " mage example [light]\n" + ), + "no_name" => array( + 'name' => '', + 'helpMessage' => 'This command does everything you want to', + 'examples' => array( + array( + 'snippet' => 'mage example', + 'description' => 'Default command' + ), + array( + 'snippet' => 'mage example light', + 'description' => 'Runs the command with lights' + ) + ), + 'syntax' => 'mage example [light]', + 'output' => "\n" + . "This command does everything you want to\n" + . "\n" + . "Syntax:\n" + . " mage example [light]\n" + . "\n" + . "Usage examples:\n" + . " * Default command:\n" + . " mage example\n" + . " * Runs the command with lights:\n" + . " mage example light\n" + ), + "no_info_at_all" => array( + 'name' => '', + 'helpMessage' => '', + 'examples' => array(), + 'syntax' => '', + 'output' => "\n" + . "Sorry, there's no help for this command at the moment.\n" + ) + ); + } + + /** + * @covers ::getInfoMessage + * @covers ::setHelpMessage + * @covers ::addUsageExample + * @covers ::setSyntaxMessage + * @covers ::setName + * + * @dataProvider infoMessageProvider + */ + public function testGetInfoMessage($name, $helpMessage, $examples, $syntax, $expectedMessage) + { + /** @var AbstractCommand $command */ + $command = $this->getMockForAbstractClass('Mage\Command\AbstractCommand'); + + $command->setName($name); + + foreach ($examples as $example) { + $command->addUsageExample($example['snippet'], $example['description']); + } + + $command->setHelpMessage($helpMessage); + $command->setSyntaxMessage($syntax); + + $actualMessage = $command->getInfoMessage(); + $this->assertEquals($expectedMessage, $actualMessage); + } } diff --git a/tests/MageTest/Command/BuiltIn/CompileCommandTest.php b/tests/MageTest/Command/BuiltIn/CompileCommandTest.php index 44b4486..77af2a3 100644 --- a/tests/MageTest/Command/BuiltIn/CompileCommandTest.php +++ b/tests/MageTest/Command/BuiltIn/CompileCommandTest.php @@ -16,6 +16,7 @@ use malkusch\phpmock\MockBuilder; * @uses malkusch\phpmock\MockBuilder * @uses Mage\Console * @uses Mage\Console\Colors + * @uses Mage\Command\AbstractCommand */ class CompileCommandTest extends BaseTest { diff --git a/tests/MageTest/Command/BuiltIn/DeployCommandTest.php b/tests/MageTest/Command/BuiltIn/DeployCommandTest.php new file mode 100644 index 0000000..b74a304 --- /dev/null +++ b/tests/MageTest/Command/BuiltIn/DeployCommandTest.php @@ -0,0 +1,130 @@ +getMock('Mage\Mailer'); + $mailerMock + ->method('setAddress') + ->willReturnSelf(); + + $mailerMock + ->method('setProject') + ->willReturnSelf(); + + $mailerMock + ->method('setLogFile') + ->willReturnSelf(); + + $mailerMock + ->method('setEnvironment') + ->willReturnSelf(); + + $mailerMock + ->expects($this->once()) + ->method('send'); + + $configMock = $this->getMock('Mage\Config'); + $configMock + ->method('general') + ->willReturn(true); + + $deployCommand = new DeployCommand(); + $deployCommand->setConfig($configMock); + + $this->callMethod( + $deployCommand, + 'sendNotification', + array(true, $mailerMock)); + } + + public function testIgnoreNotification() + { + $mailerMock = $this->getMock('Mage\Mailer'); + + $mailerMock + ->expects($this->never()) + ->method('send'); + + $configMock = $this->getMock('Mage\Config'); + $configMock + ->method('general') + ->willReturn(false); + + $deployCommand = new DeployCommand(); + $deployCommand->setConfig($configMock); + $this->callMethod($deployCommand, 'sendNotification', array(true, $mailerMock)); + } + + /** + * @covers ::__construct + * @covers ::sendNotification + */ + public function testSendNotificationWithEmailOptions() + { + $mailerMock = $this->getMock('Mage\Mailer'); + $mailerMock + ->method('setAddress') + ->willReturnSelf(); + + $mailerMock + ->method('setProject') + ->willReturnSelf(); + + $mailerMock + ->method('setLogFile') + ->willReturnSelf(); + + $mailerMock + ->method('setEnvironment') + ->willReturnSelf(); + + $mailerMock + ->expects($this->once()) + ->method('setCc') + ->willReturnSelf(); + + $mailerMock + ->expects($this->once()) + ->method('setBcc') + ->willReturnSelf(); + + $mailerMock + ->expects($this->once()) + ->method('send'); + + $configMock = $this->getMock('Mage\Config'); + + $configMock + ->method('general') + ->will($this->returnCallback(function($option, $default) { + if (strcmp($option, 'email_options') === 0) { + return array('bcc' => true, 'cc' => true); + } + return true; + })); + + $deployCommand = new DeployCommand(); + $deployCommand->setConfig($configMock); + + $this->callMethod( + $deployCommand, + 'sendNotification', + array(true, $mailerMock)); + } +} diff --git a/tests/MageTest/Command/BuiltIn/ListCommandTest.php b/tests/MageTest/Command/BuiltIn/ListCommandTest.php index 4d193e1..36c1389 100644 --- a/tests/MageTest/Command/BuiltIn/ListCommandTest.php +++ b/tests/MageTest/Command/BuiltIn/ListCommandTest.php @@ -93,6 +93,7 @@ class ListCommandTest extends BaseTest } /** + * @covers ::__construct * @covers ::run * @covers ::listEnvironments * @dataProvider listEnvironmentsProvider @@ -109,6 +110,7 @@ class ListCommandTest extends BaseTest } /** + * @covers ::__construct * @covers ::run */ public function testRunWithInvalidCommand() diff --git a/tests/MageTest/Command/BuiltIn/LockCommandTest.php b/tests/MageTest/Command/BuiltIn/LockCommandTest.php index e56b63f..84ab390 100644 --- a/tests/MageTest/Command/BuiltIn/LockCommandTest.php +++ b/tests/MageTest/Command/BuiltIn/LockCommandTest.php @@ -173,6 +173,7 @@ class LockCommandTest extends BaseTest } /** + * @covers ::__construct * @covers ::run * @dataProvider lockCommandProvider */ diff --git a/tests/MageTest/Command/BuiltIn/UnlockCommandTest.php b/tests/MageTest/Command/BuiltIn/UnlockCommandTest.php index 1732811..be22134 100644 --- a/tests/MageTest/Command/BuiltIn/UnlockCommandTest.php +++ b/tests/MageTest/Command/BuiltIn/UnlockCommandTest.php @@ -98,6 +98,7 @@ class UnlockCommandTest extends BaseTest } /** + * @covers ::__construct * @covers ::run * @dataProvider runProvider */ diff --git a/tests/MageTest/Command/BuiltIn/VersionCommandTest.php b/tests/MageTest/Command/BuiltIn/VersionCommandTest.php index 6565510..d6a85db 100644 --- a/tests/MageTest/Command/BuiltIn/VersionCommandTest.php +++ b/tests/MageTest/Command/BuiltIn/VersionCommandTest.php @@ -8,16 +8,18 @@ use MageTest\TestHelper\BaseTest; use PHPUnit_Framework_TestCase; /** - * @coversDefaultClass Mage\Command\BuiltIn\VersionCommands + * @coversDefaultClass Mage\Command\BuiltIn\VersionCommand * @group Mage_Command_BuildIn_VersionCommand * @uses Mage\Console * @uses Mage\Console\Colors + * @uses Mage\Command\AbstractCommand */ class VersionCommandTest extends BaseTest { /** * @group 175 - * @covers Mage\Command\BuiltIn\VersionCommand::run() + * @covers ::__construct + * @covers ::run() */ public function testRun() { diff --git a/tests/MageTest/MailerTest.php b/tests/MageTest/MailerTest.php new file mode 100644 index 0000000..8fe4d30 --- /dev/null +++ b/tests/MageTest/MailerTest.php @@ -0,0 +1,61 @@ +setNamespace('Mage') + ->setName('mail') + ->setFunction( + function () use ($mailExecuted){ + return true; + } + ) + ->build(); + + $mockFileGetContents = $builder + ->setNamespace('Mage') + ->setName('file_get_contents') + ->setFunction( + function () { + return true; + } + ) + ->build(); + + $mockMail->enable(); + $mockFileGetContents->enable(); + + $mailer = new Mailer(); + $mailer->setLogFile('test'); + $result = $mailer->send(true); + + $this->assertTrue($result); + + $mockMail->disable(); + $mockFileGetContents->disable(); + + } +} diff --git a/tests/MageTest/TestHelper/BaseTest.php b/tests/MageTest/TestHelper/BaseTest.php index d8db4dc..62f8680 100644 --- a/tests/MageTest/TestHelper/BaseTest.php +++ b/tests/MageTest/TestHelper/BaseTest.php @@ -11,6 +11,7 @@ namespace MageTest\TestHelper; * * @package MageTest\TestHelper * @author Jakub Turek + * @author César Suárez */ abstract class BaseTest extends \PHPUnit_Framework_TestCase { @@ -43,6 +44,20 @@ abstract class BaseTest extends \PHPUnit_Framework_TestCase $configProperty->setValue($object, $value); } + /** + * Calls a protected/private methord + * @param object $object Object instance + * @param string $methodName Name of the method + * @param array $args Arguments for the method + * @return mixed The output of the method + */ + final protected static function callMethod($object, $methodName, array $args) { + $class = new \ReflectionClass($object); + $method = $class->getMethod($methodName); + $method->setAccessible(true); + return $method->invokeArgs($object, $args); + } + /** * Disable logging to log file and turn off colors *