mirror of
https://github.com/andres-montanez/Magallanes
synced 2024-06-09 01:02:15 +02:00
Merge 91979c4b56
into ef72936c52
This commit is contained in:
commit
686817ef20
|
@ -14,10 +14,10 @@ use Mage\Deploy\Strategy\StrategyInterface;
|
||||||
use Mage\Runtime\Exception\RuntimeException;
|
use Mage\Runtime\Exception\RuntimeException;
|
||||||
use Mage\Runtime\Runtime;
|
use Mage\Runtime\Runtime;
|
||||||
use Mage\Task\ExecuteOnRollbackInterface;
|
use Mage\Task\ExecuteOnRollbackInterface;
|
||||||
use Mage\Task\AbstractTask;
|
|
||||||
use Mage\Task\Exception\ErrorException;
|
use Mage\Task\Exception\ErrorException;
|
||||||
use Mage\Task\Exception\SkipException;
|
use Mage\Task\Exception\SkipException;
|
||||||
use Mage\Task\TaskFactory;
|
use Mage\Task\TaskFactory;
|
||||||
|
use Mage\Task\TaskInterface;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
@ -185,8 +185,17 @@ class DeployCommand extends AbstractCommand
|
||||||
$succeededTasks = 0;
|
$succeededTasks = 0;
|
||||||
|
|
||||||
foreach ($tasks as $taskName) {
|
foreach ($tasks as $taskName) {
|
||||||
/** @var AbstractTask $task */
|
$options = null;
|
||||||
$task = $this->taskFactory->get($taskName);
|
|
||||||
|
// Handle the options
|
||||||
|
if (is_array($taskName)) {
|
||||||
|
$options = $taskName;
|
||||||
|
$taskName = key($options);
|
||||||
|
$options = $options[$taskName];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var TaskInterface $task */
|
||||||
|
$task = $this->taskFactory->get($taskName, $options);
|
||||||
$output->write(sprintf(' Running <fg=magenta>%s</> ... ', $task->getDescription()));
|
$output->write(sprintf(' Running <fg=magenta>%s</> ... ', $task->getDescription()));
|
||||||
$this->log(sprintf('Running task %s (%s)', $task->getDescription(), $task->getName()));
|
$this->log(sprintf('Running task %s (%s)', $task->getDescription(), $task->getName()));
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ use Mage\Runtime\Runtime;
|
||||||
*
|
*
|
||||||
* @author Andrés Montañez <andresmontanez@gmail.com>
|
* @author Andrés Montañez <andresmontanez@gmail.com>
|
||||||
*/
|
*/
|
||||||
abstract class AbstractTask
|
abstract class AbstractTask implements TaskInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var array Task custom options
|
* @var array Task custom options
|
||||||
|
@ -29,27 +29,6 @@ abstract class AbstractTask
|
||||||
*/
|
*/
|
||||||
protected $runtime;
|
protected $runtime;
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the Name/Code of the Task
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
abstract public function getName();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a short Description of the Task
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
abstract public function getDescription();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes the Command
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
abstract public function execute();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set additional Options for the Task
|
* Set additional Options for the Task
|
||||||
*
|
*
|
||||||
|
|
|
@ -20,18 +20,21 @@ use ReflectionClass;
|
||||||
* Task Factory
|
* Task Factory
|
||||||
*
|
*
|
||||||
* @author Andrés Montañez <andresmontanez@gmail.com>
|
* @author Andrés Montañez <andresmontanez@gmail.com>
|
||||||
|
* @author Kamil Kuzminski <https://github.com/qzminski>
|
||||||
*/
|
*/
|
||||||
class TaskFactory
|
class TaskFactory
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
* Runtime
|
||||||
* @var Runtime
|
* @var Runtime
|
||||||
*/
|
*/
|
||||||
protected $runtime;
|
private $runtime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array Registered Tasks
|
* Registered tasks
|
||||||
|
* @var TaskInterface[]
|
||||||
*/
|
*/
|
||||||
protected $registeredTasks = [];
|
private $tasks = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
@ -48,11 +51,29 @@ class TaskFactory
|
||||||
* Add a Task
|
* Add a Task
|
||||||
*
|
*
|
||||||
* @param AbstractTask $task
|
* @param AbstractTask $task
|
||||||
|
*
|
||||||
|
* @deprecated Deprecated since 3.0, to be removed in 4.0.
|
||||||
|
* Use the TaskFactory::addTask() instead.
|
||||||
*/
|
*/
|
||||||
public function add(AbstractTask $task)
|
public function add(AbstractTask $task)
|
||||||
{
|
{
|
||||||
|
@trigger_error(
|
||||||
|
'Using TaskFactory::add() has been deprecated and will no longer work in 4.0. Use the TaskFactory::addTask() instead.',
|
||||||
|
E_USER_DEPRECATED
|
||||||
|
);
|
||||||
|
|
||||||
$task->setRuntime($this->runtime);
|
$task->setRuntime($this->runtime);
|
||||||
$this->registeredTasks[$task->getName()] = $task;
|
$this->tasks[$task->getName()] = $task;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a task
|
||||||
|
*
|
||||||
|
* @param TaskInterface $task
|
||||||
|
*/
|
||||||
|
public function addTask(TaskInterface $task)
|
||||||
|
{
|
||||||
|
$this->tasks[$task->getName()] = $task;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,58 +81,101 @@ class TaskFactory
|
||||||
* in that case the class will be instantiated
|
* in that case the class will be instantiated
|
||||||
*
|
*
|
||||||
* @param string $name Name/Code or Class of the Task
|
* @param string $name Name/Code or Class of the Task
|
||||||
* @return AbstractTask
|
* @param array $options
|
||||||
|
*
|
||||||
|
* @return TaskInterface
|
||||||
|
*
|
||||||
* @throws RuntimeException
|
* @throws RuntimeException
|
||||||
*/
|
*/
|
||||||
public function get($name)
|
public function get($name, array $options = null)
|
||||||
{
|
{
|
||||||
$options = [];
|
// TODO: backwards compatibility, remove in 4.0
|
||||||
if (is_array($name)) {
|
if (is_array($name)) {
|
||||||
$options = $name;
|
$options = $name;
|
||||||
list($name) = array_keys($name);
|
$name = key($options);
|
||||||
$options = $options[$name];
|
$options = $options[$name];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (array_key_exists($name, $this->registeredTasks)) {
|
if (array_key_exists($name, $this->tasks)) {
|
||||||
/** @var AbstractTask $task */
|
$task = $this->tasks[$name];
|
||||||
$task = $this->registeredTasks[$name];
|
} else {
|
||||||
$task->setOptions($options);
|
$task = $this->createTask($name);
|
||||||
return $task;
|
|
||||||
} elseif (class_exists($name)) {
|
|
||||||
$reflex = new ReflectionClass($name);
|
|
||||||
if ($reflex->isInstantiable()) {
|
|
||||||
$task = new $name();
|
|
||||||
if ($task instanceof AbstractTask) {
|
|
||||||
$task->setOptions($options);
|
|
||||||
$this->add($task);
|
|
||||||
return $task;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new RuntimeException(sprintf('Invalid task name "%s"', $name));
|
$task->setRuntime($this->runtime);
|
||||||
|
|
||||||
|
if ($options !== null) {
|
||||||
|
$task->setOptions($options);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $task;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load BuiltIn Tasks
|
* Load the built-in tasks
|
||||||
|
*
|
||||||
|
* @throws RuntimeException
|
||||||
*/
|
*/
|
||||||
protected function loadBuiltInTasks()
|
private function loadBuiltInTasks()
|
||||||
{
|
{
|
||||||
$finder = new Finder();
|
$finder = new Finder();
|
||||||
$finder->files()->in(__DIR__ . '/BuiltIn')->name('*Task.php');
|
$finder->files()->in(__DIR__.'/BuiltIn')->name('*Task.php');
|
||||||
|
|
||||||
/** @var SplFileInfo $file */
|
/** @var SplFileInfo $file */
|
||||||
foreach ($finder as $file) {
|
foreach ($finder as $file) {
|
||||||
$class = substr('\\Mage\\Task\\BuiltIn\\' . str_replace('/', '\\', $file->getRelativePathname()), 0, -4);
|
$class = substr('\\Mage\\Task\\BuiltIn\\'.str_replace('/', '\\', $file->getRelativePathname()), 0, -4);
|
||||||
if (class_exists($class)) {
|
$reflex = new ReflectionClass($class);
|
||||||
$reflex = new ReflectionClass($class);
|
|
||||||
if ($reflex->isInstantiable()) {
|
// Some classes found in the folder can be abstract
|
||||||
$task = new $class();
|
if (!$reflex->isInstantiable()) {
|
||||||
if ($task instanceof AbstractTask) {
|
continue;
|
||||||
$this->add($task);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->createTask($class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the task
|
||||||
|
*
|
||||||
|
* @param string $class
|
||||||
|
*
|
||||||
|
* @return TaskInterface
|
||||||
|
*
|
||||||
|
* @throws RuntimeException
|
||||||
|
*/
|
||||||
|
private function createTask($class)
|
||||||
|
{
|
||||||
|
$this->validateTask($class);
|
||||||
|
|
||||||
|
/** @var TaskInterface $task */
|
||||||
|
$task = new $class();
|
||||||
|
|
||||||
|
// Register the task
|
||||||
|
$this->addTask($task);
|
||||||
|
|
||||||
|
return $task;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate the task
|
||||||
|
*
|
||||||
|
* @param string $class
|
||||||
|
*
|
||||||
|
* @throws RuntimeException
|
||||||
|
*/
|
||||||
|
private function validateTask($class)
|
||||||
|
{
|
||||||
|
if (!class_exists($class)) {
|
||||||
|
throw new RuntimeException(sprintf('The class "%s" does not exist', $class));
|
||||||
|
}
|
||||||
|
|
||||||
|
$reflex = new ReflectionClass($class);
|
||||||
|
|
||||||
|
if (!$reflex->implementsInterface(TaskInterface::class)) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
sprintf('The class "%s" must implement the "%s" interface', $class, TaskInterface::class)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
60
src/Task/TaskInterface.php
Normal file
60
src/Task/TaskInterface.php
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* This file is part of the Magallanes package.
|
||||||
|
*
|
||||||
|
* (c) Andrés Montañez <andres@andresmontanez.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mage\Task;
|
||||||
|
|
||||||
|
use Mage\Runtime\Runtime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The task interface
|
||||||
|
*
|
||||||
|
* @author Kamil Kuzminski <https://github.com/qzminski>
|
||||||
|
*/
|
||||||
|
interface TaskInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the Name/Code of the Task
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a short Description of the Task
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getDescription();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes the Command
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function execute();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set additional Options for the Task
|
||||||
|
*
|
||||||
|
* @param array $options Options
|
||||||
|
*
|
||||||
|
* @return TaskInterface
|
||||||
|
*/
|
||||||
|
public function setOptions($options = []);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the Runtime instance
|
||||||
|
*
|
||||||
|
* @param Runtime $runtime
|
||||||
|
*
|
||||||
|
* @return TaskInterface
|
||||||
|
*/
|
||||||
|
public function setRuntime(Runtime $runtime);
|
||||||
|
}
|
|
@ -122,7 +122,7 @@ class DeployCommandMiscTasksTest extends TestCase
|
||||||
|
|
||||||
$tester->execute(['command' => $command->getName(), 'environment' => 'test']);
|
$tester->execute(['command' => $command->getName(), 'environment' => 'test']);
|
||||||
$this->assertEquals(7, $tester->getStatusCode());
|
$this->assertEquals(7, $tester->getStatusCode());
|
||||||
$this->assertContains('Invalid task name "invalid/task"', $tester->getDisplay());
|
$this->assertContains('The class "invalid/task" does not exist', $tester->getDisplay());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testBrokenGitBranch()
|
public function testBrokenGitBranch()
|
||||||
|
|
|
@ -18,29 +18,31 @@ use PHPUnit_Framework_TestCase as TestCase;
|
||||||
|
|
||||||
class TaskFactoryTest extends TestCase
|
class TaskFactoryTest extends TestCase
|
||||||
{
|
{
|
||||||
public function testNonInstantiable()
|
public function testClassNotExists()
|
||||||
{
|
{
|
||||||
$runtime = new Runtime();
|
|
||||||
$factory = new TaskFactory($runtime);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$factory->get('Traversable');
|
$this->getFactory()->get('Foobar');
|
||||||
} catch (Exception $exception) {
|
} catch (Exception $exception) {
|
||||||
$this->assertTrue($exception instanceof RuntimeException);
|
$this->assertTrue($exception instanceof RuntimeException);
|
||||||
$this->assertEquals('Invalid task name "Traversable"', $exception->getMessage());
|
$this->assertEquals('The class "Foobar" does not exist', $exception->getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testNotExtendingAbstractTask()
|
public function testNotImplementingInterface()
|
||||||
{
|
{
|
||||||
$runtime = new Runtime();
|
|
||||||
$factory = new TaskFactory($runtime);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$factory->get('stdClass');
|
$this->getFactory()->get('stdClass');
|
||||||
} catch (Exception $exception) {
|
} catch (Exception $exception) {
|
||||||
$this->assertTrue($exception instanceof RuntimeException);
|
$this->assertTrue($exception instanceof RuntimeException);
|
||||||
$this->assertEquals('Invalid task name "stdClass"', $exception->getMessage());
|
$this->assertEquals(
|
||||||
|
'The class "stdClass" must implement the "Mage\Task\TaskInterface" interface',
|
||||||
|
$exception->getMessage()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getFactory()
|
||||||
|
{
|
||||||
|
return new TaskFactory(new Runtime());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue