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. 9
      Mage/Autoload.php
  2. 91
      Mage/Command/BuiltIn/Add.php
  3. 6
      Mage/Command/BuiltIn/Compile.php
  4. 72
      Mage/Command/BuiltIn/Deploy.php
  5. 9
      Mage/Command/BuiltIn/Init.php
  6. 11
      Mage/Command/BuiltIn/Install.php
  7. 23
      Mage/Command/BuiltIn/Lock.php
  8. 58
      Mage/Command/BuiltIn/Releases.php
  9. 16
      Mage/Command/BuiltIn/Unlock.php
  10. 19
      Mage/Command/BuiltIn/Update.php
  11. 23
      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. 442
      Mage/Config.php
  17. 261
      Mage/Console.php
  18. 14
      Mage/Task/BuiltIn/Deployment/Releases.php
  19. 42
      Mage/Task/BuiltIn/Deployment/Rsync.php
  20. 28
      Mage/Task/BuiltIn/Releases/List.php
  21. 57
      Mage/Task/BuiltIn/Releases/Rollback.php
  22. 12
      Mage/Task/BuiltIn/Scm/Clone.php
  23. 8
      Mage/Task/BuiltIn/Scm/RemoveClone.php
  24. 10
      Mage/Task/BuiltIn/Scm/Update.php
  25. 4
      Mage/Task/Releases/SkipOnOverride.php
  26. 25
      Mage/Task/TaskAbstract.php
  27. 31
      bin/mage.php
  28. 59
      docs/commands.txt
  29. 14
      docs/example-config/.mage/config/environment/staging.yml

9
Mage/Autoload.php

