Browse Source

Major overhauling and refactoring of Magallanes Command and Tasks modulairty and workflow.

ADVICE: there is no Backwards Compatibility with custom tasks, those
using the _config instance will be broken or those using the
getEnvironmentName().
1.0
Andrés Montañez 12 years ago
parent
commit
811c83e13a
  1. 7
      Mage/Autoload.php
  2. 39
      Mage/Command/BuiltIn/Add.php
  3. 6
      Mage/Command/BuiltIn/Compile.php
  4. 62
      Mage/Command/BuiltIn/Deploy.php
  5. 3
      Mage/Command/BuiltIn/Init.php
  6. 7
      Mage/Command/BuiltIn/Install.php
  7. 23
      Mage/Command/BuiltIn/Lock.php
  8. 56
      Mage/Command/BuiltIn/Releases.php
  9. 16
      Mage/Command/BuiltIn/Unlock.php
  10. 15
      Mage/Command/BuiltIn/Update.php
  11. 3
      Mage/Command/BuiltIn/Upgrade.php
  12. 10
      Mage/Command/BuiltIn/Version.php
  13. 21
      Mage/Command/CommandAbstract.php
  14. 37
      Mage/Command/Factory.php
  15. 4
      Mage/Command/RequiresEnvironment.php
  16. 414
      Mage/Config.php
  17. 255
      Mage/Console.php
  18. 14
      Mage/Task/BuiltIn/Deployment/Releases.php
  19. 28
      Mage/Task/BuiltIn/Deployment/Rsync.php
  20. 22
      Mage/Task/BuiltIn/Releases/List.php
  21. 23
      Mage/Task/BuiltIn/Releases/Rollback.php
  22. 4
      Mage/Task/BuiltIn/Scm/Clone.php
  23. 2
      Mage/Task/BuiltIn/Scm/RemoveClone.php
  24. 10
      Mage/Task/BuiltIn/Scm/Update.php
  25. 4
      Mage/Task/Releases/SkipOnOverride.php
  26. 5
      Mage/Task/TaskAbstract.php
  27. 31
      bin/mage.php
  28. 59
      docs/commands.txt
  29. 12
      docs/example-config/.mage/config/environment/staging.yml

7
Mage/Autoload.php

@ -8,6 +8,13 @@ class Mage_Autoload
require_once $classFile; require_once $classFile;
} }
public static function isLoadable($className)
{
$baseDir = dirname(dirname(__FILE__));
$classFile = $baseDir . '/' . str_replace('_', '/', $className . '.php');
return (file_exists($classFile) && is_readable($classFile));
}
public static function loadUserTask($taskName) public static function loadUserTask($taskName)
{ {
$classFile = '.mage/tasks/' . ucfirst($taskName) . '.php'; $classFile = '.mage/tasks/' . ucfirst($taskName) . '.php';

39
Mage/Command/BuiltIn/Add.php

@ -1,17 +1,39 @@
<?php <?php
class Mage_Task_Add class Mage_Command_BuiltIn_Add
extends Mage_Command_CommandAbstract
{ {
public function environment($environmentName, $withRelases = false) public function run()
{ {
$environmentName = strtolower($environmentName); $subCommand = $this->getConfig()->getArgument(1);
try {
switch ($subCommand) {
case 'environment':
$this->_environment();
break;
}
} catch (Exception $e) {
Mage_Console::output('<red>' . $e->getMessage() . '</red>', 1, 2);
}
}
private function _environment()
{
$withReleases = $this->getConfig()->getParameter('enableReleases', false);
$environmentName = strtolower($this->getConfig()->getParameter('name'));
if ($environmentName == '') {
throw new Exception('You must specify a name for the environment.');
}
$environmentConfigFile = '.mage/config/environment/' . $environmentName . '.yml'; $environmentConfigFile = '.mage/config/environment/' . $environmentName . '.yml';
if (file_exists($environmentConfigFile)) {
throw new Exception('The environment already exists.');
}
Mage_Console::output('Adding new environment: <dark_gray>' . $environmentName . '</dark_gray>'); Mage_Console::output('Adding new environment: <dark_gray>' . $environmentName . '</dark_gray>');
// Check if there is already an environment with the same name
if (file_exists($environmentConfigFile)) {
Mage_Console::output('<light_red>Error!!</light_red> Already exists an environment called <dark_gray>' . $environmentName . '</dark_gray>', 1, 2);
} else {
$releasesConfig = 'releases:' . PHP_EOL $releasesConfig = 'releases:' . PHP_EOL
. ' enabled: true' . PHP_EOL . ' enabled: true' . PHP_EOL
. ' max: 10' . PHP_EOL . ' max: 10' . PHP_EOL
@ -24,7 +46,7 @@ class Mage_Task_Add
. ' from: ./' . PHP_EOL . ' from: ./' . PHP_EOL
. ' to: /var/www/vhosts/example.com/www' . PHP_EOL . ' to: /var/www/vhosts/example.com/www' . PHP_EOL
. ' excludes:' . PHP_EOL . ' excludes:' . PHP_EOL
. ($withRelases ? $releasesConfig : '') . ($withReleases ? $releasesConfig : '')
. 'hosts:' . PHP_EOL . 'hosts:' . PHP_EOL
. 'tasks:' . PHP_EOL . 'tasks:' . PHP_EOL
. ' pre-deploy:' . PHP_EOL . ' pre-deploy:' . PHP_EOL
@ -40,5 +62,4 @@ class Mage_Task_Add
Mage_Console::output('<light_red>Error!!</light_red> Unable to create config file for environment called <dark_gray>' . $environmentName . '</dark_gray>', 1, 2); Mage_Console::output('<light_red>Error!!</light_red> Unable to create config file for environment called <dark_gray>' . $environmentName . '</dark_gray>', 1, 2);
} }
} }
}
} }

6
Mage/Command/BuiltIn/Compile.php

