diff --git a/Mage/Console.php b/Mage/Console.php index b472701..b93dd8d 100644 --- a/Mage/Console.php +++ b/Mage/Console.php @@ -111,7 +111,12 @@ class Mage_Console switch ($this->_args[1]) { case 'list': $task->setAction($this->_args[1]); - break; + break; + + case 'rollback': + $task->setAction($this->_args[1]); + $task->setRelease($this->_args[2]); + break; } $task->run($config); break; diff --git a/Mage/Task/BuiltIn/Deployment/Releases.php b/Mage/Task/BuiltIn/Deployment/Releases.php index 7e6fddf..90be299 100644 --- a/Mage/Task/BuiltIn/Deployment/Releases.php +++ b/Mage/Task/BuiltIn/Deployment/Releases.php @@ -15,7 +15,14 @@ class Mage_Task_BuiltIn_Deployment_Releases $currentCopy = $releasesDirectory . '/' . $this->_config->getReleaseId(); - $result = $this->_runRemoteCommand('ln -sf ' . $currentCopy . ' ' . $symlink); + $userGroup = ''; + $resultFetch = $this->_runRemoteCommand('ls -ld ' . $currentCopy . ' | awk \'{print \$3\":\"\$4}\'', $userGroup); + $command = 'rm -f ' . $symlink + . ' && ' + . 'ln -sf ' . $currentCopy . ' ' . $symlink + . ' && ' + . 'chown -h ' . $userGroup . ' ' . $symlink; + $result = $this->_runRemoteCommand($command); return $result; } else { diff --git a/Mage/Task/BuiltIn/Releases/List.php b/Mage/Task/BuiltIn/Releases/List.php index e681043..02a793b 100644 --- a/Mage/Task/BuiltIn/Releases/List.php +++ b/Mage/Task/BuiltIn/Releases/List.php @@ -46,8 +46,11 @@ class Mage_Task_BuiltIn_Releases_List } } + Mage_Console::output(''); return $result; + } else { + Mage_Console::output(''); return false; } } diff --git a/Mage/Task/BuiltIn/Releases/Rollback.php b/Mage/Task/BuiltIn/Releases/Rollback.php new file mode 100644 index 0000000..74e8ec6 --- /dev/null +++ b/Mage/Task/BuiltIn/Releases/Rollback.php @@ -0,0 +1,126 @@ +_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'); + + $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 ' . $this->_config->getHost() . ' ... FAIL'); + + } else { + rsort($releases); + + $releaseIsAvailable = false; + if ($this->getRelease() == '') { + $releaseId = $releases[0]; + + } else if ($this->getRelease() <= 0) { + $index = $this->getRelease() * -1; + if (isset($releases[$index])) { + $releaseId = $releases[$index]; + $releaseIsAvailable = true; + } + } else { + if (in_array($this->getRelease(), $releases)) { + $releaseId = $this->getRelease(); + $releaseIsAvailable = true; + } + } + + if (!$releaseIsAvailable) { + Mage_Console::output('Release ' . $this->getRelease() . ' is invalid or unavailable for ' . $this->_config->getHost() . ' ... FAIL'); + + } else { + Mage_Console::output('Rollback release on ' . $this->_config->getHost() . ''); + $rollbackTo = $releasesDirectory . '/' . $releaseId; + + // Tasks + $tasks = 1; + $completedTasks = 0; + $tasksToRun = $this->_config->getTasks(); + $this->_config->setReleaseId($releaseId); + + if (count($tasksToRun) == 0) { + Mage_Console::output('Warning! No Deployment tasks defined.', 2); + Mage_Console::output('Deployment to ' . $this->_config->getHost() . ' skipped!', 1, 3); + + } else { + foreach ($tasksToRun as $taskName) { + $tasks++; + $task = Mage_Task_Factory::get($taskName, $this->_config); + $task->init(); + + Mage_Console::output('Running ' . $task->getName() . ' ... ', 2, false); + $result = $task->run(); + + if ($result == true) { + Mage_Console::output('OK', 0); + $completedTasks++; + } else { + Mage_Console::output('FAIL', 0); + } + } + } + + // Changing Release + Mage_Console::output('Releasing to ' . $releaseId . ' ... ', 2, false); + + $userGroup = ''; + $resultFetch = $this->_runRemoteCommand('ls -ld ' . $rollbackTo . ' | awk \'{print \$3\":\"\$4}\'', $userGroup); + $command = 'rm -f ' . $symlink + . ' && ' + . 'ln -sf ' . $rollbackTo . ' ' . $symlink + . ' && ' + . 'chown -h ' . $userGroup . ' ' . $symlink; + $result = $this->_runRemoteCommand($command); + + if ($result) { + Mage_Console::output('OK', 0); + $completedTasks++; + } else { + Mage_Console::output('FAIL', 0); + } + + if ($completedTasks == $tasks) { + $tasksColor = 'green'; + } else { + $tasksColor = 'red'; + } + + Mage_Console::output('Release rollback on ' . $this->_config->getHost() . ' compted: <' . $tasksColor . '>' . $completedTasks . '/' . $tasks . ' tasks done.', 1, 3); + } + } + + return $result; + } else { + return false; + } + } + +} \ No newline at end of file diff --git a/Mage/Task/Deploy.php b/Mage/Task/Deploy.php index 434fd6b..aa91ed5 100644 --- a/Mage/Task/Deploy.php +++ b/Mage/Task/Deploy.php @@ -31,6 +31,8 @@ class Mage_Task_Deploy Mage_Console::output('Deploying to ' . $host . ''); $tasksToRun = $config->getTasks(); + array_unshift($tasksToRun, 'deployment/rsync'); + if ($config->release('enabled', false) == true) { $config->setReleaseId($this->_releaseId); array_push($tasksToRun, 'deployment/releases'); @@ -57,8 +59,6 @@ class Mage_Task_Deploy } } - // Run Post-Deployment Tasks - if ($completedTasks == $tasks) { $tasksColor = 'green'; } else { diff --git a/Mage/Task/Releases.php b/Mage/Task/Releases.php index 190e65c..4275360 100644 --- a/Mage/Task/Releases.php +++ b/Mage/Task/Releases.php @@ -3,6 +3,7 @@ class Mage_Task_Releases { private $_config = null; private $_action = null; + private $_release = null; public function setAction($action) { @@ -15,6 +16,17 @@ class Mage_Task_Releases 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; @@ -34,11 +46,16 @@ class Mage_Task_Releases $task->init(); $result = $task->run(); break; + + case 'rollback': + $task = Mage_Task_Factory::get('releases/rollback', $config); + $task->init(); + $task->setRelease($this->getRelease()); + $result = $task->run(); + break; } - Mage_Console::output(''); } } - } private function _listReleases() diff --git a/bin/mage.php b/bin/mage.php index 67b3a51..6024338 100644 --- a/bin/mage.php +++ b/bin/mage.php @@ -7,10 +7,11 @@ # 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 -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 diff --git a/docs/example-config/.mage/config/environment/production.yaml b/docs/example-config/.mage/config/environment/production.yaml index f50bb40..5874fb1 100644 --- a/docs/example-config/.mage/config/environment/production.yaml +++ b/docs/example-config/.mage/config/environment/production.yaml @@ -19,6 +19,5 @@ tasks: pre-deploy: - scm/update on-deploy: - - deployment/rsync - privileges #post-deploy: \ No newline at end of file diff --git a/docs/example-config/.mage/config/environment/staging.yaml b/docs/example-config/.mage/config/environment/staging.yaml index 7fb44e0..97b604a 100644 --- a/docs/example-config/.mage/config/environment/staging.yaml +++ b/docs/example-config/.mage/config/environment/staging.yaml @@ -9,6 +9,5 @@ tasks: pre-deploy: - scm/update on-deploy: - - deployment/rsync - privileges #post-deploy: \ No newline at end of file