@ -7,7 +7,14 @@ class Mage_Autoload
$classFile = $baseDir . '/' . str_replace('_', '/', $className . '.php');
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)
{
$classFile = '.mage/tasks/' . ucfirst($taskName) . '.php';

91
Mage/Command/BuiltIn/Add.php

@ -1,44 +1,65 @@
<?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';
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);
throw new Exception('The environment already exists.');
}
Mage_Console::output('Adding new environment: <dark_gray>' . $environmentName . '</dark_gray>');
$releasesConfig = 'releases:' . PHP_EOL
. ' enabled: true' . PHP_EOL
. ' max: 10' . PHP_EOL
. ' symlink: current' . PHP_EOL
. ' directory: releases' . PHP_EOL;
$baseConfig = '#' . $environmentName . PHP_EOL
. 'deployment:' . PHP_EOL
. ' user: dummy' . PHP_EOL
. ' from: ./' . PHP_EOL
. ' to: /var/www/vhosts/example.com/www' . PHP_EOL
. ' excludes:' . PHP_EOL
. ($withReleases ? $releasesConfig : '')
. 'hosts:' . PHP_EOL
. 'tasks:' . PHP_EOL
. ' pre-deploy:' . PHP_EOL
. ' on-deploy:' . PHP_EOL
. ' - deployment/rsync' . PHP_EOL
. ' post-deploy:' . PHP_EOL;
$result = file_put_contents($environmentConfigFile, $baseConfig);
if ($result) {
Mage_Console::output('<light_green>Success!!</light_green> Environment config file for <dark_gray>' . $environmentName . '</dark_gray> created successfully at <blue>' . $environmentConfigFile . '</blue>');
Mage_Console::output('<dark_gray>So please! Review and adjust its configuration.</dark_gray>', 2, 2);
} else {
$releasesConfig = 'releases:' . PHP_EOL
. ' enabled: true' . PHP_EOL
. ' max: 10' . PHP_EOL
. ' symlink: current' . PHP_EOL
. ' directory: releases' . PHP_EOL;
$baseConfig = '#' . $environmentName . PHP_EOL
. 'deployment:' . PHP_EOL
. ' user: dummy' . PHP_EOL
. ' from: ./' . PHP_EOL
. ' to: /var/www/vhosts/example.com/www' . PHP_EOL
. ' excludes:' . PHP_EOL
. ($withRelases ? $releasesConfig : '')
. 'hosts:' . PHP_EOL
. 'tasks:' . PHP_EOL
. ' pre-deploy:' . PHP_EOL
. ' on-deploy:' . PHP_EOL
. ' - deployment/rsync' . PHP_EOL
. ' post-deploy:' . PHP_EOL;
$result = file_put_contents($environmentConfigFile, $baseConfig);
if ($result) {
Mage_Console::output('<light_green>Success!!</light_green> Environment config file for <dark_gray>' . $environmentName . '</dark_gray> created successfully at <blue>' . $environmentConfigFile . '</blue>');
Mage_Console::output('<dark_gray>So please! Review and adjust its configuration.</dark_gray>', 2, 2);
} else {
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
/**
* Class Mage_Task_Compile
* Class Mage_Command_BuiltIn_Compile
*
* @author Ismael Ambrosi<ismaambrosi@gmail.com>
*/
class Mage_Task_Compile
class Mage_Command_BuiltIn_Compile
extends Mage_Command_CommandAbstract
{
/**
* @see Mage_Compile::compile()

72
Mage/Command/BuiltIn/Deploy.php

@ -1,8 +1,8 @@
<?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 $_startTimeHosts = null;
private $_endTimeHosts = null;
@ -13,27 +13,21 @@ class Mage_Task_Deploy
$this->_releaseId = date('YmdHis');
}
public function run(Mage_Config $config)
public function run()
{
$this->_startTime = time();
$this->_config = $config;
if ($config->getEnvironmentName() == '') {
Mage_Console::output('<red>You must specify an environment</red>', 0, 2);
return;
}
$lockFile = '.mage/' . $config->getEnvironmentName() . '.lock';
$lockFile = '.mage/' . $this->getConfig()->getEnvironment() . '.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>', 1, 2);
return;
}
// Run Pre-Deployment Tasks
$this->_runNonDeploymentTasks('pre-deploy', $config, 'Pre-Deployment');
$this->_runNonDeploymentTasks('pre-deploy', $this->getConfig(), 'Pre-Deployment');
// Run Tasks for Deployment
$hosts = $config->getHosts();
$hosts = $this->getConfig()->getHosts();
if (count($hosts) == 0) {
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();
foreach ($hosts as $host) {
$this->_hostsCount++;
$config->setHost($host);
$this->getConfig()->setHost($host);
$tasks = 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');
if ($config->release('enabled', false) == true) {
$config->setReleaseId($this->_releaseId);
if ($this->getConfig()->release('enabled', false) == true) {
$this->getConfig()->setReleaseId($this->_releaseId);
array_push($tasksToRun, 'deployment/releases');
}
$tasksToRun = $tasksToRun + $this->getConfig()->getTasks('post-release');
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('Deployment to <dark_gray>' . $config->getHost() . '</dark_gray> skipped!', 1, 3);
@ -63,17 +59,27 @@ class Mage_Task_Deploy
} else {
foreach ($tasksToRun as $taskName) {
$tasks++;
$task = Mage_Task_Factory::get($taskName, $config, false, 'deploy');
$task = Mage_Task_Factory::get($taskName, $this->getConfig(), false, 'deploy');
$task->init();
$runTask = true;
Mage_Console::output('Running <purple>' . $task->getName() . '</purple> ... ', 2, false);
$result = $task->run();
if ($result == true) {
Mage_Console::output('<green>OK</green>', 0);
$completedTasks++;
if (($task instanceOf Mage_Task_Releases_SkipOnOverride) && $this->getConfig()->getParameter('overrideRelease', false)) {
$runTask == false;
}
if ($runTask == true) {
$result = $task->run();
if ($result == true) {
Mage_Console::output('<green>OK</green>', 0);
$completedTasks++;
} else {
Mage_Console::output('<red>FAIL</red>', 0);
}
} else {
Mage_Console::output('<red>FAIL</red>', 0);
Mage_Console::output('<yellow>SKIPPED</yellow>', 0);
}
}
@ -83,14 +89,14 @@ class Mage_Task_Deploy
$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();
}
// Run Post-Deployment Tasks
$this->_runNonDeploymentTasks('post-deploy', $config, 'Post-Deployment');
$this->_runNonDeploymentTasks('post-deploy', $this->getConfig(), 'Post-Deployment');
// Time Information Hosts
if ($this->_hostsCount > 0) {
@ -106,6 +112,13 @@ class Mage_Task_Deploy
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)
{
$tasksToRun = $config->getTasks($stage);
@ -156,6 +169,11 @@ class Mage_Task_Deploy
}
/**
* Humanize Transcurred time
* @param integer $time
* @return string
*/
private function _transcurredTime($time)
{
$hours = floor($time / 3600);

9
Mage/Command/BuiltIn/Init.php

@ -1,12 +1,13 @@
<?php
class Mage_Task_Init
class Mage_Command_BuiltIn_Init
extends Mage_Command_CommandAbstract
{
public function run()
{
$configDir = '.mage';
Mage_Console::output('Initiating managing process for application with <dark_gray>Magallanes</dark_gray>');
// Check if there is already a config dir
if (file_exists($configDir)) {
Mage_Console::output('<light_red>Error!!</light_red> Already exists <dark_gray>.mage</dark_gray> directory.', 1, 2);
@ -19,7 +20,7 @@ class Mage_Task_Init
$results[] = mkdir($configDir . '/config/environment');
$results[] = file_put_contents($configDir . '/config/general.yml', '#global settings' . PHP_EOL . PHP_EOL);
$results[] = file_put_contents($configDir . '/config/scm.yml', '#scm settings' . PHP_EOL . PHP_EOL);
if (!in_array(false, $results)) {
Mage_Console::output('<light_green>Success!!</light_green> The configuration for <dark_gray>Magallanes</dark_gray> has been generated at <blue>.mage</blue> directory.');
Mage_Console::output('<dark_gray>Please!! Review and adjust the configuration.</dark_gray>', 2, 2);

11
Mage/Command/BuiltIn/Install.php

@ -1,11 +1,12 @@
<?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);
$this->_recursiveCopy('./', '/opt/magallanes-' . MAGALLANES_VERSION);
if (file_exists('/opt/magallanes') && is_link('/opt/magallanes')) {
unlink('/opt/magallanes');
}
@ -18,7 +19,7 @@ class Mage_Task_Install
Mage_Console::output('<light_green>Success!</light_green>', 0, 2);
}
private function _recursiveCopy ($from, $to)
private function _recursiveCopy($from, $to)
{
if (is_dir($from)) {
mkdir($to);
@ -38,7 +39,7 @@ class Mage_Task_Install
} else {
copy(
$from . DIRECTORY_SEPARATOR . $file,
$from . DIRECTORY_SEPARATOR . $file,
$to . DIRECTORY_SEPARATOR . $file
);
}

23
Mage/Command/BuiltIn/Lock.php

@ -1,23 +1,14 @@
<?php
class Mage_Task_Lock
class Mage_Command_BuiltIn_Lock
extends Mage_Command_CommandAbstract
implements Mage_Command_RequiresEnvironment
{
private $_config = null;
public function run(Mage_Config $config, $unlock = false)
public function run()
{
$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)) {
@unlink($lockFile);
}
$lockFile = '.mage/' . $this->getConfig()->getEnvironment() . '.lock';
file_put_contents($lockFile, 'Locked environment at date: ' . date('Y-m-d H:i:s'));
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);
}
}

58
Mage/Command/BuiltIn/Releases.php

@ -1,67 +1,41 @@
<?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;
public function setAction($action)
public function run()
{
$this->_action = $action;
return $this;
}
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)) {
$subcommand = $this->getConfig()->getArgument(1);
$lockFile = '.mage/' . $this->getConfig()->getEnvironment() . '.lock';
if (file_exists($lockFile) && ($subcommand == 'rollback')) {
Mage_Console::output('<red>This environment is locked!</red>', 0, 2);
return;
}
// Run Tasks for Deployment
$hosts = $config->getHosts();
$hosts = $this->getConfig()->getHosts();
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);
} else {
foreach ($hosts as $host) {
$config->setHost($host);
switch ($this->getAction()) {
$this->getConfig()->setHost($host);
switch ($subcommand) {
case 'list':
$task = Mage_Task_Factory::get('releases/list', $config);
$task = Mage_Task_Factory::get('releases/list', $this->getConfig());
$task->init();
$result = $task->run();
break;
case 'rollback':
$task = Mage_Task_Factory::get('releases/rollback', $config);
case 'rollback':
$releaseId = $this->getConfig()->getParameter('release', '');
$task = Mage_Task_Factory::get('releases/rollback', $this->getConfig());
$task->init();
$task->setRelease($this->getRelease());
$task->setRelease($releaseId);
$result = $task->run();
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);
}
}

19
Mage/Command/BuiltIn/Update.php

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

23
Mage/Command/BuiltIn/Upgrade.php

@ -1,19 +1,20 @@
<?php
class Mage_Task_Upgrade
class Mage_Command_BuiltIn_Upgrade
extends Mage_Command_CommandAbstract
{
const DOWNLOAD = 'https://github.com/andres-montanez/Magallanes/tarball/stable';
public function run ()
{
Mage_Console::output('Upgrading <dark_gray>Magallanes</dark_gray> ... ', 1, 0);
$user = '';
// Check if user is root
Mage_Console::executeCommand('whoami', $user);
if ($user != 'root') {
Mage_Console::output('<red>FAIL</red>', 0, 1);
Mage_Console::output('You need to be the <dark_gray>root</dark_gray> user to perform the upgrade.', 2);
} else {
// Download Package
$tarball = file_get_contents(self::DOWNLOAD);
@ -21,7 +22,7 @@ class Mage_Task_Upgrade
rename($tarballFile, $tarballFile . '.tar.gz');
$tarballFile .= '.tar.gz';
file_put_contents($tarballFile, $tarball);
// Unpackage
if (file_exists('/tmp/__magallanesDownload')) {
Mage_Console::executeCommand('rm -rf /tmp/__magallanesDownload');
@ -29,7 +30,7 @@ class Mage_Task_Upgrade
Mage_Console::executeCommand('mkdir /tmp/__magallanesDownload');
Mage_Console::executeCommand('cd /tmp/__magallanesDownload && tar xfz ' . $tarballFile);
Mage_Console::executeCommand('rm -f ' . $tarballFile);
// Find Package
$tarballDir = opendir('/tmp/__magallanesDownload');
while (($file = readdir($tarballDir)) == true) {
@ -40,14 +41,14 @@ class Mage_Task_Upgrade
break;
}
}
// Get Version
$version = false;
if (file_exists('/tmp/__magallanesDownload/' . $packageDir . '/bin/mage')) {
list(, $version) = file('/tmp/__magallanesDownload/' . $packageDir . '/bin/mage');
$version = trim(str_replace('#VERSION:', '', $version));
}
if ($version != false) {
$versionCompare = version_compare(MAGALLANES_VERSION, $version);
if ($versionCompare == 0) {
@ -66,13 +67,13 @@ class Mage_Task_Upgrade
Mage_Console::output('<green>OK</green>', 0, 1);
}
} else {
Mage_Console::output('<red>FAIL</red>', 0, 1);
Mage_Console::output('Corrupted download.', 2);
}
}
}
@ -96,7 +97,7 @@ class Mage_Task_Upgrade
} else {
copy(
$from . DIRECTORY_SEPARATOR . $file,
$from . DIRECTORY_SEPARATOR . $file,
$to . DIRECTORY_SEPARATOR . $file
);
}

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
{
}

442
Mage/Config.php

@ -1,88 +1,132 @@
<?php
class Mage_Config
{
private $_environmentName = null;
private $_environment = null;
private $_scm = null;
private $_general = null;
private $_arguments = array();
private $_parameters = array();
private $_environment = false;
private $_host = null;
private $_releaseId = null;
public function reloadConfig()
private $_config = array(
'general' => array(),
'scm' => array(),
'environment' => array(),
);
/**
* Load the Configuration and parses the Arguments
*
* @param array $arguments
*/
public function load($arguments)
{
$this->loadGeneral();
$this->loadSCM();
$this->loadEnvironment($this->getEnvironmentName());
$this->_parse($arguments);
$this->_loadGeneral();
$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')) {
$this->_environment = spyc_load_file('.mage/config/environment/' . $environment . '.yml');
$this->_environmentName = $environment;
// 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')) {
if (isset($this->_arguments[$position])) {
return $this->_arguments[$position];
} else {
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')) {
$this->_scm = spyc_load_file('.mage/config/scm.yml');
if (isset($this->_parameters[$name])) {
return $this->_parameters[$name];
} else {
return $default;
}
}
public function loadGeneral()
{
if (file_exists('.mage/config/general.yml')) {
$this->_general = spyc_load_file('.mage/config/general.yml');
}
/**
* Returns all the invocation arguments
*
* @return array
*/
public function getParameters()
{
return $this->_parameters;
}
/**
* Returns the Current environment
*
* @return mixed
*/
public function getEnvironment()
{
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 $this->_global;
return $tasks;
}
/**
* Get the current Hosts to deploy
*
* @return array
*/
public function getHosts()
{
$config = $this->getEnvironment();
$hosts = array();
if (isset($config['hosts'])) {
if (is_array($config['hosts'])) {
$hosts = (array) $config['hosts'];
} else if (is_string($config['hosts'])) {
$fileContent = fopen($config['hosts'], 'r');
if (isset($this->_config['environment']['hosts'])) {
if (is_array($this->_config['environment']['hosts'])) {
$hosts = (array) $this->_config['environment']['hosts'];
} else if (is_string($this->_config['environment']['hosts']) && file_exists($this->_config['environment']['hosts']) && is_readable($this->_config['environment']['hosts'])) {
$fileContent = fopen($this->_config['environment']['hosts'], 'r');
while (($host = fgets($fileContent)) == true) {
$host = trim($host);
if ($host != '') {
@ -95,18 +139,34 @@ class Mage_Config
return $hosts;
}
/**
* Set the current host
*
* @param string $host
* @return Mage_Config
*/
public function setHost($host)
{
$this->_host = $host;
return $this;
}
/**
* Get the current host name
*
* @return string
*/
public function getHostName()
{
$info = explode(':', $this->_host);
return $info[0];
}
/**
* Get the current Host Port
*
* @return unknown
*/
public function getHostPort()
{
$info = explode(':', $this->_host);
@ -114,144 +174,222 @@ class Mage_Config
return $info[1];
}
/**
* Get the current Host
*
* @return string
*/
public function getHost()
{
return $this->_host;
}
public function setReleaseId($id)
{
$this->_releaseId = $id;
return $this;
}
public function getReleaseId()
/**
* Gets General Configuration
*
* @param string $option
* @param string $default
* @return mixed
*/
public function general($option, $default = false)
{
return $this->_releaseId;
}
public function getTasks($stage = 'on-deploy')
{
switch ($stage) {
case 'pre-deploy':
$type = 'tasks';
$stage = 'pre-deploy';
break;
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;
}
$tasks = array();
$config = $this->getEnvironment();
if (isset($config[$type]) && isset($config[$type][$stage])) {
$tasks = ($config[$type][$stage] ? (array) $config[$type][$stage] : array());
$config = $this->_config['general'];
if (isset($config[$option])) {
if (is_array($default) && ($config[$option] == '')) {
return $default;
} else {
return $config[$option];
}
} else {
return $default;
}
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();
$taskConfig['deploy'] = $this->getEnvironment();
$taskConfig['deploy']['host'] = $host;
$taskConfig['scm'] = $this->getSCM();
unset($taskConfig['deploy']['tasks']);
unset($taskConfig['deploy']['hosts']);
return $taskConfig;
}
public function setFrom($from)
{
$this->_environment['deployment']['from'] = $from;
return $this;
$config = $this->_config['scm'];
if (isset($config[$option])) {
if (is_array($default) && ($config[$option] == '')) {
return $default;
} else {
return $config[$option];
}
} else {
return $default;
}
}
/**
* Get deployment configuration
*
* @param string $option
* @param string $default
* @return string
*/
public function deployment($option, $default = false)
{
$options = $this->getEnvironment();
if (isset($options['deployment'][$option])) {
if (is_array($default) && ($options['deployment'][$option] == '')) {
$config = $this->_getEnvironmentOption('deployment', array());
if (isset($config[$option])) {
if (is_array($default) && ($config[$option] == '')) {
return $default;
} else {
return $options['deployment'][$option];
return $config[$option];
}
} else {
return $default;
}
}
/**
* Returns Releaseing Options
*
* @param string $option
* @param string $default
* @return mixed
*/
public function release($option, $default = false)
{
$options = $this->getEnvironment();
if (isset($options['releases'][$option])) {
if (is_array($default) && ($options['releases'][$option] == '')) {
$config = $this->_getEnvironmentOption('releases', array());
if (isset($config[$option])) {
if (is_array($default) && ($config[$option] == '')) {
return $default;
} else {
return $options['releases'][$option];
return $config[$option];
}
} else {
return $default;
}
}
public function scm($option, $default = false)
{
$options = $this->_scm;
if (isset($options[$option])) {
if (is_array($default) && ($options[$option] == '')) {
return $default;
} else {
return $options[$option];
}
return $options[$option];
} else {
return $default;
}
/**
* Set From Deployment Path
*
* @param string $from
* @return Mage_Config
*/
public function setFrom($from)
{
$this->_config['environment']['deployment']['from'] = $from;
return $this;
}
public function general($option, $default = false)
{
$options = $this->_general;
if (isset($options[$option])) {
if (is_array($default) && ($options[$option] == '')) {
return $default;
} else {
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;
}
public function mail($option, $default = false)
{
$options = $this->_general;
if (isset($options['mail'][$option])) {
if (is_array($default) && ($options['mail'][$option] == '')) {
return $default;
} else {
return $options['mail'][$option];
}
} else {
return $default;
}
/**
* Gets the Current Release ID
*
* @return integer
*/
public function getReleaseId()
{
return $this->_releaseId;
}
/**
* Parse the Command Line options
* @return boolean
*/
private function _parse($arguments)
{
foreach ($arguments as $argument) {
if (preg_match('/to:[\w]+/i', $argument)) {
$this->_environment = str_replace('to:', '', $argument);
} else if (preg_match('/--[\w]+/i', $argument)) {
$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 {
$this->_arguments[] = $argument;
}
}
}
/**
* Loads the General Configuration
*/
private function _loadGeneral()
{
if (file_exists('.mage/config/general.yml')) {
$this->_config['general'] = spyc_load_file('.mage/config/general.yml');
}
}
/**
* 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 {
return $default;
}
}
}

261
Mage/Console.php

@ -1,95 +1,77 @@
<?php
class Mage_Console
{
private $_args = array();
private $_action = null;
private static $_actionOptions = array();
private $_environment = null;
private static $_log = null;
private static $_logEnabled = true;
private static $_screenBuffer = '';
private static $_commandsOutput = '';
public function setArgs($args)
/**
* Runns a Magallanes Command
* @throws Exception
*/
public function run($arguments)
{
$this->_args = $args;
array_shift($this->_args);
}
public function parse()
{
if (count($this->_args) == 0) {
return false;
$configError = false;
try {
// Load Config
$config = new Mage_Config;
$config->load($arguments);
$configLoadedOk = true;
} catch (Exception $e) {
$configError = $e->getMessage();
}
if ($this->_args[0] == 'deploy') {
$this->_action = 'deploy';
} 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') {
$this->_action = 'init';
// Command Option
$commandName = $config->getArgument(0);
} else if ($this->_args[0] == 'lock') {
$this->_action = 'lock';
// Logging
$showGrettings = true;
if (in_array($commandName, array('install', 'upgrade', 'version'))) {
self::$_logEnabled = false;
$showGrettings = false;
} else {
self::$_logEnabled = $config->general('logging', false);
}
} else if ($this->_args[0] == 'unlock') {
$this->_action = 'unlock';
// Grettings
if ($showGrettings) {
Mage_Console::output('Starting <blue>Magallanes</blue>', 0, 2);
}
foreach ($this->_args as $argument) {
if (preg_match('/to:[\w]+/i', $argument)) {
$this->_environment = str_replace('to:', '', $argument);
// Run Command
if ($configError !== false) {
Mage_Console::output('<red>' . $configError . '</red>', 1, 2);
} else if (preg_match('/--[\w]+/i', $argument)) {
$optionValue = explode('=', substr($argument, 2));
if (count($optionValue) == 1) {
self::$_actionOptions[$optionValue[0]] = true;
} else if (count($optionValue) == 2) {
self::$_actionOptions[$optionValue[0]] = $optionValue[1];
} else {
try {
$command = Mage_Command_Factory::get($commandName, $config);
if ($command instanceOf Mage_Command_RequiresEnvironment) {
if ($config->getEnvironment() == false) {
throw new Exception('You must specify an environment for this command.');
}
}
$command->run();
} catch (Exception $e) {
Mage_Console::output('<red>' . $e->getMessage() . '</red>', 1, 2);
}
}
}
public function getAction()
{
return $this->_action;
}
public function getEnvironment()
{
return $this->_environment;
}
public static function getActionOption($name, $default = false)
{
if (isset(self::$_actionOptions[$name])) {
return self::$_actionOptions[$name];
} else {
return $default;
if ($showGrettings) {
Mage_Console::output('Finished <blue>Magallanes</blue>', 0, 2);
}
}
/**
* 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)
{
self::log(strip_tags($message));
@ -105,6 +87,13 @@ class Mage_Console
echo $output;
}
/**
* Executes a Command on the Shell
*
* @param string $command
* @param string $output
* @return boolean
*/
public static function executeCommand($command, &$output = null)
{
self::log('---------------------------------');
@ -126,134 +115,12 @@ class Mage_Console
return !$return;
}
public function run()
{
// Load Config
$config = new Mage_Config;
$config->loadGeneral();
$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);
}
/**
* Log a message to the logfile.
*
* @param string $message
* @param boolean $continuation
*/
public static function log($message, $continuation = false)
{
if (self::$_logEnabled) {

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

@ -10,15 +10,15 @@ class Mage_Task_BuiltIn_Deployment_Releases
public function run()
{
if ($this->_config->release('enabled', false) == true) {
$releasesDirectory = $this->_config->release('directory', 'releases');
$symlink = $this->_config->release('symlink', 'current');
if ($this->getConfig()->release('enabled', false) == true) {
$releasesDirectory = $this->getConfig()->release('directory', 'releases');
$symlink = $this->getConfig()->release('symlink', 'current');
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
$userGroup = '33:33';
@ -35,7 +35,7 @@ class Mage_Task_BuiltIn_Deployment_Releases
$result = $this->_runRemoteCommand($command);
// Count Releases
$maxReleases = $this->_config->release('max', false);
$maxReleases = $this->getConfig()->release('max', false);
if (($maxReleases !== false) && ($maxReleases > 0)) {
$releasesList = '';
$countReleasesFetch = $this->_runRemoteCommand('ls -1 ' . $releasesDirectory, $releasesList);
@ -44,7 +44,7 @@ class Mage_Task_BuiltIn_Deployment_Releases
if ($releasesList != '') {
$releasesList = explode(PHP_EOL, $releasesList);
if (count($releasesList) > $maxReleases) {
$releasesToDelete = array_diff($releasesList, array($this->_config->getReleaseId()));
$releasesToDelete = array_diff($releasesList, array($this->getConfig()->getReleaseId()));
sort($releasesToDelete);
$releasesToDeleteCount = count($releasesToDelete) - $maxReleases;
$releasesToDelete = array_slice($releasesToDelete, 0, $releasesToDeleteCount + 1);

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

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

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

@ -10,16 +10,22 @@ class Mage_Task_BuiltIn_Releases_List
public function run()
{
if ($this->_config->release('enabled', false) == true) {
$releasesDirectory = $this->_config->release('directory', 'releases');
$symlink = $this->_config->release('symlink', 'current');
if ($this->getConfig()->release('enabled', false) == true) {
$releasesDirectory = $this->getConfig()->release('directory', 'releases');
$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 = '';
$result = $this->_runRemoteCommand('ls -1 ' . $releasesDirectory, $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) {
Mage_Console::output('<dark_gray>No releases available</dark_gray> ... ', 2);
} else {
@ -27,6 +33,7 @@ class Mage_Task_BuiltIn_Releases_List
$releases = array_slice($releases, 0, 10);
foreach ($releases as $releaseIndex => $release) {
$release = trim($release);
$releaseIndex = str_pad($releaseIndex * -1, 2, ' ', STR_PAD_LEFT);
$releaseDate = $release[0] . $release[1] . $release[2] .$release[3]
. '-'
@ -39,11 +46,16 @@ class Mage_Task_BuiltIn_Releases_List
. $release[10] . $release[11]
. ':'
. $release[12] . $release[13];
$isCurrent = '';
if ($currentRelease == $release) {
$isCurrent = ' <- current';
}
Mage_Console::output(
'Release: <purple>' . $release . '</purple> '
. '- Date: <dark_gray>' . $releaseDate . '</dark_gray> '
. '- Index: <dark_gray>' . $releaseIndex . '</dark_gray>', 2);
. '- Index: <dark_gray>' . $releaseIndex . '</dark_gray>' . $isCurrent, 2);
}
}

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

@ -4,7 +4,7 @@ class Mage_Task_BuiltIn_Releases_Rollback
implements Mage_Task_Releases_BuiltIn
{
private $_release = null;
public function getName()
{
return 'Rollback release [built-in]';
@ -15,31 +15,32 @@ class Mage_Task_BuiltIn_Releases_Rollback
$this->_release = $releaseId;
return $this;
}
public function getRelease()
{
return $this->_release;
}
public function run()
{
if ($this->_config->release('enabled', false) == true) {
$releasesDirectory = $this->_config->release('directory', 'releases');
$symlink = $this->_config->release('symlink', 'current');
if ($this->getConfig()->release('enabled', false) == true) {
$releasesDirectory = $this->getConfig()->release('directory', 'releases');
$symlink = $this->getConfig()->release('symlink', 'current');
$output = '';
$result = $this->_runRemoteCommand('ls -1 ' . $releasesDirectory, $output);
$releases = ($output == '') ? array() : explode(PHP_EOL, $output);
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 {
rsort($releases);
$releaseIsAvailable = false;
if ($this->getRelease() == '') {
$releaseId = $releases[0];
$releaseIsAvailable = true;
} else if ($this->getRelease() <= 0) {
$index = $this->getRelease() * -1;
@ -53,34 +54,34 @@ class Mage_Task_BuiltIn_Releases_Rollback
$releaseIsAvailable = true;
}
}
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 {
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;
// Tasks
$tasks = 1;
$completedTasks = 0;
$tasksToRun = $this->_config->getTasks();
$this->_config->setReleaseId($releaseId);
$tasksToRun = $this->getConfig()->getTasks();
$this->getConfig()->setReleaseId($releaseId);
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('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 {
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();
Mage_Console::output('Running <purple>' . $task->getName() . '</purple> ... ', 2, false);
if ($task instanceOf Mage_Task_Releases_RollbackAware) {
$tasks++;
$result = $task->run();
if ($result == true) {
Mage_Console::output('<green>OK</green>', 0);
$completedTasks++;
@ -88,14 +89,14 @@ class Mage_Task_BuiltIn_Releases_Rollback
Mage_Console::output('<red>FAIL</red>', 0);
}
} else {
Mage_Console::output('<yellow>SKIPPED</yellow>', 0);
Mage_Console::output('<yellow>SKIPPED</yellow>', 0);
}
}
}
// Changing Release
Mage_Console::output('Running <purple>Rollback Release [id=' . $releaseId . ']</purple> ... ', 2, false);
$userGroup = '';
$resultFetch = $this->_runRemoteCommand('ls -ld ' . $rollbackTo . ' | awk \'{print \$3\":\"\$4}\'', $userGroup);
$command = 'rm -f ' . $symlink
@ -111,14 +112,14 @@ class Mage_Task_BuiltIn_Releases_Rollback
} else {
Mage_Console::output('<red>FAIL</red>', 0);
}
if ($completedTasks == $tasks) {
$tasksColor = 'green';
} else {
$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);
}
}

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

@ -4,15 +4,15 @@ class Mage_Task_BuiltIn_Scm_Clone
{
private $_name = 'SCM Clone [built-in]';
private $_source = null;
public function getName()
{
return $this->_name;
}
public function init()
{
$this->_source = $this->_config->deployment('source');
$this->_source = $this->getConfig()->deployment('source');
switch ($this->_source['type']) {
case 'git':
$this->_name = 'SCM Clone (GIT) [built-in]';
@ -23,7 +23,7 @@ class Mage_Task_BuiltIn_Scm_Clone
break;
}
}
public function run()
{
$this->_runLocalCommand('mkdir -p ' . $this->_source['temporal']);
@ -39,14 +39,14 @@ class Mage_Task_BuiltIn_Scm_Clone
. 'git checkout ' . $this->_source['from'];
$result = $result && $this->_runLocalCommand($command);
$this->_config->setFrom($this->_source['temporal']);
$this->getConfig()->setFrom($this->_source['temporal']);
break;
case 'svn':
return false;
break;
}
return $result;
}
}

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

@ -4,17 +4,17 @@ class Mage_Task_BuiltIn_Scm_RemoveClone
{
private $_name = 'SCM Remove Clone [built-in]';
private $_source = null;
public function getName()
{
return $this->_name;
}
public function init()
public function init()
{
$this->_source = $this->_config->deployment('source');
$this->_source = $this->getConfig()->deployment('source');
}
public function run()
{
return $this->_runLocalCommand('rm -rf ' . $this->_source['temporal']);

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

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

4
Mage/Task/Releases/SkipOnOverride.php

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

25
Mage/Task/TaskAbstract.php

@ -4,47 +4,42 @@ abstract class Mage_Task_TaskAbstract
protected $_config = null;
protected $_inRollback = false;
protected $_stage = null;
public abstract function getName();
public abstract function run();
public final function __construct(Mage_Config $config, $inRollback = false, $stage = null)
{
$this->_config = $config;
$this->_inRollback = $inRollback;
$this->_stage = $stage;
}
public function inRollback()
{
return $this->_inRollback;
}
public function getStage()
{
return $this->_stage;
}
public function getConfig()
{
return $this->_config;
}
public function getActionOption($name, $value = false)
{
return Mage_Console::getActionOption($name, $value);
}
public function init()
{
}
protected final function _runLocalCommand($command, &$output = null)
{
return Mage_Console::executeCommand($command, $output);
}
protected final function _runRemoteCommand($command, &$output = null)
{
if ($this->_config->release('enabled', false) == true) {
@ -61,7 +56,7 @@ abstract class Mage_Task_TaskAbstract
} else {
$releasesDirectory = '';
}
$localCommand = 'ssh -p ' . $this->_config->getHostPort() . ' '
. '-q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no '
. $this->_config->deployment('user') . '@' . $this->_config->getHostName() . ' '

31
bin/mage.php

@ -1,37 +1,18 @@
<?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');
$baseDir = dirname(dirname(__FILE__));
define('MAGALLANES_VERSION', '0.9.10');
// Preload
require_once $baseDir . '/Mage/spyc.php';
require_once $baseDir . '/Mage/Autoload.php';
spl_autoload_register(array('Mage_Autoload', 'autoload'));
$console = new Mage_Console;
$console->setArgs($argv);
$console->parse();
// Clean arguments
array_shift($argv);
$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

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

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

Loading…
Cancel
Save