* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Mage\Command\BuiltIn\Releases; use Mage\Task\TaskFactory; use Mage\Runtime\Exception\RuntimeException; use Symfony\Component\Process\Process; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Output\OutputInterface; use Mage\Command\BuiltIn\DeployCommand; /** * Command for Rolling Back a Releases * * @author Andrés Montañez */ class RollbackCommand extends DeployCommand { /** * @var int */ protected $statusCode = 0; /** * Configure the Command */ protected function configure() { $this ->setName('releases:rollback') ->setDescription('Rollback to a release on an environment') ->addArgument('environment', InputArgument::REQUIRED, 'Name of the environment to deploy to') ->addArgument('release', InputArgument::REQUIRED, 'The ID or the Index of the release to rollback to') ; } /** * Execute the Command * * @param InputInterface $input * @param OutputInterface $output * @return int|mixed */ protected function execute(InputInterface $input, OutputInterface $output) { $this->requireConfig(); $output->writeln('Starting Magallanes'); $output->writeln(''); try { $this->runtime->setEnvironment($input->getArgument('environment')); $strategy = $this->runtime->guessStrategy(); $this->taskFactory = new TaskFactory($this->runtime); if (!$this->runtime->getEnvOption('releases', false)) { throw new RuntimeException('Releases are not enabled', 70); } $releaseToRollback = $input->getArgument('release'); if (($releaseId = $this->checkReleaseAvailability($releaseToRollback)) === false) { throw new RuntimeException(sprintf('Release "%s" is not available on all hosts', $releaseToRollback), 72); } $this->runtime->setReleaseId($releaseId)->setRollback(true); $output->writeln(sprintf(' Environment: %s', $this->runtime->getEnvironment())); $this->log(sprintf('Environment: %s', $this->runtime->getEnvironment())); $output->writeln(sprintf(' Rollback to Release Id: %s', $this->runtime->getReleaseId())); $this->log(sprintf('Release ID: %s', $this->runtime->getReleaseId())); if ($this->runtime->getConfigOption('log_file', false)) { $output->writeln(sprintf(' Logfile: %s', $this->runtime->getConfigOption('log_file'))); } $output->writeln(sprintf(' Strategy: %s', $strategy->getName())); $output->writeln(''); $this->runDeployment($output, $strategy); } catch (RuntimeException $exception) { $output->writeln(sprintf('%s', $exception->getMessage())); $this->statusCode = $exception->getCode(); } $output->writeln('Finished Magallanes'); return $this->statusCode; } /** * Check if the provided Release ID is available in all hosts * * @param string $releaseToRollback Release ID * @return bool */ protected function checkReleaseAvailability($releaseToRollback) { $hosts = $this->runtime->getEnvOption('hosts'); $hostPath = rtrim($this->runtime->getEnvOption('host_path'), '/'); $availableInHosts = 0; foreach ($hosts as $host) { $releases = []; $this->runtime->setWorkingHost($host); // Get List of Releases $cmdListReleases = sprintf('ls -1 %s/releases', $hostPath); /** @var Process $process */ $process = $this->runtime->runRemoteCommand($cmdListReleases, false); if ($process->isSuccessful()) { $releases = explode("\n", trim($process->getOutput())); rsort($releases); } if (in_array($releaseToRollback, $releases)) { $availableInHosts++; } $this->runtime->setWorkingHost(null); } if ($availableInHosts === count($hosts)) { return $releaseToRollback; } return false; } }