From 03b158c0a59d324b099e2fb793433f5168012f37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Monta=C3=B1ez?= Date: Fri, 8 Nov 2013 13:42:34 -0200 Subject: [PATCH] Abort Deployment when pre-deploy task fails. Addresses issue #29 --- Mage/Command/BuiltIn/DeployCommand.php | 349 ++++++++++-------- .../.mage/config/environment/staging.yml | 5 +- docs/example-config/.mage/tasks/FailTask.php | 17 + 3 files changed, 212 insertions(+), 159 deletions(-) create mode 100644 docs/example-config/.mage/tasks/FailTask.php diff --git a/Mage/Command/BuiltIn/DeployCommand.php b/Mage/Command/BuiltIn/DeployCommand.php index 7340e67..427b12e 100644 --- a/Mage/Command/BuiltIn/DeployCommand.php +++ b/Mage/Command/BuiltIn/DeployCommand.php @@ -70,8 +70,18 @@ class DeployCommand extends AbstractCommand implements RequiresEnvironment */ protected $hostsCount = 0; + /** + * Current Status of the Deployment (in progress, succeded, failed) + * @var string + */ protected static $deployStatus = 'in_progress'; + /** + * Total of Failed tasks + * @var integer + */ + protected static $failedTasks = 0; + /** * Returns the Status of the Deployment * @@ -105,7 +115,6 @@ class DeployCommand extends AbstractCommand implements RequiresEnvironment // Release ID $this->getConfig()->setReleaseId(date('YmdHis')); - $failedTasks = 0; // Deploy Summary Console::output('Deploy summary', 1, 1); @@ -134,168 +143,25 @@ class DeployCommand extends AbstractCommand implements RequiresEnvironment // Run Pre-Deployment Tasks $this->runNonDeploymentTasks('pre-deploy', $this->getConfig(), 'Pre-Deployment'); - // Run Tasks for Deployment - $hosts = $this->getConfig()->getHosts(); - $this->hostsCount = count($hosts); - - if ($this->hostsCount == 0) { - Console::output('Warning! No hosts defined, skipping deployment tasks.', 1, 3); + // Check Status + if (self::$failedTasks > 0) { + self::$deployStatus = self::FAILED; + Console::output('A total of ' . self::$failedTasks . ' deployment tasks failed: ABORTING', 1, 2); } else { - $this->startTimeHosts = time(); - foreach ($hosts as $hostKey => $host) { + // Run Deployment Tasks + $this->runDeploymentTasks(); - // Check if Host has specific configuration - $hostConfig = null; - if (is_array($host)) { - $hostConfig = $host; - $host = $hostKey; - } + // Check Status + if (self::$failedTasks > 0) { + self::$deployStatus = self::FAILED; + Console::output('A total of ' . self::$failedTasks . ' deployment tasks failed: ABORTING', 1, 2); + } - // Set Host and Host Specific Config - $this->getConfig()->setHost($host); - $this->getConfig()->setHostConfig($hostConfig); - - // Prepare Tasks - $tasks = 0; - $completedTasks = 0; - - Console::output('Deploying to ' . $this->getConfig()->getHost() . ''); - - $tasksToRun = $this->getConfig()->getTasks(); - - // Guess a Deploy Strategy - switch ($this->getConfig()->deployment('strategy', 'guess')) { - case 'rsync': - $deployStrategy = 'deployment/strategy/rsync'; - break; - - case 'targz': - $deployStrategy = 'deployment/strategy/tar-gz'; - break; - - case 'guess': - default: - if ($this->getConfig()->release('enabled', false) == true) { - $deployStrategy = 'deployment/strategy/tar-gz'; - } else { - $deployStrategy = 'deployment/strategy/rsync'; - } - break; - } - array_unshift($tasksToRun, $deployStrategy); - - if (count($tasksToRun) == 0) { - Console::output('Warning! No Deployment tasks defined.', 2); - Console::output('Deployment to ' . $host . ' skipped!', 1, 3); - - } else { - foreach ($tasksToRun as $taskData) { - $tasks++; - $task = Factory::get($taskData, $this->getConfig(), false, 'deploy'); - - if ($this->runTask($task)) { - $completedTasks++; - } else { - $failedTasks++; - } - } - - if ($completedTasks == $tasks) { - $tasksColor = 'green'; - } else { - $tasksColor = 'red'; - } - - Console::output('Deployment to ' . $this->getConfig()->getHost() . ' completed: <' . $tasksColor . '>' . $completedTasks . '/' . $tasks . ' tasks done.', 1, 3); - } - - // Reset Host Config - $this->getConfig()->setHostConfig(null); - } - $this->endTimeHosts = time(); - - if ($failedTasks > 0) { - self::$deployStatus = self::FAILED; - Console::output('A total of ' . $failedTasks . ' deployment tasks failed: ABORTING', 1, 2); - } else { - self::$deployStatus = self::SUCCEDED; - } - - // Releasing - if (self::$deployStatus == self::SUCCEDED && $this->getConfig()->release('enabled', false) == true) { - // Execute the Releases - Console::output('Starting the Releaseing'); - foreach ($hosts as $hostKey => $host) { - - // Check if Host has specific configuration - $hostConfig = null; - if (is_array($host)) { - $hostConfig = $host; - $host = $hostKey; - } - - // Set Host - $this->getConfig()->setHost($host); - $this->getConfig()->setHostConfig($hostConfig); - - $task = Factory::get('deployment/release', $this->getConfig(), false, 'deploy'); - - if ($this->runTask($task, 'Releasing on host ' . $host . ' ... ')) { - $completedTasks++; - } - - // Reset Host Config - $this->getConfig()->setHostConfig(null); - } - Console::output('Finished the Releaseing', 1, 3); - - // Execute the Post-Release Tasks - foreach ($hosts as $hostKey => $host) { - - // Check if Host has specific configuration - $hostConfig = null; - if (is_array($host)) { - $hostConfig = $host; - $host = $hostKey; - } - - // Set Host - $this->getConfig()->setHost($host); - $this->getConfig()->setHostConfig($hostConfig); - - $tasksToRun = $this->getConfig()->getTasks('post-release'); - $tasks = count($tasksToRun); - $completedTasks = 0; - - if (count($tasksToRun) > 0) { - Console::output('Starting Post-Release tasks for ' . $host . ':'); - - foreach ($tasksToRun as $task) { - $task = Factory::get($task, $this->getConfig(), false, 'post-release'); - - if ($this->runTask($task)) { - $completedTasks++; - } - } - - if ($completedTasks == $tasks) { - $tasksColor = 'green'; - } else { - $tasksColor = 'red'; - } - Console::output('Finished Post-Release tasks for ' . $host . ': <' . $tasksColor . '>' . $completedTasks . '/' . $tasks . ' tasks done.', 1, 3); - } - - // Reset Host Config - $this->getConfig()->setHostConfig(null); - } - } + // Run Post-Deployment Tasks + $this->runNonDeploymentTasks('post-deploy', $this->getConfig(), 'Post-Deployment'); } - // Run Post-Deployment Tasks - $this->runNonDeploymentTasks('post-deploy', $this->getConfig(), 'Post-Deployment'); - // Time Information Hosts if ($this->hostsCount > 0) { $timeTextHost = $this->transcurredTime($this->endTimeHosts - $this->startTimeHosts); @@ -328,6 +194,7 @@ class DeployCommand extends AbstractCommand implements RequiresEnvironment protected function runNonDeploymentTasks($stage, Config $config, $title) { $tasksToRun = $config->getTasks($stage); + self::$failedTasks = 0; // PreDeployment Hook if ($stage == 'pre-deploy') { @@ -376,6 +243,8 @@ class DeployCommand extends AbstractCommand implements RequiresEnvironment if ($this->runTask($task)) { $completedTasks++; + } else { + self::$failedTasks++; } } @@ -389,6 +258,172 @@ class DeployCommand extends AbstractCommand implements RequiresEnvironment } } + protected function runDeploymentTasks() + { + if (self::$deployStatus == self::FAILED) { + return; + } + + // Run Tasks for Deployment + $hosts = $this->getConfig()->getHosts(); + $this->hostsCount = count($hosts); + self::$failedTasks = 0; + + if ($this->hostsCount == 0) { + Console::output('Warning! No hosts defined, skipping deployment tasks.', 1, 3); + + } else { + $this->startTimeHosts = time(); + foreach ($hosts as $hostKey => $host) { + + // Check if Host has specific configuration + $hostConfig = null; + if (is_array($host)) { + $hostConfig = $host; + $host = $hostKey; + } + + // Set Host and Host Specific Config + $this->getConfig()->setHost($host); + $this->getConfig()->setHostConfig($hostConfig); + + // Prepare Tasks + $tasks = 0; + $completedTasks = 0; + + Console::output('Deploying to ' . $this->getConfig()->getHost() . ''); + + $tasksToRun = $this->getConfig()->getTasks(); + + // Guess a Deploy Strategy + switch ($this->getConfig()->deployment('strategy', 'guess')) { + case 'rsync': + $deployStrategy = 'deployment/strategy/rsync'; + break; + + case 'targz': + $deployStrategy = 'deployment/strategy/tar-gz'; + break; + + case 'guess': + default: + if ($this->getConfig()->release('enabled', false) == true) { + $deployStrategy = 'deployment/strategy/tar-gz'; + } else { + $deployStrategy = 'deployment/strategy/rsync'; + } + break; + } + array_unshift($tasksToRun, $deployStrategy); + + if (count($tasksToRun) == 0) { + Console::output('Warning! No Deployment tasks defined.', 2); + Console::output('Deployment to ' . $host . ' skipped!', 1, 3); + + } else { + foreach ($tasksToRun as $taskData) { + $tasks++; + $task = Factory::get($taskData, $this->getConfig(), false, 'deploy'); + + if ($this->runTask($task)) { + $completedTasks++; + } else { + self::$failedTasks++; + } + } + + if ($completedTasks == $tasks) { + $tasksColor = 'green'; + } else { + $tasksColor = 'red'; + } + + Console::output('Deployment to ' . $this->getConfig()->getHost() . ' completed: <' . $tasksColor . '>' . $completedTasks . '/' . $tasks . ' tasks done.', 1, 3); + } + + // Reset Host Config + $this->getConfig()->setHostConfig(null); + } + $this->endTimeHosts = time(); + + if (self::$failedTasks > 0) { + self::$deployStatus = self::FAILED; + } else { + self::$deployStatus = self::SUCCEDED; + } + + // Releasing + if (self::$deployStatus == self::SUCCEDED && $this->getConfig()->release('enabled', false) == true) { + // Execute the Releases + Console::output('Starting the Releaseing'); + foreach ($hosts as $hostKey => $host) { + + // Check if Host has specific configuration + $hostConfig = null; + if (is_array($host)) { + $hostConfig = $host; + $host = $hostKey; + } + + // Set Host + $this->getConfig()->setHost($host); + $this->getConfig()->setHostConfig($hostConfig); + + $task = Factory::get('deployment/release', $this->getConfig(), false, 'deploy'); + + if ($this->runTask($task, 'Releasing on host ' . $host . ' ... ')) { + $completedTasks++; + } + + // Reset Host Config + $this->getConfig()->setHostConfig(null); + } + Console::output('Finished the Releaseing', 1, 3); + + // Execute the Post-Release Tasks + foreach ($hosts as $hostKey => $host) { + + // Check if Host has specific configuration + $hostConfig = null; + if (is_array($host)) { + $hostConfig = $host; + $host = $hostKey; + } + + // Set Host + $this->getConfig()->setHost($host); + $this->getConfig()->setHostConfig($hostConfig); + + $tasksToRun = $this->getConfig()->getTasks('post-release'); + $tasks = count($tasksToRun); + $completedTasks = 0; + + if (count($tasksToRun) > 0) { + Console::output('Starting Post-Release tasks for ' . $host . ':'); + + foreach ($tasksToRun as $task) { + $task = Factory::get($task, $this->getConfig(), false, 'post-release'); + + if ($this->runTask($task)) { + $completedTasks++; + } + } + + if ($completedTasks == $tasks) { + $tasksColor = 'green'; + } else { + $tasksColor = 'red'; + } + Console::output('Finished Post-Release tasks for ' . $host . ': <' . $tasksColor . '>' . $completedTasks . '/' . $tasks . ' tasks done.', 1, 3); + } + + // Reset Host Config + $this->getConfig()->setHostConfig(null); + } + } + } + } + /** * Runs a Task * diff --git a/docs/example-config/.mage/config/environment/staging.yml b/docs/example-config/.mage/config/environment/staging.yml index 04d0c88..c3db3ef 100644 --- a/docs/example-config/.mage/config/environment/staging.yml +++ b/docs/example-config/.mage/config/environment/staging.yml @@ -4,18 +4,19 @@ deployment: from: ./ to: /var/www/ scm: - branch: master2 + branch: master releases: enabled: true max: 5 symlink: current directory: releases hosts: -# - localhost + - localhost # - dbserver tasks: pre-deploy: - sampleTask +# - failTask - scm/update on-deploy: - privileges diff --git a/docs/example-config/.mage/tasks/FailTask.php b/docs/example-config/.mage/tasks/FailTask.php new file mode 100644 index 0000000..91e9c52 --- /dev/null +++ b/docs/example-config/.mage/tasks/FailTask.php @@ -0,0 +1,17 @@ +