@ -1,11 +1,11 @@
<?php <?php
/** /**
* Class Mage_Task_Compile * Class Mage_Command_BuiltIn_Compile
* *
* @author Ismael Ambrosi<ismaambrosi@gmail.com> * @author Ismael Ambrosi<ismaambrosi@gmail.com>
*/ */
class Mage_Task_Compile class Mage_Command_BuiltIn_Compile
extends Mage_Command_CommandAbstract
{ {
/** /**
* @see Mage_Compile::compile() * @see Mage_Compile::compile()

62
Mage/Command/BuiltIn/Deploy.php

@ -1,8 +1,8 @@
<?php <?php
class Mage_Task_Deploy class Mage_Command_BuiltIn_Deploy
extends Mage_Command_CommandAbstract
implements Mage_Command_RequiresEnvironment
{ {
private $_config = null;
private $_releaseId = null;
private $_startTime = null; private $_startTime = null;
private $_startTimeHosts = null; private $_startTimeHosts = null;
private $_endTimeHosts = null; private $_endTimeHosts = null;
@ -13,27 +13,21 @@ class Mage_Task_Deploy
$this->_releaseId = date('YmdHis'); $this->_releaseId = date('YmdHis');
} }
public function run(Mage_Config $config) public function run()
{ {
$this->_startTime = time(); $this->_startTime = time();
$this->_config = $config;
if ($config->getEnvironmentName() == '') { $lockFile = '.mage/' . $this->getConfig()->getEnvironment() . '.lock';
Mage_Console::output('<red>You must specify an environment</red>', 0, 2);
return;
}
$lockFile = '.mage/' . $config->getEnvironmentName() . '.lock';
if (file_exists($lockFile)) { if (file_exists($lockFile)) {
Mage_Console::output('<red>This environment is locked!</red>', 0, 2); Mage_Console::output('<red>This environment is locked!</red>', 1, 2);
return; return;
} }
// Run Pre-Deployment Tasks // Run Pre-Deployment Tasks
$this->_runNonDeploymentTasks('pre-deploy', $config, 'Pre-Deployment'); $this->_runNonDeploymentTasks('pre-deploy', $this->getConfig(), 'Pre-Deployment');
// Run Tasks for Deployment // Run Tasks for Deployment
$hosts = $config->getHosts(); $hosts = $this->getConfig()->getHosts();
if (count($hosts) == 0) { if (count($hosts) == 0) {
Mage_Console::output('<light_purple>Warning!</light_purple> <dark_gray>No hosts defined, skipping deployment tasks.</dark_gray>', 1, 3); Mage_Console::output('<light_purple>Warning!</light_purple> <dark_gray>No hosts defined, skipping deployment tasks.</dark_gray>', 1, 3);
@ -42,20 +36,22 @@ class Mage_Task_Deploy
$this->_startTimeHosts = time(); $this->_startTimeHosts = time();
foreach ($hosts as $host) { foreach ($hosts as $host) {
$this->_hostsCount++; $this->_hostsCount++;
$config->setHost($host); $this->getConfig()->setHost($host);
$tasks = 0; $tasks = 0;
$completedTasks = 0; $completedTasks = 0;
Mage_Console::output('Deploying to <dark_gray>' . $config->getHost() . '</dark_gray>'); Mage_Console::output('Deploying to <dark_gray>' . $this->getConfig()->getHost() . '</dark_gray>');
$tasksToRun = $config->getTasks(); $tasksToRun = $this->getConfig()->getTasks();
array_unshift($tasksToRun, 'deployment/rsync'); array_unshift($tasksToRun, 'deployment/rsync');
if ($config->release('enabled', false) == true) { if ($this->getConfig()->release('enabled', false) == true) {
$config->setReleaseId($this->_releaseId); $this->getConfig()->setReleaseId($this->_releaseId);
array_push($tasksToRun, 'deployment/releases'); array_push($tasksToRun, 'deployment/releases');
} }
$tasksToRun = $tasksToRun + $this->getConfig()->getTasks('post-release');
if (count($tasksToRun) == 0) { if (count($tasksToRun) == 0) {
Mage_Console::output('<light_purple>Warning!</light_purple> <dark_gray>No </dark_gray><light_cyan>Deployment</light_cyan> <dark_gray>tasks defined.</dark_gray>', 2); Mage_Console::output('<light_purple>Warning!</light_purple> <dark_gray>No </dark_gray><light_cyan>Deployment</light_cyan> <dark_gray>tasks defined.</dark_gray>', 2);
Mage_Console::output('Deployment to <dark_gray>' . $config->getHost() . '</dark_gray> skipped!', 1, 3); Mage_Console::output('Deployment to <dark_gray>' . $config->getHost() . '</dark_gray> skipped!', 1, 3);
@ -63,10 +59,17 @@ class Mage_Task_Deploy
} else { } else {
foreach ($tasksToRun as $taskName) { foreach ($tasksToRun as $taskName) {
$tasks++; $tasks++;
$task = Mage_Task_Factory::get($taskName, $config, false, 'deploy'); $task = Mage_Task_Factory::get($taskName, $this->getConfig(), false, 'deploy');
$task->init(); $task->init();
$runTask = true;
Mage_Console::output('Running <purple>' . $task->getName() . '</purple> ... ', 2, false); Mage_Console::output('Running <purple>' . $task->getName() . '</purple> ... ', 2, false);
if (($task instanceOf Mage_Task_Releases_SkipOnOverride) && $this->getConfig()->getParameter('overrideRelease', false)) {
$runTask == false;
}
if ($runTask == true) {
$result = $task->run(); $result = $task->run();
if ($result == true) { if ($result == true) {
@ -75,6 +78,9 @@ class Mage_Task_Deploy
} else { } else {
Mage_Console::output('<red>FAIL</red>', 0); Mage_Console::output('<red>FAIL</red>', 0);
} }
} else {
Mage_Console::output('<yellow>SKIPPED</yellow>', 0);
}
} }
if ($completedTasks == $tasks) { if ($completedTasks == $tasks) {
@ -83,14 +89,14 @@ class Mage_Task_Deploy
$tasksColor = 'red'; $tasksColor = 'red';
} }
Mage_Console::output('Deployment to <dark_gray>' . $config->getHost() . '</dark_gray> compted: <' . $tasksColor . '>' . $completedTasks . '/' . $tasks . '</' . $tasksColor . '> tasks done.', 1, 3); Mage_Console::output('Deployment to <dark_gray>' . $this->getConfig()->getHost() . '</dark_gray> compted: <' . $tasksColor . '>' . $completedTasks . '/' . $tasks . '</' . $tasksColor . '> tasks done.', 1, 3);
} }
} }
$this->_endTimeHosts = time(); $this->_endTimeHosts = time();
} }
// Run Post-Deployment Tasks // Run Post-Deployment Tasks
$this->_runNonDeploymentTasks('post-deploy', $config, 'Post-Deployment'); $this->_runNonDeploymentTasks('post-deploy', $this->getConfig(), 'Post-Deployment');
// Time Information Hosts // Time Information Hosts
if ($this->_hostsCount > 0) { if ($this->_hostsCount > 0) {
@ -106,6 +112,13 @@ class Mage_Task_Deploy
Mage_Console::output('Total time: <dark_gray>' . $timeText . '</dark_gray>.', 1, 2); Mage_Console::output('Total time: <dark_gray>' . $timeText . '</dark_gray>.', 1, 2);
} }
/**
* Execute Pre and Post Deployment Tasks
*
* @param string $stage
* @param Mage_Config $config
* @param string $title
*/
private function _runNonDeploymentTasks($stage, Mage_Config $config, $title) private function _runNonDeploymentTasks($stage, Mage_Config $config, $title)
{ {
$tasksToRun = $config->getTasks($stage); $tasksToRun = $config->getTasks($stage);
@ -156,6 +169,11 @@ class Mage_Task_Deploy
} }
/**
* Humanize Transcurred time
* @param integer $time
* @return string
*/
private function _transcurredTime($time) private function _transcurredTime($time)
{ {
$hours = floor($time / 3600); $hours = floor($time / 3600);

3
Mage/Command/BuiltIn/Init.php

@ -1,5 +1,6 @@
<?php <?php
class Mage_Task_Init class Mage_Command_BuiltIn_Init
extends Mage_Command_CommandAbstract
{ {
public function run() public function run()
{ {

7
Mage/Command/BuiltIn/Install.php

@ -1,7 +1,8 @@
<?php <?php
class Mage_Task_Install class Mage_Command_BuiltIn_Install
extends Mage_Command_CommandAbstract
{ {
public function run () public function run()
{ {
Mage_Console::output('Installing <dark_gray>Magallanes</dark_gray>... ', 1, 0); Mage_Console::output('Installing <dark_gray>Magallanes</dark_gray>... ', 1, 0);
$this->_recursiveCopy('./', '/opt/magallanes-' . MAGALLANES_VERSION); $this->_recursiveCopy('./', '/opt/magallanes-' . MAGALLANES_VERSION);
@ -18,7 +19,7 @@ class Mage_Task_Install
Mage_Console::output('<light_green>Success!</light_green>', 0, 2); Mage_Console::output('<light_green>Success!</light_green>', 0, 2);
} }
private function _recursiveCopy ($from, $to) private function _recursiveCopy($from, $to)
{ {
if (is_dir($from)) { if (is_dir($from)) {
mkdir($to); mkdir($to);

23
Mage/Command/BuiltIn/Lock.php

@ -1,23 +1,14 @@
<?php <?php
class Mage_Task_Lock class Mage_Command_BuiltIn_Lock
extends Mage_Command_CommandAbstract
implements Mage_Command_RequiresEnvironment
{ {
private $_config = null; public function run()
public function run(Mage_Config $config, $unlock = false)
{ {
$this->_config = $config; $lockFile = '.mage/' . $this->getConfig()->getEnvironment() . '.lock';
file_put_contents($lockFile, 'Locked environment at date: ' . date('Y-m-d H:i:s'));
if ($config->getEnvironmentName() == '') {
Mage_Console::output('<red>You must specify an environment</red>', 0, 2);
return;
}
$lockFile = '.mage/' . $config->getEnvironmentName() . '.lock';
if (file_exists($lockFile)) {
@unlink($lockFile);
}
Mage_Console::output('Unlocked deployment to <light_purple>' . $config->getEnvironmentName() . '</light_purple> environment', 1, 2); Mage_Console::output('Locked deployment to <light_purple>' . $this->getConfig()->getEnvironment() . '</light_purple> environment', 1, 2);
} }
} }

56
Mage/Command/BuiltIn/Releases.php

@ -1,67 +1,41 @@
<?php <?php
class Mage_Task_Releases class Mage_Command_BuiltIn_Releases
extends Mage_Command_CommandAbstract
implements Mage_Command_RequiresEnvironment
{ {
private $_config = null;
private $_action = null;
private $_release = null; private $_release = null;
public function setAction($action) public function run()
{ {
$this->_action = $action; $subcommand = $this->getConfig()->getArgument(1);
return $this; $lockFile = '.mage/' . $this->getConfig()->getEnvironment() . '.lock';
} if (file_exists($lockFile) && ($subcommand == 'rollback')) {
public function getAction()
{
return $this->_action;
}
public function setRelease($releaseId)
{
$this->_release = $releaseId;
return $this;
}
public function getRelease()
{
return $this->_release;
}
public function run(Mage_Config $config)
{
$this->_config = $config;
if ($config->getEnvironmentName() == '') {
Mage_Console::output('<red>You must specify an environment</red>', 0, 2);
return;
}
$lockFile = '.mage/' . $config->getEnvironmentName() . '.lock';
if (file_exists($lockFile)) {
Mage_Console::output('<red>This environment is locked!</red>', 0, 2); Mage_Console::output('<red>This environment is locked!</red>', 0, 2);
return; return;
} }
// Run Tasks for Deployment // Run Tasks for Deployment
$hosts = $config->getHosts(); $hosts = $this->getConfig()->getHosts();
if (count($hosts) == 0) { if (count($hosts) == 0) {
Mage_Console::output('<light_purple>Warning!</light_purple> <dark_gray>No hosts defined, unable to get releases.</dark_gray>', 1, 3); Mage_Console::output('<light_purple>Warning!</light_purple> <dark_gray>No hosts defined, unable to get releases.</dark_gray>', 1, 3);
} else { } else {
foreach ($hosts as $host) { foreach ($hosts as $host) {
$config->setHost($host); $this->getConfig()->setHost($host);
switch ($this->getAction()) {
switch ($subcommand) {
case 'list': case 'list':
$task = Mage_Task_Factory::get('releases/list', $config); $task = Mage_Task_Factory::get('releases/list', $this->getConfig());
$task->init(); $task->init();
$result = $task->run(); $result = $task->run();
break; break;
case 'rollback': case 'rollback':
$task = Mage_Task_Factory::get('releases/rollback', $config); $releaseId = $this->getConfig()->getParameter('release', '');
$task = Mage_Task_Factory::get('releases/rollback', $this->getConfig());
$task->init(); $task->init();
$task->setRelease($this->getRelease()); $task->setRelease($releaseId);
$result = $task->run(); $result = $task->run();
break; break;
} }

16
Mage/Command/BuiltIn/Unlock.php

@ -0,0 +1,16 @@
<?php
class Mage_Command_BuiltIn_Unlock
extends Mage_Command_CommandAbstract
implements Mage_Command_RequiresEnvironment
{
public function run()
{
$lockFile = '.mage/' . $this->getConfig()->getEnvironment() . '.lock';
if (file_exists($lockFile)) {
@unlink($lockFile);
}
Mage_Console::output('Unlocked deployment to <light_purple>' . $this->getConfig()->getEnvironment() . '</light_purple> environment', 1, 2);
}
}

15
Mage/Command/BuiltIn/Update.php

@ -1,22 +1,19 @@
<?php <?php
class Mage_Task_Update class Mage_Command_BuiltIn_Update
extends Mage_Command_CommandAbstract
{ {
private $_config = null; public function run()
public function run(Mage_Config $config)
{ {
$this->_config = $config; $task = Mage_Task_Factory::get('scm/update', $this->getConfig());
$task = Mage_Task_Factory::get('scm/update', $config);
$task->init(); $task->init();
Mage_Console::output('Updating application via ' . $task->getName() . ' ... ', 1, 0); Mage_Console::output('Updating application via ' . $task->getName() . ' ... ', 1, 0);
$result = $task->run(); $result = $task->run();
if ($result == true) { if ($result == true) {
Mage_Console::output('OK' . PHP_EOL, 0); Mage_Console::output('<green>OK</green>' . PHP_EOL, 0);
} else { } else {
Mage_Console::output('FAIL' . PHP_EOL, 0); Mage_Console::output('<red>FAIL</red>' . PHP_EOL, 0);
} }
} }

3
Mage/Command/BuiltIn/Upgrade.php

@ -1,5 +1,6 @@
<?php <?php
class Mage_Task_Upgrade class Mage_Command_BuiltIn_Upgrade
extends Mage_Command_CommandAbstract
{ {
const DOWNLOAD = 'https://github.com/andres-montanez/Magallanes/tarball/stable'; const DOWNLOAD = 'https://github.com/andres-montanez/Magallanes/tarball/stable';

10
Mage/Command/BuiltIn/Version.php

@ -0,0 +1,10 @@
<?php
class Mage_Command_BuiltIn_Version
extends Mage_Command_CommandAbstract
{
public function run()
{
Mage_Console::output('Running <blue>Magallanes</blue> version <dark_gray>' . MAGALLANES_VERSION .'</dark_gray>', 0, 2);
}
}

21
Mage/Command/CommandAbstract.php

@ -0,0 +1,21 @@
<?php
abstract class Mage_Command_CommandAbstract
{
protected $_config = null;
public abstract function run();
public function setConfig(Mage_Config $config)
{
$this->_config = $config;
}
/**
*
* @return Mage_Config
*/
public function getConfig()
{
return $this->_config;
}
}

37
Mage/Command/Factory.php

@ -0,0 +1,37 @@
<?php
class Mage_Command_Factory
{
/**
*
*
* @param string $commandName
* @param Mage_Config $config
* @return Mage_Command_CommandAbstract
*/
public static function get($commandName, Mage_Config $config)
{
$instance = null;
$commandName = ucwords(str_replace('-', ' ', $commandName));
$commandName = str_replace(' ', '', $commandName);
// if (strpos($commandName, '/') === false) {
// Mage_Autoload::loadUserTask($taskName);
// $className = 'Task_' . ucfirst($taskName);
// $instance = new $className($taskConfig, $inRollback, $stage);
// } else {
$commandName = str_replace(' ', '_', ucwords(str_replace('/', ' ', $commandName)));
$className = 'Mage_Command_BuiltIn_' . $commandName;
if (Mage_Autoload::isLoadable($className)) {
$instance = new $className;
$instance->setConfig($config);
} else {
throw new Exception('Command not found.');
}
// }
assert($instance instanceOf Mage_Command_CommandAbstract);
return $instance;
}
}

4
Mage/Command/RequiresEnvironment.php

@ -0,0 +1,4 @@
<?php
interface Mage_Command_RequiresEnvironment
{
}

414
Mage/Config.php

@ -1,88 +1,132 @@
<?php <?php
class Mage_Config class Mage_Config
{ {
private $_environmentName = null; private $_arguments = array();
private $_environment = null; private $_parameters = array();
private $_scm = null; private $_environment = false;
private $_general = null;
private $_host = null; private $_host = null;
private $_releaseId = null; private $_releaseId = null;
private $_config = array(
public function reloadConfig() 'general' => array(),
'scm' => array(),
'environment' => array(),
);
/**
* Load the Configuration and parses the Arguments
*
* @param array $arguments
*/
public function load($arguments)
{ {
$this->loadGeneral(); $this->_parse($arguments);
$this->loadSCM(); $this->_loadGeneral();
$this->loadEnvironment($this->getEnvironmentName()); $this->_loadSCM();
} $this->_loadEnvironment();
}
public function loadEnvironment($environment)
/**
* Return the invocation argument based on a position
* 0 = Invoked Command Name
*
* @param integer $position
* @return mixed
*/
public function getArgument($position = 0)
{ {
if (($environment != '') && file_exists('.mage/config/environment/' . $environment . '.yml')) { if (isset($this->_arguments[$position])) {
$this->_environment = spyc_load_file('.mage/config/environment/' . $environment . '.yml'); return $this->_arguments[$position];
$this->_environmentName = $environment; } else {
// Create temporal directory for clone
if (isset($this->_environment['deployment']['source']) && is_array($this->_environment['deployment']['source'])) {
if (trim($this->_environment['deployment']['source']['temporal']) == '') {
$this->_environment['deployment']['source']['temporal'] = '/tmp';
}
$newTemporal = rtrim($this->_environment['deployment']['source']['temporal'], '/')
. '/' . md5(microtime()) . '/';
$this->_environment['deployment']['source']['temporal'] = $newTemporal;
}
return true;
} else if (($environment != '') && !file_exists('.mage/config/environment/' . $environment . '.yml')) {
return false; return false;
} }
}
return true; /**
* Returns all the invocation arguments
*
* @return array
*/
public function getArguments()
{
return $this->_arguments;
} }
public function loadSCM() /**
* Return the a parameter
*
* @param string $name
* @return mixed
*/
public function getParameter($name, $default = null)
{ {
if (file_exists('.mage/config/scm.yml')) { if (isset($this->_parameters[$name])) {
$this->_scm = spyc_load_file('.mage/config/scm.yml'); return $this->_parameters[$name];
} else {
return $default;
} }
} }
public function loadGeneral() /**
* Returns all the invocation arguments
*
* @return array
*/
public function getParameters()
{ {
if (file_exists('.mage/config/general.yml')) { return $this->_parameters;
$this->_general = spyc_load_file('.mage/config/general.yml');
}
} }
/**
* Returns the Current environment
*
* @return mixed
*/
public function getEnvironment() public function getEnvironment()
{ {
return $this->_environment; return $this->_environment;
} }
public function getEnvironmentName() /**
* Reloads the configuration
*/
public function reload()
{ {
return $this->_environmentName; $this->_loadGeneral();
$this->_loadSCM();
$this->_loadEnvironment();
} }
public function getSCM() /**
* Get the Tasks to execute
*
* @param string $stage
* @return array
*/
public function getTasks($stage = 'on-deploy')
{ {
return $this->_scm; $tasks = array();
$config = $this->_getEnvironmentOption('tasks', array());
if (isset($config[$stage])) {
$tasks = ($config[$stage] ? (array) $config[$stage] : array());
} }
public function getGlobal() return $tasks;
{
return $this->_global;
} }
/**
* Get the current Hosts to deploy
*
* @return array
*/
public function getHosts() public function getHosts()
{ {
$config = $this->getEnvironment();
$hosts = array(); $hosts = array();
if (isset($config['hosts'])) { if (isset($this->_config['environment']['hosts'])) {
if (is_array($config['hosts'])) { if (is_array($this->_config['environment']['hosts'])) {
$hosts = (array) $config['hosts']; $hosts = (array) $this->_config['environment']['hosts'];
} else if (is_string($config['hosts'])) { } else if (is_string($this->_config['environment']['hosts']) && file_exists($this->_config['environment']['hosts']) && is_readable($this->_config['environment']['hosts'])) {
$fileContent = fopen($config['hosts'], 'r'); $fileContent = fopen($this->_config['environment']['hosts'], 'r');
while (($host = fgets($fileContent)) == true) { while (($host = fgets($fileContent)) == true) {
$host = trim($host); $host = trim($host);
if ($host != '') { if ($host != '') {
@ -95,18 +139,34 @@ class Mage_Config
return $hosts; return $hosts;
} }
/**
* Set the current host
*
* @param string $host
* @return Mage_Config
*/
public function setHost($host) public function setHost($host)
{ {
$this->_host = $host; $this->_host = $host;
return $this; return $this;
} }
/**
* Get the current host name
*
* @return string
*/
public function getHostName() public function getHostName()
{ {
$info = explode(':', $this->_host); $info = explode(':', $this->_host);
return $info[0]; return $info[0];
} }
/**
* Get the current Host Port
*
* @return unknown
*/
public function getHostPort() public function getHostPort()
{ {
$info = explode(':', $this->_host); $info = explode(':', $this->_host);
@ -114,144 +174,222 @@ class Mage_Config
return $info[1]; return $info[1];
} }
/**
* Get the current Host
*
* @return string
*/
public function getHost() public function getHost()
{ {
return $this->_host; return $this->_host;
} }
public function setReleaseId($id) /**
{ * Gets General Configuration
$this->_releaseId = $id; *
return $this; * @param string $option
} * @param string $default
* @return mixed
public function getReleaseId() */
{ public function general($option, $default = false)
return $this->_releaseId;
}
public function getTasks($stage = 'on-deploy')
{ {
switch ($stage) { $config = $this->_config['general'];
case 'pre-deploy': if (isset($config[$option])) {
$type = 'tasks'; if (is_array($default) && ($config[$option] == '')) {
$stage = 'pre-deploy'; return $default;
break; } else {
return $config[$option];
case 'post-deploy':
$type = 'tasks';
$stage = 'post-deploy';
break;
case 'post-release':
$type = 'releases';
$stage = 'post-release';
break;
case 'on-deploy':
default:
$type = 'tasks';
$stage = 'on-deploy';
break;
} }
} else {
$tasks = array(); return $default;
$config = $this->getEnvironment();
if (isset($config[$type]) && isset($config[$type][$stage])) {
$tasks = ($config[$type][$stage] ? (array) $config[$type][$stage] : array());
} }
return $tasks;
} }
public function getConfig($host = false) /**
* Gets SCM Configuration
*
* @param string $option
* @param string $default
* @return mixed
*/
public function scm($option, $default = false)
{ {
$taskConfig = array(); $config = $this->_config['scm'];
$taskConfig['deploy'] = $this->getEnvironment(); if (isset($config[$option])) {
$taskConfig['deploy']['host'] = $host; if (is_array($default) && ($config[$option] == '')) {
$taskConfig['scm'] = $this->getSCM(); return $default;
} else {
unset($taskConfig['deploy']['tasks']); return $config[$option];
unset($taskConfig['deploy']['hosts']); }
} else {
return $taskConfig; return $default;
} }
public function setFrom($from)
{
$this->_environment['deployment']['from'] = $from;
return $this;
} }
/**
* Get deployment configuration
*
* @param string $option
* @param string $default
* @return string
*/
public function deployment($option, $default = false) public function deployment($option, $default = false)
{ {
$options = $this->getEnvironment(); $config = $this->_getEnvironmentOption('deployment', array());
if (isset($options['deployment'][$option])) { if (isset($config[$option])) {
if (is_array($default) && ($options['deployment'][$option] == '')) { if (is_array($default) && ($config[$option] == '')) {
return $default; return $default;
} else { } else {
return $options['deployment'][$option]; return $config[$option];
} }
} else { } else {
return $default; return $default;
} }
} }
/**
* Returns Releaseing Options
*
* @param string $option
* @param string $default
* @return mixed
*/
public function release($option, $default = false) public function release($option, $default = false)
{ {
$options = $this->getEnvironment(); $config = $this->_getEnvironmentOption('releases', array());
if (isset($options['releases'][$option])) { if (isset($config[$option])) {
if (is_array($default) && ($options['releases'][$option] == '')) { if (is_array($default) && ($config[$option] == '')) {
return $default; return $default;
} else { } else {
return $options['releases'][$option]; return $config[$option];
} }
} else { } else {
return $default; return $default;
} }
} }
public function scm($option, $default = false) /**
* Set From Deployment Path
*
* @param string $from
* @return Mage_Config
*/
public function setFrom($from)
{ {
$options = $this->_scm; $this->_config['environment']['deployment']['from'] = $from;
if (isset($options[$option])) { return $this;
if (is_array($default) && ($options[$option] == '')) {
return $default;
} else {
return $options[$option];
} }
return $options[$option];
} else { /**
return $default; * Sets the Current Release ID
*
* @param integer $id
* @return Mage_Config
*/
public function setReleaseId($id)
{
$this->_releaseId = $id;
return $this;
} }
/**
* Gets the Current Release ID
*
* @return integer
*/
public function getReleaseId()
{
return $this->_releaseId;
} }
public function general($option, $default = false) /**
* Parse the Command Line options
* @return boolean
*/
private function _parse($arguments)
{ {
$options = $this->_general; foreach ($arguments as $argument) {
if (isset($options[$option])) { if (preg_match('/to:[\w]+/i', $argument)) {
if (is_array($default) && ($options[$option] == '')) { $this->_environment = str_replace('to:', '', $argument);
return $default;
} else { } else if (preg_match('/--[\w]+/i', $argument)) {
return $options[$option]; $optionValue = explode('=', substr($argument, 2));
if (count($optionValue) == 1) {
$this->_parameters[$optionValue[0]] = true;
} else if (count($optionValue) == 2) {
$this->_parameters[$optionValue[0]] = $optionValue[1];
} }
} else { } else {
return $default; $this->_arguments[] = $argument;
}
} }
} }
public function mail($option, $default = false) /**
* Loads the General Configuration
*/
private function _loadGeneral()
{ {
$options = $this->_general; if (file_exists('.mage/config/general.yml')) {
if (isset($options['mail'][$option])) { $this->_config['general'] = spyc_load_file('.mage/config/general.yml');
if (is_array($default) && ($options['mail'][$option] == '')) { }
return $default; }
} else {
return $options['mail'][$option]; /**
* Loads the SCM Configuration
*/
private function _loadSCM()
{
if (file_exists('.mage/config/scm.yml')) {
$this->_config['scm'] = spyc_load_file('.mage/config/scm.yml');
} }
}
/**
* Loads the Environment configuration
*
* @throws Exception
* @return boolean
*/
private function _loadEnvironment()
{
$environment = $this->getEnvironment();
if (($environment != false) && file_exists('.mage/config/environment/' . $environment . '.yml')) {
$this->_config['environment'] = spyc_load_file('.mage/config/environment/' . $environment . '.yml');
// Create temporal directory for clone
if (isset($this->_config['environment']['deployment']['source']) && is_array($this->_config['environment']['deployment']['source'])) {
if (trim($this->_config['environment']['deployment']['source']['temporal']) == '') {
$this->_config['environment']['deployment']['source']['temporal'] = '/tmp';
}
$newTemporal = rtrim($this->_config['environment']['deployment']['source']['temporal'], '/')
. '/' . md5(microtime()) . '/';
$this->_config['environment']['deployment']['source']['temporal'] = $newTemporal;
}
return true;
} else if (($environment != '') && !file_exists('.mage/config/environment/' . $environment . '.yml')) {
throw new Exception('Environment does not exists.');
}
return false;
}
/**
* Get Environment root option
*
* @param string $option
* @param mixed $default
* @return mixed
*/
private function _getEnvironmentOption($option, $default = array())
{
$config = $this->_config['environment'];
if (isset($config[$option])) {
return $config[$option];
} else { } else {
return $default; return $default;
} }
} }
} }

255
Mage/Console.php

@ -1,95 +1,77 @@
<?php <?php
class Mage_Console class Mage_Console
{ {
private $_args = array();
private $_action = null;
private static $_actionOptions = array();
private $_environment = null;
private static $_log = null; private static $_log = null;
private static $_logEnabled = true; private static $_logEnabled = true;
private static $_screenBuffer = ''; private static $_screenBuffer = '';
private static $_commandsOutput = ''; private static $_commandsOutput = '';
public function setArgs($args) /**
* Runns a Magallanes Command
* @throws Exception
*/
public function run($arguments)
{ {
$this->_args = $args; $configError = false;
array_shift($this->_args); try {
} // Load Config
$config = new Mage_Config;
$config->load($arguments);
$configLoadedOk = true;
public function parse() } catch (Exception $e) {
{ $configError = $e->getMessage();
if (count($this->_args) == 0) {
return false;
} }
if ($this->_args[0] == 'deploy') { // Command Option
$this->_action = 'deploy'; $commandName = $config->getArgument(0);
} else if ($this->_args[0] == 'releases') {
$this->_action = 'releases';
} else if ($this->_args[0] == 'update') {
$this->_action = 'update';
} else if ($this->_args[0] == 'compile') {
$this->_action = 'compile';
} else if ($this->_args[0] == 'add') {
$this->_action = 'add';
} else if ($this->_args[0] == 'install') {
$this->_action = 'install';
} else if ($this->_args[0] == 'upgrade') {
$this->_action = 'upgrade';
} else if ($this->_args[0] == 'version') {
$this->_action = 'version';
} else if ($this->_args[0] == 'init') { // Logging
$this->_action = 'init'; $showGrettings = true;
if (in_array($commandName, array('install', 'upgrade', 'version'))) {
} else if ($this->_args[0] == 'lock') { self::$_logEnabled = false;
$this->_action = 'lock'; $showGrettings = false;
} else {
self::$_logEnabled = $config->general('logging', false);
}
} else if ($this->_args[0] == 'unlock') { // Grettings
$this->_action = 'unlock'; if ($showGrettings) {
Mage_Console::output('Starting <blue>Magallanes</blue>', 0, 2);
} }
foreach ($this->_args as $argument) { // Run Command
if (preg_match('/to:[\w]+/i', $argument)) { if ($configError !== false) {
$this->_environment = str_replace('to:', '', $argument); Mage_Console::output('<red>' . $configError . '</red>', 1, 2);
} else if (preg_match('/--[\w]+/i', $argument)) { } else {
$optionValue = explode('=', substr($argument, 2)); try {
if (count($optionValue) == 1) { $command = Mage_Command_Factory::get($commandName, $config);
self::$_actionOptions[$optionValue[0]] = true;
} else if (count($optionValue) == 2) { if ($command instanceOf Mage_Command_RequiresEnvironment) {
self::$_actionOptions[$optionValue[0]] = $optionValue[1]; if ($config->getEnvironment() == false) {
} throw new Exception('You must specify an environment for this command.');
}
} }
} }
$command->run();
public function getAction() } catch (Exception $e) {
{ Mage_Console::output('<red>' . $e->getMessage() . '</red>', 1, 2);
return $this->_action;
} }
public function getEnvironment()
{
return $this->_environment;
} }
public static function getActionOption($name, $default = false) if ($showGrettings) {
{ Mage_Console::output('Finished <blue>Magallanes</blue>', 0, 2);
if (isset(self::$_actionOptions[$name])) {
return self::$_actionOptions[$name];
} else {
return $default;
} }
} }
/**
* Outputs a message to the user screen
*
* @param string $message
* @param integer $tabs
* @param integer $newLine
*/
public static function output($message, $tabs = 1, $newLine = 1) public static function output($message, $tabs = 1, $newLine = 1)
{ {
self::log(strip_tags($message)); self::log(strip_tags($message));
@ -105,6 +87,13 @@ class Mage_Console
echo $output; echo $output;
} }
/**
* Executes a Command on the Shell
*
* @param string $command
* @param string $output
* @return boolean
*/
public static function executeCommand($command, &$output = null) public static function executeCommand($command, &$output = null)
{ {
self::log('---------------------------------'); self::log('---------------------------------');
@ -126,134 +115,12 @@ class Mage_Console
return !$return; return !$return;
} }
public function run() /**
{ * Log a message to the logfile.
// Load Config *
$config = new Mage_Config; * @param string $message
$config->loadGeneral(); * @param boolean $continuation
$environmentOk = $config->loadEnvironment($this->getEnvironment()); */
$config->loadSCM();
// Logging
$showGrettings = true;
if (in_array($this->getAction(), array('install', 'upgrade', 'version'))) {
self::$_logEnabled = false;
$showGrettings = false;
} else {
self::$_logEnabled = $config->general('logging', false);
}
// Grettings
if ($showGrettings) {
Mage_Console::output('Starting <blue>Magallanes</blue>', 0, 2);
}
if (!$environmentOk) {
Mage_Console::output('<red>You have selected an invalid environment</red>', 0, 2);
} else {
switch ($this->getAction()) {
case 'deploy':
$task = new Mage_Task_Deploy;
$task->run($config);
break;
case 'releases':
$task = new Mage_Task_Releases;
if (!isset($this->_args[1])) {
Mage_Console::output('<red>You must indicate a task</red>', 0, 2);
break;
}
if ($this->_args[1] == 'list') {
$task->setAction('list');
} else if ($this->_args[1] == 'rollback') {
if (!isset($this->_args[2])) {
Mage_Console::output('<red>You must indicate a release point</red>', 0, 2);
break;
}
$task->setAction($this->_args[1]);
$task->setRelease($this->_args[2]);
} else {
Mage_Console::output('<red>Invalid Releases task</red>', 0, 2);
break;
}
$task->run($config);
break;
case 'update';
$task = new Mage_Task_Update;
$task->run($config);
break;
case 'compile';
$task = new Mage_Task_Compile;
$task->run($config);
break;
case 'install';
$task = new Mage_Task_Install;
$task->run();
break;
case 'lock';
$task = new Mage_Task_Lock;
$task->run($config);
break;
case 'unlock';
$task = new Mage_Task_Lock;
$task->run($config, true);
break;
case 'upgrade';
$task = new Mage_Task_Upgrade;
$task->run();
break;
case 'init';
$task = new Mage_Task_Init;
$task->run();
break;
case 'add';
switch ($this->_args[1]) {
case 'environment':
if (isset($this->_args[3]) && ($this->_args[3] == '--with-releases')) {
$withRelases = true;
} else {
$withRelases = false;
}
$task = new Mage_Task_Add;
$task->environment($this->_args[2], $withRelases);
break;
}
break;
case 'version';
$this->showVersion();
break;
default:
Mage_Console::output('<red>Invalid action</red>', 0, 2);
break;
}
}
if ($showGrettings) {
Mage_Console::output('Finished <blue>Magallanes</blue>', 0, 2);
}
}
public function showVersion()
{
Mage_Console::output('Running <blue>Magallanes</blue> version <dark_gray>' . MAGALLANES_VERSION .'</dark_gray>', 0, 2);
}
public static function log($message, $continuation = false) public static function log($message, $continuation = false)
{ {
if (self::$_logEnabled) { if (self::$_logEnabled) {

14
Mage/Task/BuiltIn/Deployment/Releases.php

@ -10,15 +10,15 @@ class Mage_Task_BuiltIn_Deployment_Releases
public function run() public function run()
{ {
if ($this->_config->release('enabled', false) == true) { if ($this->getConfig()->release('enabled', false) == true) {
$releasesDirectory = $this->_config->release('directory', 'releases'); $releasesDirectory = $this->getConfig()->release('directory', 'releases');
$symlink = $this->_config->release('symlink', 'current'); $symlink = $this->getConfig()->release('symlink', 'current');
if (substr($symlink, 0, 1) == '/') { if (substr($symlink, 0, 1) == '/') {
$releasesDirectory = rtrim($this->_config->deployment('to'), '/') . '/' . $releasesDirectory; $releasesDirectory = rtrim($this->getConfig()->deployment('to'), '/') . '/' . $releasesDirectory;
} }
$currentCopy = $releasesDirectory . '/' . $this->_config->getReleaseId(); $currentCopy = $releasesDirectory . '/' . $this->getConfig()->getReleaseId();
// Fetch the user and group from base directory // Fetch the user and group from base directory
$userGroup = '33:33'; $userGroup = '33:33';
@ -35,7 +35,7 @@ class Mage_Task_BuiltIn_Deployment_Releases
$result = $this->_runRemoteCommand($command); $result = $this->_runRemoteCommand($command);
// Count Releases // Count Releases
$maxReleases = $this->_config->release('max', false); $maxReleases = $this->getConfig()->release('max', false);
if (($maxReleases !== false) && ($maxReleases > 0)) { if (($maxReleases !== false) && ($maxReleases > 0)) {
$releasesList = ''; $releasesList = '';
$countReleasesFetch = $this->_runRemoteCommand('ls -1 ' . $releasesDirectory, $releasesList); $countReleasesFetch = $this->_runRemoteCommand('ls -1 ' . $releasesDirectory, $releasesList);
@ -44,7 +44,7 @@ class Mage_Task_BuiltIn_Deployment_Releases
if ($releasesList != '') { if ($releasesList != '') {
$releasesList = explode(PHP_EOL, $releasesList); $releasesList = explode(PHP_EOL, $releasesList);
if (count($releasesList) > $maxReleases) { if (count($releasesList) > $maxReleases) {
$releasesToDelete = array_diff($releasesList, array($this->_config->getReleaseId())); $releasesToDelete = array_diff($releasesList, array($this->getConfig()->getReleaseId()));
sort($releasesToDelete); sort($releasesToDelete);
$releasesToDeleteCount = count($releasesToDelete) - $maxReleases; $releasesToDeleteCount = count($releasesToDelete) - $maxReleases;
$releasesToDelete = array_slice($releasesToDelete, 0, $releasesToDeleteCount + 1); $releasesToDelete = array_slice($releasesToDelete, 0, $releasesToDeleteCount + 1);

28
Mage/Task/BuiltIn/Deployment/Rsync.php

@ -5,8 +5,8 @@ class Mage_Task_BuiltIn_Deployment_Rsync
{ {
public function getName() public function getName()
{ {
if ($this->_config->release('enabled', false) == true) { if ($this->getConfig()->release('enabled', false) == true) {
if ($this->getActionOption('overrideRelease', false) == true) { if ($this->getConfig()->getParameter('overrideRelease', false) == true) {
return 'Rsync (with Releases override) [built-in]'; return 'Rsync (with Releases override) [built-in]';
} else { } else {
return 'Rsync (with Releases) [built-in]'; return 'Rsync (with Releases) [built-in]';
@ -18,13 +18,13 @@ class Mage_Task_BuiltIn_Deployment_Rsync
public function run() public function run()
{ {
$overrideRelease = $this->getActionOption('overrideRelease', false); $overrideRelease = $this->getConfig()->getParameter('overrideRelease', false);
if ($overrideRelease == true) { if ($overrideRelease == true) {
$releaseToOverride = false; $releaseToOverride = false;
$resultFetch = $this->_runRemoteCommand('ls -ld current | cut -d\"/\" -f2', $releaseToOverride); $resultFetch = $this->_runRemoteCommand('ls -ld current | cut -d\"/\" -f2', $releaseToOverride);
if (is_numeric($releaseToOverride)) { if (is_numeric($releaseToOverride)) {
$this->_config->setReleaseId($releaseToOverride); $this->getConfig()->setReleaseId($releaseToOverride);
} }
} }
@ -36,24 +36,24 @@ class Mage_Task_BuiltIn_Deployment_Rsync
); );
// Look for User Excludes // Look for User Excludes
$userExcludes = $this->_config->deployment('excludes', array()); $userExcludes = $this->getConfig()->deployment('excludes', array());
// If we are working with releases // If we are working with releases
$deployToDirectory = $this->_config->deployment('to'); $deployToDirectory = $this->getConfig()->deployment('to');
if ($this->_config->release('enabled', false) == true) { if ($this->getConfig()->release('enabled', false) == true) {
$releasesDirectory = $this->_config->release('directory', 'releases'); $releasesDirectory = $this->getConfig()->release('directory', 'releases');
$deployToDirectory = rtrim($this->_config->deployment('to'), '/') $deployToDirectory = rtrim($this->getConfig()->deployment('to'), '/')
. '/' . $releasesDirectory . '/' . $releasesDirectory
. '/' . $this->_config->getReleaseId(); . '/' . $this->getConfig()->getReleaseId();
$this->_runRemoteCommand('mkdir -p ' . $releasesDirectory . '/' . $this->_config->getReleaseId()); $this->_runRemoteCommand('mkdir -p ' . $releasesDirectory . '/' . $this->getConfig()->getReleaseId());
} }
$command = 'rsync -avz ' $command = 'rsync -avz '
. '--rsh="ssh -p' . $this->_config->getHostPort() . '" ' . '--rsh="ssh -p' . $this->getConfig()->getHostPort() . '" '
. $this->_excludes(array_merge($excludes, $userExcludes)) . ' ' . $this->_excludes(array_merge($excludes, $userExcludes)) . ' '
. $this->_config->deployment('from') . ' ' . $this->getConfig()->deployment('from') . ' '
. $this->_config->deployment('user') . '@' . $this->_config->getHostName() . ':' . $deployToDirectory; . $this->getConfig()->deployment('user') . '@' . $this->getConfig()->getHostName() . ':' . $deployToDirectory;
$result = $this->_runLocalCommand($command); $result = $this->_runLocalCommand($command);

22
Mage/Task/BuiltIn/Releases/List.php

@ -10,16 +10,22 @@ class Mage_Task_BuiltIn_Releases_List
public function run() public function run()
{ {
if ($this->_config->release('enabled', false) == true) { if ($this->getConfig()->release('enabled', false) == true) {
$releasesDirectory = $this->_config->release('directory', 'releases'); $releasesDirectory = $this->getConfig()->release('directory', 'releases');
$symlink = $this->_config->release('symlink', 'current'); $symlink = $this->getConfig()->release('symlink', 'current');
Mage_Console::output('Releases available on <dark_gray>' . $this->_config->getHost() . '</dark_gray>'); Mage_Console::output('Releases available on <dark_gray>' . $this->getConfig()->getHost() . '</dark_gray>');
// Get Releases
$output = ''; $output = '';
$result = $this->_runRemoteCommand('ls -1 ' . $releasesDirectory, $output); $result = $this->_runRemoteCommand('ls -1 ' . $releasesDirectory, $output);
$releases = ($output == '') ? array() : explode(PHP_EOL, $output); $releases = ($output == '') ? array() : explode(PHP_EOL, $output);
// Get Current
$result = $this->_runRemoteCommand('ls -l ' . $symlink, $output);
$currentRelease = explode('/', $output);
$currentRelease = trim(array_pop($currentRelease));
if (count($releases) == 0) { if (count($releases) == 0) {
Mage_Console::output('<dark_gray>No releases available</dark_gray> ... ', 2); Mage_Console::output('<dark_gray>No releases available</dark_gray> ... ', 2);
} else { } else {
@ -27,6 +33,7 @@ class Mage_Task_BuiltIn_Releases_List
$releases = array_slice($releases, 0, 10); $releases = array_slice($releases, 0, 10);
foreach ($releases as $releaseIndex => $release) { foreach ($releases as $releaseIndex => $release) {
$release = trim($release);
$releaseIndex = str_pad($releaseIndex * -1, 2, ' ', STR_PAD_LEFT); $releaseIndex = str_pad($releaseIndex * -1, 2, ' ', STR_PAD_LEFT);
$releaseDate = $release[0] . $release[1] . $release[2] .$release[3] $releaseDate = $release[0] . $release[1] . $release[2] .$release[3]
. '-' . '-'
@ -40,10 +47,15 @@ class Mage_Task_BuiltIn_Releases_List
. ':' . ':'
. $release[12] . $release[13]; . $release[12] . $release[13];
$isCurrent = '';
if ($currentRelease == $release) {
$isCurrent = ' <- current';
}
Mage_Console::output( Mage_Console::output(
'Release: <purple>' . $release . '</purple> ' 'Release: <purple>' . $release . '</purple> '
. '- Date: <dark_gray>' . $releaseDate . '</dark_gray> ' . '- Date: <dark_gray>' . $releaseDate . '</dark_gray> '
. '- Index: <dark_gray>' . $releaseIndex . '</dark_gray>', 2); . '- Index: <dark_gray>' . $releaseIndex . '</dark_gray>' . $isCurrent, 2);
} }
} }

23
Mage/Task/BuiltIn/Releases/Rollback.php

@ -23,16 +23,16 @@ class Mage_Task_BuiltIn_Releases_Rollback
public function run() public function run()
{ {
if ($this->_config->release('enabled', false) == true) { if ($this->getConfig()->release('enabled', false) == true) {
$releasesDirectory = $this->_config->release('directory', 'releases'); $releasesDirectory = $this->getConfig()->release('directory', 'releases');
$symlink = $this->_config->release('symlink', 'current'); $symlink = $this->getConfig()->release('symlink', 'current');
$output = ''; $output = '';
$result = $this->_runRemoteCommand('ls -1 ' . $releasesDirectory, $output); $result = $this->_runRemoteCommand('ls -1 ' . $releasesDirectory, $output);
$releases = ($output == '') ? array() : explode(PHP_EOL, $output); $releases = ($output == '') ? array() : explode(PHP_EOL, $output);
if (count($releases) == 0) { if (count($releases) == 0) {
Mage_Console::output('Release are not available for <dark_gray>' . $this->_config->getHost() . '</dark_gray> ... <red>FAIL</red>'); Mage_Console::output('Release are not available for <dark_gray>' . $this->getConfig()->getHost() . '</dark_gray> ... <red>FAIL</red>');
} else { } else {
rsort($releases); rsort($releases);
@ -40,6 +40,7 @@ class Mage_Task_BuiltIn_Releases_Rollback
$releaseIsAvailable = false; $releaseIsAvailable = false;
if ($this->getRelease() == '') { if ($this->getRelease() == '') {
$releaseId = $releases[0]; $releaseId = $releases[0];
$releaseIsAvailable = true;
} else if ($this->getRelease() <= 0) { } else if ($this->getRelease() <= 0) {
$index = $this->getRelease() * -1; $index = $this->getRelease() * -1;
@ -55,25 +56,25 @@ class Mage_Task_BuiltIn_Releases_Rollback
} }
if (!$releaseIsAvailable) { if (!$releaseIsAvailable) {
Mage_Console::output('Release <dark_gray>' . $this->getRelease() . '</dark_gray> is invalid or unavailable for <dark_gray>' . $this->_config->getHost() . '</dark_gray> ... <red>FAIL</red>'); Mage_Console::output('Release <dark_gray>' . $this->getRelease() . '</dark_gray> is invalid or unavailable for <dark_gray>' . $this->getConfig()->getHost() . '</dark_gray> ... <red>FAIL</red>');
} else { } else {
Mage_Console::output('Rollback release on <dark_gray>' . $this->_config->getHost() . '</dark_gray>'); Mage_Console::output('Rollback release on <dark_gray>' . $this->getConfig()->getHost() . '</dark_gray>');
$rollbackTo = $releasesDirectory . '/' . $releaseId; $rollbackTo = $releasesDirectory . '/' . $releaseId;
// Tasks // Tasks
$tasks = 1; $tasks = 1;
$completedTasks = 0; $completedTasks = 0;
$tasksToRun = $this->_config->getTasks(); $tasksToRun = $this->getConfig()->getTasks();
$this->_config->setReleaseId($releaseId); $this->getConfig()->setReleaseId($releaseId);
if (count($tasksToRun) == 0) { if (count($tasksToRun) == 0) {
Mage_Console::output('<light_purple>Warning!</light_purple> <dark_gray>No </dark_gray><light_cyan>Deployment</light_cyan> <dark_gray>tasks defined.</dark_gray>', 2); Mage_Console::output('<light_purple>Warning!</light_purple> <dark_gray>No </dark_gray><light_cyan>Deployment</light_cyan> <dark_gray>tasks defined.</dark_gray>', 2);
Mage_Console::output('Deployment to <dark_gray>' . $this->_config->getHost() . '</dark_gray> skipped!', 1, 3); Mage_Console::output('Deployment to <dark_gray>' . $this->getConfig()->getHost() . '</dark_gray> skipped!', 1, 3);
} else { } else {
foreach ($tasksToRun as $taskName) { foreach ($tasksToRun as $taskName) {
$task = Mage_Task_Factory::get($taskName, $this->_config, true, 'deploy'); $task = Mage_Task_Factory::get($taskName, $this->getConfig(), true, 'deploy');
$task->init(); $task->init();
Mage_Console::output('Running <purple>' . $task->getName() . '</purple> ... ', 2, false); Mage_Console::output('Running <purple>' . $task->getName() . '</purple> ... ', 2, false);
@ -118,7 +119,7 @@ class Mage_Task_BuiltIn_Releases_Rollback
$tasksColor = 'red'; $tasksColor = 'red';
} }
Mage_Console::output('Release rollback on <dark_gray>' . $this->_config->getHost() . '</dark_gray> compted: <' . $tasksColor . '>' . $completedTasks . '/' . $tasks . '</' . $tasksColor . '> tasks done.', 1, 3); Mage_Console::output('Release rollback on <dark_gray>' . $this->getConfig()->getHost() . '</dark_gray> compted: <' . $tasksColor . '>' . $completedTasks . '/' . $tasks . '</' . $tasksColor . '> tasks done.', 1, 3);
} }
} }

4
Mage/Task/BuiltIn/Scm/Clone.php

@ -12,7 +12,7 @@ class Mage_Task_BuiltIn_Scm_Clone
public function init() public function init()
{ {
$this->_source = $this->_config->deployment('source'); $this->_source = $this->getConfig()->deployment('source');
switch ($this->_source['type']) { switch ($this->_source['type']) {
case 'git': case 'git':
$this->_name = 'SCM Clone (GIT) [built-in]'; $this->_name = 'SCM Clone (GIT) [built-in]';
@ -39,7 +39,7 @@ class Mage_Task_BuiltIn_Scm_Clone
. 'git checkout ' . $this->_source['from']; . 'git checkout ' . $this->_source['from'];
$result = $result && $this->_runLocalCommand($command); $result = $result && $this->_runLocalCommand($command);
$this->_config->setFrom($this->_source['temporal']); $this->getConfig()->setFrom($this->_source['temporal']);
break; break;
case 'svn': case 'svn':

2
Mage/Task/BuiltIn/Scm/RemoveClone.php

@ -12,7 +12,7 @@ class Mage_Task_BuiltIn_Scm_RemoveClone
public function init() public function init()
{ {
$this->_source = $this->_config->deployment('source'); $this->_source = $this->getConfig()->deployment('source');
} }
public function run() public function run()

10
Mage/Task/BuiltIn/Scm/Update.php

@ -11,7 +11,7 @@ class Mage_Task_BuiltIn_Scm_Update
public function init() public function init()
{ {
switch ($this->_config->scm('type')) { switch ($this->getConfig()->scm('type')) {
case 'git': case 'git':
$this->_name = 'SCM Update (GIT) [built-in]'; $this->_name = 'SCM Update (GIT) [built-in]';
break; break;
@ -24,7 +24,7 @@ class Mage_Task_BuiltIn_Scm_Update
public function run() public function run()
{ {
switch ($this->_config->scm('type')) { switch ($this->getConfig()->scm('type')) {
case 'git': case 'git':
$command = 'git pull'; $command = 'git pull';
break; break;
@ -32,10 +32,14 @@ class Mage_Task_BuiltIn_Scm_Update
case 'svn': case 'svn':
$command = 'svn update'; $command = 'svn update';
break; break;
default:
return false;
break;
} }
$result = $this->_runLocalCommand($command); $result = $this->_runLocalCommand($command);
$this->_config->reloadConfig(); $this->getConfig()->reload();
return $result; return $result;
} }

4
Mage/Task/Releases/SkipOnOverride.php

@ -0,0 +1,4 @@
<?php
interface Mage_Task_Releases_SkipOnOverride
{
}

5
Mage/Task/TaskAbstract.php

@ -31,11 +31,6 @@ abstract class Mage_Task_TaskAbstract
return $this->_config; return $this->_config;
} }
public function getActionOption($name, $value = false)
{
return Mage_Console::getActionOption($name, $value);
}
public function init() public function init()
{ {
} }

31
bin/mage.php

@ -1,37 +1,18 @@
<?php <?php
# sudo mage install
# mage version
# mage upgrade
# mage config add host s05.example.com to:[production]
# mage config git git://github.com/andres-montanez/Zend-Framework-Twig-example-app.git
# mage config svn svn://example.com/repo
# mage task:deployment/rsync to:production
# mage releases list to:production
# mage releases rollback to:production
# mage releases rollback -1 to:production
# mage releases rollback -2 to:production
# mage releases rollback -3 to:production
# mage releases rollback 0 to:production
# mage releases rollback 20120101172148 to:production
# mage add environment production --width-releases
# mage init
# mage add environment production
# mage deploy to:production
date_default_timezone_set('UTC'); date_default_timezone_set('UTC');
$baseDir = dirname(dirname(__FILE__)); $baseDir = dirname(dirname(__FILE__));
define('MAGALLANES_VERSION', '0.9.10'); define('MAGALLANES_VERSION', '0.9.10');
// Preload
require_once $baseDir . '/Mage/spyc.php'; require_once $baseDir . '/Mage/spyc.php';
require_once $baseDir . '/Mage/Autoload.php'; require_once $baseDir . '/Mage/Autoload.php';
spl_autoload_register(array('Mage_Autoload', 'autoload')); spl_autoload_register(array('Mage_Autoload', 'autoload'));
$console = new Mage_Console; // Clean arguments
$console->setArgs($argv); array_shift($argv);
$console->parse();
$console->run(); // Run Magallanes
$console = new Mage_Console;
$console->run($argv);

59
docs/commands.txt

@ -0,0 +1,59 @@
### List of Commands ###
# Installs Magallanes on the system
sudo mage install
# Displays Magallanes version
mage version
# Creats a Magallanes instance configuration
mage init
# Creates a compiled version of Magallanes using phar
mage compile
# Upgrades Magallanes itself
mage upgrade
# Add a new Environment configuration
mage add environment --name=production
# Add a new Environment configuration with releases enabled
mage add environment --name=production --enableReleases
# Performs a SCM Update, if configured
mage update
# Deploys Application to Production environment
mage deploy to:production
# Deploys Application to Production environment, overriding the current release
mage deploy to:production --overrideRelease
# Locks deployment to Production environment
mage lock to:production
# Unlocks deployment to Production environment
mage unlock to:production
# Lists all Releases on the Production environment
mage releases list to:production
# Rollback to the last Release on the Production environment
mage releases rollback to:production
mage releases rollback --release=0 to:production
# Rollback to the first, second, or thrith Release before the current Release on the Production environment
mage releases rollback --release=-1 to:production
mage releases rollback --release=-2 to:production
mage releases rollback --release=-3 to:production
# Rollback to a specific Release on the Production environment
# mage releases rollback --release=20120101172148 to:production
### List of UPCOMING Commands ###
# mage config add host s05.example.com to:[production]
# mage config git git://github.com/andres-montanez/Zend-Framework-Twig-example-app.git
# mage config svn svn://example.com/repo
# mage task:deployment/rsync to:production

12
docs/example-config/.mage/config/environment/staging.yml

@ -2,11 +2,14 @@
deployment: deployment:
user: root user: root
from: ./ from: ./
to: /var/www/vhosts/example.com/staging to: /var/www/
#hosts: /tmp/current-staging-hosts.txt releases:
enabled: true
max: 5
symlink: current
directory: releases
hosts: hosts:
- s01.example.com:22 - localhost
- s02.example.com
tasks: tasks:
pre-deploy: pre-deploy:
- scm/update - scm/update
@ -14,4 +17,5 @@ tasks:
- privileges - privileges
- sampleTask - sampleTask
- sampleTaskRollbackAware - sampleTaskRollbackAware
#post-release
#post-deploy: #post-deploy:
Loading…
Cancel
Save