Merge pull request #35 from jelte/feature/multistage

Simple multistage support
This commit is contained in:
Anton 2014-08-07 11:38:26 +04:00
commit d5b8f6aa25
5 changed files with 191 additions and 7 deletions

View File

@ -8,12 +8,14 @@
namespace Deployer\Console;
use Deployer\Deployer;
use Deployer\Server\DryRun;
use Deployer\Environment;
use Deployer\Server\ServerInterface;
use Deployer\Stage\Stage;
use Deployer\Task\AbstractTask;
use Deployer\Task\Runner;
use Deployer\Task\TaskInterface;
use Symfony\Component\Console\Command\Command as BaseCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
@ -45,6 +47,13 @@ class RunTaskCommand extends BaseCommand
'Run without execution command on servers.'
);
$this->addArgument(
'stage',
InputArgument::OPTIONAL,
'Run tasks for a specific environment',
Deployer::$defaultStage
);
$this->addOption(
'server',
null,
@ -60,12 +69,29 @@ class RunTaskCommand extends BaseCommand
// Nothing to do now.
}
$servers = Deployer::$servers;
if (Deployer::$multistage) {
if (null === $input->getArgument('stage')) {
throw new \InvalidArgumentException('You have turned on multistage support, but not defined a stage (or default stage).');
}
if (!isset(Deployer::$stages[$input->getArgument('stage')])) {
throw new \InvalidArgumentException('This stage is not defined.');
}
/** @var Stage $stage */
$stage = Deployer::$stages[$input->getArgument('stage')];
$servers = $stage->getServers();
foreach ( $stage->getOptions() as $key => $value ) {
set($key, $value);
}
}
try {
foreach ($this->task->get() as $runner) {
$isPrinted = $this->writeDesc($output, $runner->getDesc());
$this->runSeries($runner, $input, $output);
$this->runSeries($runner, $servers, $input, $output);
if ($isPrinted) {
$this->writeOk($output);
@ -73,17 +99,21 @@ class RunTaskCommand extends BaseCommand
}
} catch (\Exception $e) {
$this->rollbackOnDeploy($input, $output);
$this->rollbackOnDeploy($servers, $input, $output);
throw $e;
}
}
private function runSeries(Runner $runner, InputInterface $input, OutputInterface $output)
private function runSeries(Runner $runner, array $servers, InputInterface $input, OutputInterface $output)
{
$taskName = $runner->getName();
$taskName = empty($taskName) ? 'UnNamed' : $taskName;
foreach (Deployer::$servers as $name => $server) {
/**
* @var string $name
* @var ServerInterface $server
*/
foreach ($servers as $name => $server) {
// Skip to specified server.
$onServer = $input->getOption('server');
if (null !== $onServer && $onServer !== $name) {
@ -150,7 +180,7 @@ class RunTaskCommand extends BaseCommand
* @param InputInterface $input
* @param OutputInterface $output
*/
private function rollbackOnDeploy(InputInterface $input, OutputInterface $output)
private function rollbackOnDeploy(array $servers, InputInterface $input, OutputInterface $output)
{
if (!isset(Deployer::$tasks['deploy:rollback'])) {
return;
@ -159,7 +189,7 @@ class RunTaskCommand extends BaseCommand
$task = Deployer::$tasks['deploy:rollback'];
foreach ($task->get() as $runner) {
$this->runSeries($runner, $input, $output);
$this->runSeries($runner, $servers, $input, $output);
}
}
}

View File

@ -56,6 +56,25 @@ class Deployer
*/
public static $servers = [];
/**
* Turn on/off multistage support
* @var bool
*/
public static $multistage = false;
/**
* Default deploy stage
* @var string
*/
public static $defaultStage = 'develop';
/**
* List of all stages.
* @var array[]
*/
public static $stages = [];
/**
* Array of global parameters.
* @var array

66
src/Stage/Stage.php Normal file
View File

@ -0,0 +1,66 @@
<?php
namespace Deployer\Stage;
class Stage
{
/**
* @var string
*/
protected $name;
/**
* @var array
*/
protected $servers = [];
/**
* @var array
*/
protected $options = [];
/**
* @param string $name Name of the stage
* @param array $servers List of servers
* @param array $options List of additional options
*/
public function __construct($name, array $servers, array $options = array())
{
$this->name = $name;
$this->servers = $servers;
$this->options = $options;
}
public function getName()
{
return $this->name;
}
public function getServers()
{
return $this->servers;
}
public function options(array $options)
{
$this->options = $options;
}
public function set($key, $value)
{
return $this->options[$key] = $value;
}
public function get($key, $default)
{
return array_key_exists($key, $this->options) ? $this->options[$key] : $default;
}
public function getOptions()
{
return $this->options;
}
}

View File

@ -0,0 +1,46 @@
<?php
namespace Deployer\Stage;
use Deployer\Deployer;
class StageFactory
{
/**
* @param $name
* @param array $servers
* @param bool $default
* @return Stage
* @throws \RuntimeException
*/
public static function create($name, array $servers, array $options = array(), $default = false)
{
if ( count(Deployer::$servers) == 0 ) {
throw new \RuntimeException('Server should be defined before you define any stages.');
}
// Automatically turn on multistage support when creating a stage
Deployer::$multistage = true;
// Make the server list for this stage
$servers = array_combine($servers, $servers);
array_walk($servers, function(&$value, $name) {
if ( !isset(Deployer::$servers[$name]) ) {
throw new \RuntimeException(sprintf('Server "%s" not found', $name));
}
$value = Deployer::$servers[$name];
});
// Register the stage serverlist
Deployer::$stages[$name] = new Stage($name, $servers, $options);
// When defined as default, set the stage as default on Deployer
if ( $default ) {
Deployer::$defaultStage = $name;
}
return Deployer::$stages[$name];
}
}

View File

@ -7,6 +7,7 @@
use Deployer\Deployer;
use Deployer\Environment;
use Deployer\Server;
use Deployer\Stage;
use Deployer\Task;
use Deployer\Utils;
@ -21,6 +22,28 @@ function server($name, $domain, $port = 22)
return Server\ServerFactory::create($name, $domain, $port);
}
/**
* @param string $defaultStage
*/
function multistage($defaultStage = 'develop')
{
Deployer::$multistage = true;
Deployer::$defaultStage = $defaultStage;
}
/**
* Define a new stage
* @param string $name Name of current stage
* @param array $servers List of servers
* @param array $options List of addition options
* @param bool $default Set as default stage
* @return Stage\Stage
*/
function stage($name, array $servers, array $options = array(), $default = false)
{
return Stage\StageFactory::create($name, $servers, $options, $default);
}
/**
* Define a new task and save to tasks list.
* @param string $name Name of current task.