Skip to content

Commit

Permalink
Merge pull request #535 from michaelmoussa/only-for-stages
Browse files Browse the repository at this point in the history
Added way to execute tasks only for certain stages
  • Loading branch information
antonmedv committed Jan 26, 2016
2 parents dcccb73 + b20df44 commit 66c4543
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 7 deletions.
13 changes: 13 additions & 0 deletions src/Executor/ParallelExecutor.php
Expand Up @@ -9,6 +9,7 @@

use Deployer\Console\Output\OutputWatcher;
use Deployer\Console\Output\VerbosityString;
use Deployer\Server\Environment;
use Deployer\Task\Context;
use Pure\Server;
use Pure\Storage\ArrayStorage;
Expand Down Expand Up @@ -45,6 +46,11 @@ class ParallelExecutor implements ExecutorInterface
*/
private $servers;

/**
* @var \Deployer\Server\Environment[]
*/
private $environments;

/**
* @var \Symfony\Component\Console\Input\InputInterface
*/
Expand Down Expand Up @@ -128,6 +134,7 @@ public function run($tasks, $servers, $environments, $input, $output)
{
$this->tasks = $tasks;
$this->servers = $servers;
$this->environments = $environments;
$this->input = $input;
$this->output = new OutputWatcher($output);
$this->informer = new Informer($this->output);
Expand Down Expand Up @@ -286,6 +293,12 @@ public function sendTasks()

foreach ($this->servers as $serverName => $server) {
if ($task->runOnServer($serverName)) {
$env = isset($this->environments[$serverName]) ? $this->environments[$serverName] : $this->environments[$serverName] = new Environment();

if (count($task->getOnlyForStage()) > 0 && (!$env->has('stages') || !$task->runForStages($env->get('stages')))) {
continue;
}

$this->informer->onServer($serverName);
$this->tasksToDo[$serverName] = $taskName;
}
Expand Down
4 changes: 4 additions & 0 deletions src/Executor/SeriesExecutor.php
Expand Up @@ -33,6 +33,10 @@ public function run($tasks, $servers, $environments, $input, $output)
if ($task->runOnServer($serverName)) {
$env = isset($environments[$serverName]) ? $environments[$serverName] : $environments[$serverName] = new Environment();

if (count($task->getOnlyForStage()) > 0 && (!$env->has('stages') || !$task->runForStages($env->get('stages')))) {
continue;
}

$informer->onServer($serverName);

try {
Expand Down
42 changes: 41 additions & 1 deletion src/Task/Task.php
Expand Up @@ -32,6 +32,12 @@ class Task
*/
private $once = false;

/**
* List of stages in which this task should be executed.
* @var array Key contains stage names.
*/
private $onlyForStage = [];

/**
* List of servers names there this task should be executed.
* @var array Key contains server names.
Expand Down Expand Up @@ -135,14 +141,48 @@ public function onlyOn($servers = [])
return $this;
}

/**
* Indicate for which stages this task should be run.
*
* @param array|string $stages
* @return $this
*/
public function onlyForStage($stages = [])
{
$this->onlyForStage = array_flip(is_array($stages) ? $stages: func_get_args());
return $this;
}

/**
* @return array
*/
public function getOnlyOn()
{
return $this->onlyOn;
}


/**
* @return array
*/
public function getOnlyForStage()
{
return $this->onlyForStage;
}

/**
* Decide to run or not to run for these stages.
* @param $stages
* @return bool
*/
public function runForStages($stages)
{
if (empty($this->onlyForStage)) {
return true;
} else {
return count(array_intersect($stages, array_keys($this->onlyForStage))) > 0;
}
}

/**
* Decide to run or not to run on this server.
* @param string $serverName
Expand Down
18 changes: 17 additions & 1 deletion test/fixture/recipe.php
@@ -1,9 +1,25 @@
<?php

require __DIR__ . '/../../recipe/common.php';

localServer('localhost');
localServer('server1');
localServer('server2');
localServer('server3')
->stage('production');
localServer('server4')
->stage('production');

task('test', function () {
task('test:hello', function () {
writeln('Hello world!');
});

task('test:onlyForStage', function () {
writeln('You should only see this for production');
})
->onlyForStage('production');

task('test', [
'test:hello',
'test:onlyForStage'
]);
17 changes: 15 additions & 2 deletions test/src/Executor/ParallelExecutorTest.php
Expand Up @@ -26,12 +26,25 @@ protected function loadRecipe()
include $this->recipeFile = __DIR__ . '/../../fixture/recipe.php';
}

public function testParallel()
public static function setUpBeforeClass()
{
define('DEPLOYER_BIN', __DIR__ . '/../../../bin/dep');

}

public function testParallel()
{
$display = $this->exec('test', ['--parallel' => true, '--file' => $this->recipeFile]);

$this->assertContains('Ok', $display);
$this->assertNotContains('You should only see this for production', $display);
}

public function testParallelWithStage()
{
$display = $this->exec('test', ['--parallel' => true, '--file' => $this->recipeFile, 'stage' => 'production']);

$this->assertContains('Ok', $display);
$this->assertContains('[server3] You should only see this for production', $display);
$this->assertContains('[server4] You should only see this for production', $display);
}
}
13 changes: 11 additions & 2 deletions test/src/Executor/SeriesExecutorTest.php
Expand Up @@ -21,7 +21,7 @@ public function testSeriesExecutor()
$this->initialize();

$mock = $this->getMockBuilder('stdClass')
->setMethods(['task', 'once', 'only'])
->setMethods(['task', 'once', 'only', 'onlyStaging'])
->getMock();

$mock->expects($this->exactly(2))
Expand All @@ -30,6 +30,8 @@ public function testSeriesExecutor()
->method('once');
$mock->expects($this->once())
->method('only');
$mock->expects($this->once())
->method('onlyStaging');

$task = new Task('task', function () use ($mock) {
$mock->task();
Expand All @@ -45,12 +47,19 @@ public function testSeriesExecutor()
});
$taskOnly->onlyOn(['one']);

$tasks = [$task, $taskOne, $taskOnly];
$taskOnlyStaging = new Task('onlyStaging', function () use ($mock) {
$mock->onlyStaging();
});
$taskOnlyStaging->onlyForStage('staging');

$tasks = [$task, $taskOne, $taskOnly, $taskOnlyStaging];

$environments = [
'one' => new Environment(),
'two' => new Environment(),
];
$environments['two']->set('stages', ['staging']);

$servers = [
'one' => new Local(),
'two' => new Local(),
Expand Down
17 changes: 16 additions & 1 deletion test/src/Task/TaskTest.php
Expand Up @@ -44,8 +44,23 @@ public function testTask()

$task->onlyOn();
$this->assertTrue($task->runOnServer('server'));

$task->setPrivate();
$this->assertTrue($task->isPrivate());

$task->onlyForStage(['staging', 'production']);
$this->assertEquals(['staging' => 0, 'production' => 1], $task->getOnlyForStage());
$this->assertTrue($task->runForStages(['staging']));
$this->assertTrue($task->runForStages(['production']));
$this->assertTrue($task->runForStages(['staging', 'production']));

$task->onlyForStage('staging', 'production');
$this->assertEquals(['staging' => 0, 'production' => 1], $task->getOnlyForStage());
$this->assertTrue($task->runForStages(['staging']));
$this->assertTrue($task->runForStages(['production']));
$this->assertTrue($task->runForStages(['staging', 'production']));

$task->onlyForStage();
$this->assertTrue($task->runForStages('anything'));
}
}

0 comments on commit 66c4543

Please sign in to comment.