From c7976d9d770ea06b84a8c4afa176125d4070c720 Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Sat, 24 Oct 2015 13:40:40 +0200 Subject: [PATCH 01/11] Make it possible to hook in with events + Add a run command --- composer.json | 1 + resources/config/services.yml | 9 ++ .../Console/Helper/TaskRunnerHelperSpec.php | 16 +++- spec/GrumPHP/Event/RunnerEventSpec.php | 30 ++++++ spec/GrumPHP/Event/RunnerFailedEventSpec.php | 35 +++++++ .../Subscriber/ProgressSubscriberSpec.php | 69 ++++++++++++++ spec/GrumPHP/Event/TaskEventSpec.php | 31 +++++++ spec/GrumPHP/Event/TaskFailedEventSpec.php | 37 ++++++++ spec/GrumPHP/Locator/RegisteredFilesSpec.php | 37 ++++++++ spec/GrumPHP/Runner/TaskRunnerSpec.php | 48 +++++++++- spec/GrumPHP/Task/BehatSpec.php | 6 ++ spec/GrumPHP/Task/PhpcsSpec.php | 7 ++ spec/GrumPHP/Task/PhpcsfixerSpec.php | 6 ++ spec/GrumPHP/Task/PhpspecSpec.php | 6 ++ spec/GrumPHP/Task/PhpunitSpec.php | 6 ++ .../{ => Compiler}/TaskCompilerPass.php | 4 +- .../Configuration/ContainerFactory.php | 6 +- src/GrumPHP/Console/Application.php | 7 +- src/GrumPHP/Console/Command/RunCommand.php | 91 ++++++++++++++++++ .../Console/Helper/TaskRunnerHelper.php | 25 ++++- src/GrumPHP/Event/RunnerEvent.php | 35 +++++++ src/GrumPHP/Event/RunnerEvents.php | 15 +++ src/GrumPHP/Event/RunnerFailedEvent.php | 36 +++++++ .../Event/Subscriber/ProgressSubscriber.php | 93 +++++++++++++++++++ src/GrumPHP/Event/TaskEvent.php | 35 +++++++ src/GrumPHP/Event/TaskEvents.php | 15 +++ src/GrumPHP/Event/TaskFailedEvent.php | 39 ++++++++ src/GrumPHP/Locator/RegisteredFiles.php | 45 +++++++++ src/GrumPHP/Runner/TaskRunner.php | 30 +++++- src/GrumPHP/Task/Behat.php | 3 +- src/GrumPHP/Task/Context/RunContext.php | 35 +++++++ src/GrumPHP/Task/Phpcs.php | 3 +- src/GrumPHP/Task/Phpcsfixer.php | 3 +- src/GrumPHP/Task/Phpspec.php | 3 +- src/GrumPHP/Task/Phpunit.php | 3 +- 35 files changed, 851 insertions(+), 19 deletions(-) create mode 100644 spec/GrumPHP/Event/RunnerEventSpec.php create mode 100644 spec/GrumPHP/Event/RunnerFailedEventSpec.php create mode 100644 spec/GrumPHP/Event/Subscriber/ProgressSubscriberSpec.php create mode 100644 spec/GrumPHP/Event/TaskEventSpec.php create mode 100644 spec/GrumPHP/Event/TaskFailedEventSpec.php create mode 100644 spec/GrumPHP/Locator/RegisteredFilesSpec.php rename src/GrumPHP/Configuration/{ => Compiler}/TaskCompilerPass.php (93%) create mode 100644 src/GrumPHP/Console/Command/RunCommand.php create mode 100644 src/GrumPHP/Event/RunnerEvent.php create mode 100644 src/GrumPHP/Event/RunnerEvents.php create mode 100644 src/GrumPHP/Event/RunnerFailedEvent.php create mode 100644 src/GrumPHP/Event/Subscriber/ProgressSubscriber.php create mode 100644 src/GrumPHP/Event/TaskEvent.php create mode 100644 src/GrumPHP/Event/TaskEvents.php create mode 100644 src/GrumPHP/Event/TaskFailedEvent.php create mode 100644 src/GrumPHP/Locator/RegisteredFiles.php create mode 100644 src/GrumPHP/Task/Context/RunContext.php diff --git a/composer.json b/composer.json index 8da934a49..50f737957 100644 --- a/composer.json +++ b/composer.json @@ -8,6 +8,7 @@ "composer-plugin-api": "~1.0", "symfony/console": "^2.4", "symfony/expression-language": "^2.4", + "symfony/event-dispatcher": "^2.4", "symfony/process": "^2.4", "symfony/filesystem": "^2.4", "symfony/finder": "^2.4", diff --git a/resources/config/services.yml b/resources/config/services.yml index 3b82e0f39..b5104ab28 100644 --- a/resources/config/services.yml +++ b/resources/config/services.yml @@ -12,6 +12,9 @@ services: class: GrumPHP\Configuration\GrumPHP arguments: [@service_container] + event_dispatcher: + class: Symfony\Component\EventDispatcher\EventDispatcher + filesystem: class: Symfony\Component\Filesystem\Filesystem @@ -29,6 +32,8 @@ services: task_runner: class: GrumPHP\Runner\TaskRunner + arguments: + - @event_dispatcher locator.external_command: class: GrumPHP\Locator\ExternalCommand @@ -38,6 +43,10 @@ services: class: GrumPHP\Locator\ChangedFiles arguments: [@git.repository] + locator.registered_files: + class: GrumPHP\Locator\RegisteredFiles + arguments: [@git.repository] + task.phpcs: class: GrumPHP\Task\Phpcs arguments: diff --git a/spec/GrumPHP/Console/Helper/TaskRunnerHelperSpec.php b/spec/GrumPHP/Console/Helper/TaskRunnerHelperSpec.php index 396300bff..d5fb0880d 100644 --- a/spec/GrumPHP/Console/Helper/TaskRunnerHelperSpec.php +++ b/spec/GrumPHP/Console/Helper/TaskRunnerHelperSpec.php @@ -10,15 +10,16 @@ use GrumPHP\Task\Context\ContextInterface; use Symfony\Component\Console\Helper\HelperSet; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\Filesystem\Filesystem; use PhpSpec\ObjectBehavior; use Prophecy\Argument; class TaskRunnerHelperSpec extends ObjectBehavior { - function let(TaskRunner $taskRunner, HelperSet $helperSet, PathsHelper $pathsHelper) + function let(TaskRunner $taskRunner, EventDispatcherInterface $eventDispatcher, HelperSet $helperSet, PathsHelper $pathsHelper) { - $this->beConstructedWith($taskRunner); + $this->beConstructedWith($taskRunner, $eventDispatcher); $helperSet->get(PathsHelper::HELPER_NAME)->willreturn($pathsHelper); $this->setHelperSet($helperSet); @@ -35,4 +36,15 @@ function it_should_return_success_code_during_exceptions(OutputInterface $output $taskRunner->run($context)->shouldBeCalled(); $this->run($output, $context)->shouldReturn(TaskRunnerHelper::CODE_SUCCESS); } + + function it_should_add_a_progress_listener_during_run( + OutputInterface $output, + TaskRunner $taskRunner, + ContextInterface $context, + EventDispatcherInterface $eventDispatcher + ) { + $taskRunner->run($context)->shouldBeCalled(); + $eventDispatcher->addSubscriber(Argument::type('GrumPHP\Event\Subscriber\ProgressSubscriber'))->shouldBeCalled(); + $this->run($output, $context)->shouldReturn(TaskRunnerHelper::CODE_SUCCESS); + } } diff --git a/spec/GrumPHP/Event/RunnerEventSpec.php b/spec/GrumPHP/Event/RunnerEventSpec.php new file mode 100644 index 000000000..d2eea0f10 --- /dev/null +++ b/spec/GrumPHP/Event/RunnerEventSpec.php @@ -0,0 +1,30 @@ +beConstructedWith($tasks); + } + + function it_is_initializable() + { + $this->shouldHaveType('GrumPHP\Event\RunnerEvent'); + } + + function it_is_an_event() + { + $this->shouldHaveType('Symfony\Component\EventDispatcher\Event'); + } + + function it_has_tasks(TasksCollection $tasks) + { + $this->getTasks()->shouldBe($tasks); + } +} diff --git a/spec/GrumPHP/Event/RunnerFailedEventSpec.php b/spec/GrumPHP/Event/RunnerFailedEventSpec.php new file mode 100644 index 000000000..4e8ea9fc2 --- /dev/null +++ b/spec/GrumPHP/Event/RunnerFailedEventSpec.php @@ -0,0 +1,35 @@ +beConstructedWith($tasks, []); + } + + function it_is_initializable() + { + $this->shouldHaveType('GrumPHP\Event\RunnerFailedEvent'); + } + + function it_is_a_runner_event() + { + $this->shouldHaveType('GrumPHP\Event\RunnerEvent'); + } + + function it_has_tasks(TasksCollection $tasks) + { + $this->getTasks()->shouldBe($tasks); + } + + function it_should_contain_the_error_messages() + { + $this->getMessages()->shouldBe([]); + } +} diff --git a/spec/GrumPHP/Event/Subscriber/ProgressSubscriberSpec.php b/spec/GrumPHP/Event/Subscriber/ProgressSubscriberSpec.php new file mode 100644 index 000000000..0d902ce65 --- /dev/null +++ b/spec/GrumPHP/Event/Subscriber/ProgressSubscriberSpec.php @@ -0,0 +1,69 @@ +beConstructedWith($output, $progressBar); + } + + function it_is_initializable() + { + $this->shouldHaveType('GrumPHP\Event\Subscriber\ProgressSubscriber'); + } + + function it_is_an_event_subscriber() + { + $this->shouldImplement('Symfony\Component\EventDispatcher\EventSubscriberInterface'); + } + + function it_should_subscribe_to_events() + { + $this->getSubscribedEvents()->shouldBeArray(); + } + + function it_starts_progress(ProgressBar $progressBar, RunnerEvent $event, TasksCollection $tasks) + { + $tasks->count()->willReturn(2); + $event->getTasks()->willReturn($tasks); + + $progressBar->setFormat(Argument::type('string'))->shouldBeCalled(); + $progressBar->setOverwrite(false)->shouldBeCalled(); + $progressBar->setMessage(Argument::type('string'))->shouldBeCalled(); + $progressBar->start(2)->shouldBeCalled(); + + $this->startProgress($event); + } + + function it_should_advance_progress(ProgressBar $progressBar, TaskEvent $event, TaskInterface $task) + { + $event->getTask()->willReturn($task); + + $progressBar->setFormat(Argument::type('string'))->shouldBeCalled(); + $progressBar->setOverwrite(false)->shouldBeCalled(); + $progressBar->setMessage(Argument::type('string'))->shouldBeCalled(); + $progressBar->advance()->shouldBeCalled(); + + $this->advanceProgress($event); + } + + function it_finishes_progress(OutputInterface $output, ProgressBar $progressBar, RunnerEvent $event) + { + $progressBar->setOverwrite(false)->shouldBeCalled(); + $progressBar->finish()->shouldBeCalled(); + $output->writeln('')->shouldBeCalled(); + + $this->finishProgress($event); + } +} diff --git a/spec/GrumPHP/Event/TaskEventSpec.php b/spec/GrumPHP/Event/TaskEventSpec.php new file mode 100644 index 000000000..0d9b873d4 --- /dev/null +++ b/spec/GrumPHP/Event/TaskEventSpec.php @@ -0,0 +1,31 @@ +beConstructedWith($task); + } + + function it_is_initializable() + { + $this->shouldHaveType('GrumPHP\Event\TaskEvent'); + } + + function it_is_an_event() + { + $this->shouldHaveType('Symfony\Component\EventDispatcher\Event'); + } + + function it_has_a_task(TaskInterface $task) + { + $this->getTask()->shouldBe($task); + } +} diff --git a/spec/GrumPHP/Event/TaskFailedEventSpec.php b/spec/GrumPHP/Event/TaskFailedEventSpec.php new file mode 100644 index 000000000..1d33a4bb5 --- /dev/null +++ b/spec/GrumPHP/Event/TaskFailedEventSpec.php @@ -0,0 +1,37 @@ +beConstructedWith($task, $exception); + } + + function it_is_initializable() + { + $this->shouldHaveType('GrumPHP\Event\TaskFailedEvent'); + } + + function it_is_a_runner_event() + { + $this->shouldHaveType('GrumPHP\Event\TaskEvent'); + } + + function it_has_a_task(TaskInterface $task) + { + $this->getTask()->shouldBe($task); + } + + function it_should_contain_the_exception(\Exception $exception) + { + $this->getException()->shouldBe($exception); + } +} diff --git a/spec/GrumPHP/Locator/RegisteredFilesSpec.php b/spec/GrumPHP/Locator/RegisteredFilesSpec.php new file mode 100644 index 000000000..dda29e54e --- /dev/null +++ b/spec/GrumPHP/Locator/RegisteredFilesSpec.php @@ -0,0 +1,37 @@ +beConstructedWith($repository); + } + + function it_is_initializable() + { + $this->shouldHaveType('GrumPHP\Locator\RegisteredFiles'); + } + + function it_is_a_grumphp_locator() + { + $this->shouldHaveType('GrumPHP\Locator\LocatorInterface'); + } + + function it_will_list_all_diffed_files(Repository $repository) + { + $files = ['file1.txt', 'file2.txt']; + $repository->run('ls-files')->willReturn(implode(PHP_EOL, $files)); + + $result = $this->locate(); + $result->shouldBeAnInstanceOf('GrumPHP\Collection\FilesCollection'); + $result[0]->getPathname()->shouldBe('file1.txt'); + $result[1]->getPathname()->shouldBe('file2.txt'); + $result->getIterator()->count()->shouldBe(2); + } +} diff --git a/spec/GrumPHP/Runner/TaskRunnerSpec.php b/spec/GrumPHP/Runner/TaskRunnerSpec.php index 9470daf04..7e640aa70 100644 --- a/spec/GrumPHP/Runner/TaskRunnerSpec.php +++ b/spec/GrumPHP/Runner/TaskRunnerSpec.php @@ -3,16 +3,25 @@ namespace spec\GrumPHP\Runner; use GrumPHP\Collection\FilesCollection; +use GrumPHP\Event\RunnerEvents; +use GrumPHP\Event\TaskEvents; use GrumPHP\Task\Context\ContextInterface; use GrumPHP\Task\TaskInterface; use PhpSpec\ObjectBehavior; use Prophecy\Argument; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; class TaskRunnerSpec extends ObjectBehavior { - public function let(TaskInterface $task1, TaskInterface $task2, ContextInterface $context) - { + public function let( + EventDispatcherInterface $eventDispatcher, + TaskInterface $task1, + TaskInterface $task2, + ContextInterface $context + ) { + $this->beConstructedWith($eventDispatcher); + $task1->canRunInContext($context)->willReturn(true); $task2->canRunInContext($context)->willReturn(true); @@ -63,4 +72,39 @@ function it_runs_subsequent_tasks_if_one_fails( $this->shouldThrow('GrumPHP\Exception\FailureException')->duringRun($context); } + + function it_triggers_events_during_happy_flow( + EventDispatcherInterface $eventDispatcher, + TaskInterface $task1, + TaskInterface $task2, + ContextInterface $context + ) { + $task1->run($context)->shouldBeCalled(); + $task2->run($context)->shouldBeCalled(); + + $eventDispatcher->dispatch(RunnerEvents::RUNNER_RUN, Argument::type('GrumPHP\Event\RunnerEvent'))->shouldBeCalled(); + $eventDispatcher->dispatch(TaskEvents::TASK_RUN, Argument::type('GrumPHP\Event\TaskEvent'))->shouldBeCalled(); + $eventDispatcher->dispatch(TaskEvents::TASK_COMPLETE, Argument::type('GrumPHP\Event\TaskEvent'))->shouldBeCalled(); + $eventDispatcher->dispatch(RunnerEvents::RUNNER_COMPLETE, Argument::type('GrumPHP\Event\RunnerEvent'))->shouldBeCalled(); + + $this->run($context); + } + + function it_triggers_events_during_error_flow( + EventDispatcherInterface $eventDispatcher, + TaskInterface $task1, + TaskInterface $task2, + ContextInterface $context + ) { + $task1->run($context)->willThrow('GrumPHP\Exception\RuntimeException'); + $task2->run($context)->shouldBeCalled(); + + $eventDispatcher->dispatch(RunnerEvents::RUNNER_RUN, Argument::type('GrumPHP\Event\RunnerEvent'))->shouldBeCalled(); + $eventDispatcher->dispatch(TaskEvents::TASK_RUN, Argument::type('GrumPHP\Event\TaskEvent'))->shouldBeCalled(); + $eventDispatcher->dispatch(TaskEvents::TASK_COMPLETE, Argument::type('GrumPHP\Event\TaskEvent'))->shouldBeCalled(); + $eventDispatcher->dispatch(TaskEvents::TASK_FAILED, Argument::type('GrumPHP\Event\TaskFailedEvent'))->shouldBeCalled(); + $eventDispatcher->dispatch(RunnerEvents::RUNNER_FAILED, Argument::type('GrumPHP\Event\RunnerFailedEvent'))->shouldBeCalled(); + + $this->shouldThrow('GrumPHP\Exception\FailureException')->duringRun($context); + } } diff --git a/spec/GrumPHP/Task/BehatSpec.php b/spec/GrumPHP/Task/BehatSpec.php index c905f0d7e..210db7100 100644 --- a/spec/GrumPHP/Task/BehatSpec.php +++ b/spec/GrumPHP/Task/BehatSpec.php @@ -7,6 +7,7 @@ use GrumPHP\Locator\LocatorInterface; use GrumPHP\Task\Context\ContextInterface; use GrumPHP\Task\Context\GitPreCommitContext; +use GrumPHP\Task\Context\RunContext; use PhpSpec\ObjectBehavior; use Prophecy\Argument; use Symfony\Component\Process\Process; @@ -41,6 +42,11 @@ function it_should_run_in_git_pre_commit_context(GitPreCommitContext $context) $this->canRunInContext($context)->shouldReturn(true); } + function it_should_run_in_run_context(RunContext $context) + { + $this->canRunInContext($context)->shouldReturn(true); + } + function it_does_not_do_anything_if_there_are_no_files(ProcessBuilder $processBuilder, ContextInterface $context) { $processBuilder->add(Argument::any())->shouldNotBeCalled(); diff --git a/spec/GrumPHP/Task/PhpcsSpec.php b/spec/GrumPHP/Task/PhpcsSpec.php index 3c618ed2c..97c159d8e 100644 --- a/spec/GrumPHP/Task/PhpcsSpec.php +++ b/spec/GrumPHP/Task/PhpcsSpec.php @@ -7,6 +7,7 @@ use GrumPHP\Locator\LocatorInterface; use GrumPHP\Task\Context\ContextInterface; use GrumPHP\Task\Context\GitPreCommitContext; +use GrumPHP\Task\Context\RunContext; use PhpSpec\ObjectBehavior; use Prophecy\Argument; use Symfony\Component\Process\Process; @@ -42,6 +43,12 @@ function it_should_run_in_git_pre_commit_context(GitPreCommitContext $context) $this->canRunInContext($context)->shouldReturn(true); } + + function it_should_run_in_run_context(RunContext $context) + { + $this->canRunInContext($context)->shouldReturn(true); + } + function it_does_not_do_anything_if_there_are_no_files(ProcessBuilder $processBuilder, ContextInterface $context) { $processBuilder->add(Argument::any())->shouldNotBeCalled(); diff --git a/spec/GrumPHP/Task/PhpcsfixerSpec.php b/spec/GrumPHP/Task/PhpcsfixerSpec.php index 1561d5f5e..855c24846 100644 --- a/spec/GrumPHP/Task/PhpcsfixerSpec.php +++ b/spec/GrumPHP/Task/PhpcsfixerSpec.php @@ -7,6 +7,7 @@ use GrumPHP\Locator\LocatorInterface; use GrumPHP\Task\Context\ContextInterface; use GrumPHP\Task\Context\GitPreCommitContext; +use GrumPHP\Task\Context\RunContext; use PhpSpec\ObjectBehavior; use Prophecy\Argument; use Symfony\Component\Process\Process; @@ -52,6 +53,11 @@ function it_should_run_in_git_pre_commit_context(GitPreCommitContext $context) $this->canRunInContext($context)->shouldReturn(true); } + function it_should_run_in_run_context(RunContext $context) + { + $this->canRunInContext($context)->shouldReturn(true); + } + function it_runs_the_suite(ProcessBuilder $processBuilder, Process $process, ContextInterface $context) { $processBuilder->add('--config=default')->shouldBeCalled(); diff --git a/spec/GrumPHP/Task/PhpspecSpec.php b/spec/GrumPHP/Task/PhpspecSpec.php index 2a21e53e5..3503a5e38 100644 --- a/spec/GrumPHP/Task/PhpspecSpec.php +++ b/spec/GrumPHP/Task/PhpspecSpec.php @@ -7,6 +7,7 @@ use GrumPHP\Locator\LocatorInterface; use GrumPHP\Task\Context\ContextInterface; use GrumPHP\Task\Context\GitPreCommitContext; +use GrumPHP\Task\Context\RunContext; use PhpSpec\ObjectBehavior; use Prophecy\Argument; use Symfony\Component\Process\Process; @@ -42,6 +43,11 @@ function it_should_run_in_git_pre_commit_context(GitPreCommitContext $context) $this->canRunInContext($context)->shouldReturn(true); } + function it_should_run_in_run_context(RunContext $context) + { + $this->canRunInContext($context)->shouldReturn(true); + } + function it_runs_the_suite(ProcessBuilder $processBuilder, Process $process, ContextInterface $context) { $processBuilder->setArguments(Argument::type('array'))->shouldBeCalled(); diff --git a/spec/GrumPHP/Task/PhpunitSpec.php b/spec/GrumPHP/Task/PhpunitSpec.php index b05767140..71d3fb08b 100644 --- a/spec/GrumPHP/Task/PhpunitSpec.php +++ b/spec/GrumPHP/Task/PhpunitSpec.php @@ -7,6 +7,7 @@ use GrumPHP\Locator\LocatorInterface; use GrumPHP\Task\Context\ContextInterface; use GrumPHP\Task\Context\GitPreCommitContext; +use GrumPHP\Task\Context\RunContext; use PhpSpec\ObjectBehavior; use Prophecy\Argument; use Symfony\Component\Process\Process; @@ -41,6 +42,11 @@ function it_should_run_in_git_pre_commit_context(GitPreCommitContext $context) $this->canRunInContext($context)->shouldReturn(true); } + function it_should_run_in_run_context(RunContext $context) + { + $this->canRunInContext($context)->shouldReturn(true); + } + function it_runs_the_suite(ProcessBuilder $processBuilder, Process $process, ContextInterface $context) { $processBuilder->setArguments(Argument::type('array'))->shouldBeCalled(); diff --git a/src/GrumPHP/Configuration/TaskCompilerPass.php b/src/GrumPHP/Configuration/Compiler/TaskCompilerPass.php similarity index 93% rename from src/GrumPHP/Configuration/TaskCompilerPass.php rename to src/GrumPHP/Configuration/Compiler/TaskCompilerPass.php index 9a10d201b..f2d9f903c 100644 --- a/src/GrumPHP/Configuration/TaskCompilerPass.php +++ b/src/GrumPHP/Configuration/Compiler/TaskCompilerPass.php @@ -1,6 +1,6 @@ addCompilerPass(new TaskCompilerPass()); + $container->addCompilerPass( + new RegisterListenersPass('event_dispatcher', 'grumphp.event_listener', 'grumphp.event_subscriber') + ); // Load basic service file + custom user configuration $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../../../resources/config')); diff --git a/src/GrumPHP/Console/Application.php b/src/GrumPHP/Console/Application.php index 73d54ea0d..91cac345b 100644 --- a/src/GrumPHP/Console/Application.php +++ b/src/GrumPHP/Console/Application.php @@ -95,6 +95,10 @@ protected function getDefaultCommands() $container->get('git.repository'), $container->get('task_runner') ); + $commands[] = new Command\RunCommand( + $container->get('config'), + $container->get('locator.registered_files') + ); $commands[] = new Command\Git\CommitMsgCommand( $container->get('config'), @@ -127,7 +131,8 @@ protected function getDefaultHelperSet() $container->get('filesystem') )); $helperSet->set(new Helper\TaskRunnerHelper( - $container->get('task_runner') + $container->get('task_runner'), + $container->get('event_dispatcher') )); return $helperSet; diff --git a/src/GrumPHP/Console/Command/RunCommand.php b/src/GrumPHP/Console/Command/RunCommand.php new file mode 100644 index 000000000..cc1e3075c --- /dev/null +++ b/src/GrumPHP/Console/Command/RunCommand.php @@ -0,0 +1,91 @@ +grumPHP = $grumPHP; + $this->registeredFilesLocator = $registeredFilesLocator; + } + + /** + * Configure command + */ + protected function configure() + { + $this->setName(self::COMMAND_NAME); + } + + /** + * @param InputInterface $input + * @param OutputInterface $output + * + * @return int|void + */ + public function execute(InputInterface $input, OutputInterface $output) + { + $files = $this->getRegisteredFiles(); + $context = new RunContext($files); + + return $this->taskRunner()->run($output, $context); + } + + /** + * @return FilesCollection + */ + protected function getRegisteredFiles() + { + return $this->registeredFilesLocator->locate(); + } + + /** + * @return TaskRunnerHelper + */ + protected function taskRunner() + { + return $this->getHelper(TaskRunnerHelper::HELPER_NAME); + } + + /** + * @return PathsHelper + */ + protected function paths() + { + return $this->getHelper(PathsHelper::HELPER_NAME); + } +} diff --git a/src/GrumPHP/Console/Helper/TaskRunnerHelper.php b/src/GrumPHP/Console/Helper/TaskRunnerHelper.php index 57afa1240..f03816c06 100644 --- a/src/GrumPHP/Console/Helper/TaskRunnerHelper.php +++ b/src/GrumPHP/Console/Helper/TaskRunnerHelper.php @@ -2,11 +2,14 @@ namespace GrumPHP\Console\Helper; +use GrumPHP\Event\Subscriber\ProgressSubscriber; use GrumPHP\Exception\ExceptionInterface; use GrumPHP\Runner\TaskRunner; use GrumPHP\Task\Context\ContextInterface; use Symfony\Component\Console\Helper\Helper; +use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * Class TaskRunnerHelper @@ -26,11 +29,18 @@ class TaskRunnerHelper extends Helper private $taskRunner; /** - * @param TaskRunner $taskRunner + * @var EventDispatcherInterface */ - public function __construct(TaskRunner $taskRunner) + private $eventDispatcher; + + /** + * @param TaskRunner $taskRunner + * @param EventDispatcherInterface $eventDispatcher + */ + public function __construct(TaskRunner $taskRunner, EventDispatcherInterface $eventDispatcher) { $this->taskRunner = $taskRunner; + $this->eventDispatcher = $eventDispatcher; } /** @@ -50,6 +60,9 @@ private function paths() */ public function run(OutputInterface $output, ContextInterface $context, $skipSuccessOutput = false) { + // Make sure to add some default event listeners before running. + $this->registerEventListeners($output, $context); + try { $this->taskRunner->run($context); } catch (ExceptionInterface $e) { @@ -64,7 +77,15 @@ public function run(OutputInterface $output, ContextInterface $context, $skipSuc } return $this->returnSuccessMessage($output); + } + /** + * @param OutputInterface $output + * @param ContextInterface $context + */ + private function registerEventListeners(OutputInterface $output, ContextInterface $context) + { + $this->eventDispatcher->addSubscriber(new ProgressSubscriber($output, new ProgressBar($output))); } /** diff --git a/src/GrumPHP/Event/RunnerEvent.php b/src/GrumPHP/Event/RunnerEvent.php new file mode 100644 index 000000000..3e09927ad --- /dev/null +++ b/src/GrumPHP/Event/RunnerEvent.php @@ -0,0 +1,35 @@ +tasks = $tasks; + } + + /** + * @return TasksCollection + */ + public function getTasks() + { + return $this->tasks; + } +} diff --git a/src/GrumPHP/Event/RunnerEvents.php b/src/GrumPHP/Event/RunnerEvents.php new file mode 100644 index 000000000..0615455c8 --- /dev/null +++ b/src/GrumPHP/Event/RunnerEvents.php @@ -0,0 +1,15 @@ +messages = $messages; + } + + /** + * @return array + */ + public function getMessages() + { + return $this->messages; + } +} diff --git a/src/GrumPHP/Event/Subscriber/ProgressSubscriber.php b/src/GrumPHP/Event/Subscriber/ProgressSubscriber.php new file mode 100644 index 000000000..1a453ca3d --- /dev/null +++ b/src/GrumPHP/Event/Subscriber/ProgressSubscriber.php @@ -0,0 +1,93 @@ +output = $output; + $this->progressBar = $progressBar ?: new ProgressBar($output); + $this->progressBar->setOverwrite(false); + $this->progressFormat = "Running task %current%/%max%: %message%"; + } + + /** + * @return array + */ + public static function getSubscribedEvents() + { + return [ + RunnerEvents::RUNNER_RUN => 'startProgress', + TaskEvents::TASK_RUN => 'advanceProgress', + RunnerEvents::RUNNER_COMPLETE => 'finishProgress', + RunnerEvents::RUNNER_FAILED => 'finishProgress', + ]; + } + + /** + * @param RunnerEvent $event + */ + public function startProgress(RunnerEvent $event) + { + $numberOftasks = $event->getTasks()->count(); + $this->progressBar->setFormat('%message%'); + $this->progressBar->setMessage('GrumPHP is sniffing your code!'); + $this->progressBar->start($numberOftasks); + } + + /** + * @param TaskEvent $event + */ + public function advanceProgress(TaskEvent $event) + { + $taskReflection = new ReflectionClass($event->getTask()); + $taskName = $taskReflection->getShortName(); + + $this->progressBar->setFormat($this->progressFormat); + $this->progressBar->setMessage($taskName); + $this->progressBar->advance(); + } + + /** + * @param RunnerEvent $runnerEvent + */ + public function finishProgress(RunnerEvent $runnerEvent) + { + $this->progressBar->finish(); + $this->output->writeln(''); + } +} diff --git a/src/GrumPHP/Event/TaskEvent.php b/src/GrumPHP/Event/TaskEvent.php new file mode 100644 index 000000000..ba7d72318 --- /dev/null +++ b/src/GrumPHP/Event/TaskEvent.php @@ -0,0 +1,35 @@ +task = $task; + } + + /** + * @return TaskInterface + */ + public function getTask() + { + return $this->task; + } +} diff --git a/src/GrumPHP/Event/TaskEvents.php b/src/GrumPHP/Event/TaskEvents.php new file mode 100644 index 000000000..1081d6df4 --- /dev/null +++ b/src/GrumPHP/Event/TaskEvents.php @@ -0,0 +1,15 @@ +exception = $exception; + } + + /** + * @return Exception + */ + public function getException() + { + return $this->exception; + } +} diff --git a/src/GrumPHP/Locator/RegisteredFiles.php b/src/GrumPHP/Locator/RegisteredFiles.php new file mode 100644 index 000000000..fe48b2060 --- /dev/null +++ b/src/GrumPHP/Locator/RegisteredFiles.php @@ -0,0 +1,45 @@ +repository = $repository; + } + + /** + * @return FilesCollection + */ + public function locate() + { + $allFiles = trim($this->repository->run('ls-files')); + $filePaths = explode(PHP_EOL, $allFiles); + + $files = array(); + foreach ($filePaths as $file) { + $files[] = new SplFileInfo($file); + + } + + return new FilesCollection($files); + } +} diff --git a/src/GrumPHP/Runner/TaskRunner.php b/src/GrumPHP/Runner/TaskRunner.php index 0d3845ae5..904dff0c3 100644 --- a/src/GrumPHP/Runner/TaskRunner.php +++ b/src/GrumPHP/Runner/TaskRunner.php @@ -4,10 +4,17 @@ use GrumPHP\Collection\FilesCollection; use GrumPHP\Collection\TasksCollection; +use GrumPHP\Event\RunnerEvent; +use GrumPHP\Event\RunnerEvents; +use GrumPHP\Event\RunnerFailedEvent; +use GrumPHP\Event\TaskEvent; +use GrumPHP\Event\TaskEvents; +use GrumPHP\Event\TaskFailedEvent; use GrumPHP\Exception\FailureException; use GrumPHP\Exception\RuntimeException; use GrumPHP\Task\Context\ContextInterface; use GrumPHP\Task\TaskInterface; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * Class TaskRunner @@ -19,14 +26,22 @@ class TaskRunner /** * @var TasksCollection|TaskInterface[] */ - protected $tasks; + private $tasks; + + /** + * @var EventDispatcherInterface + */ + private $eventDispatcher; /** * @constructor + * + * @param EventDispatcherInterface $eventDispatcher */ - public function __construct() + public function __construct(EventDispatcherInterface $eventDispatcher) { $this->tasks = new TasksCollection(); + $this->eventDispatcher = $eventDispatcher; } /** @@ -58,19 +73,26 @@ public function run(ContextInterface $context) { $failures = false; $messages = array(); - $tasks = $this->tasks->filterByContext($context); + + $this->eventDispatcher->dispatch(RunnerEvents::RUNNER_RUN, new RunnerEvent($tasks)); foreach ($tasks as $task) { try { + $this->eventDispatcher->dispatch(TaskEvents::TASK_RUN, new TaskEvent($task)); $task->run($context); } catch (RuntimeException $e) { - $failures = true; + $this->eventDispatcher->dispatch(TaskEvents::TASK_FAILED, new TaskFailedEvent($task, $e)); $messages[] = $e->getMessage(); + $failures = true; } + $this->eventDispatcher->dispatch(TaskEvents::TASK_COMPLETE, new TaskEvent($task)); } if ($failures) { + $this->eventDispatcher->dispatch(RunnerEvents::RUNNER_FAILED, new RunnerFailedEvent($tasks, $messages)); throw new FailureException(implode(PHP_EOL, $messages)); } + + $this->eventDispatcher->dispatch(RunnerEvents::RUNNER_COMPLETE, new RunnerEvent($tasks)); } } diff --git a/src/GrumPHP/Task/Behat.php b/src/GrumPHP/Task/Behat.php index 2997b3410..6e15c0014 100644 --- a/src/GrumPHP/Task/Behat.php +++ b/src/GrumPHP/Task/Behat.php @@ -6,6 +6,7 @@ use GrumPHP\Exception\RuntimeException; use GrumPHP\Task\Context\ContextInterface; use GrumPHP\Task\Context\GitPreCommitContext; +use GrumPHP\Task\Context\RunContext; /** * Behat task @@ -40,7 +41,7 @@ public function getDefaultConfiguration() */ public function canRunInContext(ContextInterface $context) { - return ($context instanceof GitPreCommitContext); + return ($context instanceof GitPreCommitContext || $context instanceof RunContext); } /** diff --git a/src/GrumPHP/Task/Context/RunContext.php b/src/GrumPHP/Task/Context/RunContext.php new file mode 100644 index 000000000..9462497fe --- /dev/null +++ b/src/GrumPHP/Task/Context/RunContext.php @@ -0,0 +1,35 @@ +files = $files; + } + + /** + * @return FilesCollection + */ + public function getFiles() + { + return $this->files; + } +} diff --git a/src/GrumPHP/Task/Phpcs.php b/src/GrumPHP/Task/Phpcs.php index 38667028c..7b9beb020 100644 --- a/src/GrumPHP/Task/Phpcs.php +++ b/src/GrumPHP/Task/Phpcs.php @@ -6,6 +6,7 @@ use GrumPHP\Exception\RuntimeException; use GrumPHP\Task\Context\ContextInterface; use GrumPHP\Task\Context\GitPreCommitContext; +use GrumPHP\Task\Context\RunContext; /** * Phpcs task @@ -41,7 +42,7 @@ public function getCommandLocation() */ public function canRunInContext(ContextInterface $context) { - return ($context instanceof GitPreCommitContext); + return ($context instanceof GitPreCommitContext || $context instanceof RunContext); } /** diff --git a/src/GrumPHP/Task/Phpcsfixer.php b/src/GrumPHP/Task/Phpcsfixer.php index 331f194dd..fe4978f4b 100644 --- a/src/GrumPHP/Task/Phpcsfixer.php +++ b/src/GrumPHP/Task/Phpcsfixer.php @@ -6,6 +6,7 @@ use GrumPHP\Exception\RuntimeException; use GrumPHP\Task\Context\ContextInterface; use GrumPHP\Task\Context\GitPreCommitContext; +use GrumPHP\Task\Context\RunContext; /** * Php-cs-fixer task @@ -41,7 +42,7 @@ public function getCommandLocation() */ public function canRunInContext(ContextInterface $context) { - return ($context instanceof GitPreCommitContext); + return ($context instanceof GitPreCommitContext || $context instanceof RunContext); } /** diff --git a/src/GrumPHP/Task/Phpspec.php b/src/GrumPHP/Task/Phpspec.php index ee5cbf6e0..42a217f87 100644 --- a/src/GrumPHP/Task/Phpspec.php +++ b/src/GrumPHP/Task/Phpspec.php @@ -6,6 +6,7 @@ use GrumPHP\Exception\RuntimeException; use GrumPHP\Task\Context\ContextInterface; use GrumPHP\Task\Context\GitPreCommitContext; +use GrumPHP\Task\Context\RunContext; /** * Phpspec task @@ -38,7 +39,7 @@ public function getDefaultConfiguration() */ public function canRunInContext(ContextInterface $context) { - return ($context instanceof GitPreCommitContext); + return ($context instanceof GitPreCommitContext || $context instanceof RunContext); } /** diff --git a/src/GrumPHP/Task/Phpunit.php b/src/GrumPHP/Task/Phpunit.php index 910e149d0..3963abe72 100644 --- a/src/GrumPHP/Task/Phpunit.php +++ b/src/GrumPHP/Task/Phpunit.php @@ -6,6 +6,7 @@ use GrumPHP\Exception\RuntimeException; use GrumPHP\Task\Context\ContextInterface; use GrumPHP\Task\Context\GitPreCommitContext; +use GrumPHP\Task\Context\RunContext; /** * Phpunit task @@ -37,7 +38,7 @@ public function getDefaultConfiguration() */ public function canRunInContext(ContextInterface $context) { - return ($context instanceof GitPreCommitContext); + return ($context instanceof GitPreCommitContext || $context instanceof RunContext); } /** From dd243e45099bd70f4fce70f5953ce434061c725a Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Sat, 24 Oct 2015 13:41:26 +0200 Subject: [PATCH 02/11] Make it possible to hook in with events + Add a run command --- README.md | 40 ++++++++++++++++++- .../Console/Command/Git/CommitMsgCommand.php | 1 + .../Console/Command/Git/PreCommitCommand.php | 1 + 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4e01e1be9..a8ab4f7ea 100644 --- a/README.md +++ b/README.md @@ -346,6 +346,7 @@ composer require --dev leaphub/phpcs-symfony2-standard Following this, you can add the path to your phpcs task. ```yml +# grumphp.yml parameters: tasks: phpcs: @@ -411,7 +412,7 @@ You just have to create a class that implements the `GrumPHP\Task\TaskInterface` Next register it to the service manager and add your task configuration: ```yaml -# resources/config/services.yml +# grumphp.yml parameters: tasks: myConfigKey: @@ -432,6 +433,38 @@ You're welcome! You just registered your custom task in no time! Pretty cool right?! +## Events + +It is possible to hook in to GrumPHP with events. +Internally the Symfony event dispatcher is being used. +This means it can be configured just like you would in Symfony: + +```sh +# grumphp.yml +services: + listener.some_listener: + class: MyNamespace\EventListener\MyListener + tags: + - { name: grumphp.event_listener, event: grumphp.runner.run } + - { name: grumphp.event_listener, event: grumphp.runner.run, method: customMethod, priority: 10 } + listener.some_subscriber: + class: MyNamespace\EventSubscriber\MySubscriber + tags: + - { name: grumphp.event_subscriber } +``` + +Following events are triggered during execution: + +| Event name | Event class | Triggered +| ----------------------- | ----------------- | ---------- +| grumphp.task.run | TaskEvent | Triggered before a task is executed. +| grumphp.task.failed | TaskFailedEvent | Triggered when a task fails. +| grumphp.task.complete | TaskEvent | Triggered when a task succeeds. +| grumphp.runner.run | RunnerEvent | Triggered before the tasks are executed. +| grumphp.runner.failed | RunnerFailedEvent | Triggered when one task failed. +| grumphp.runner.complete | RunnerEvent | Triggered when all tasks succeed. + + ## Roadmap Following tasks are still on the roadmap: @@ -451,8 +484,13 @@ GrumPHP will be triggered with GIT hooks. However, you can execute the trigger a ```sh php ./vendor/bin/grumphp git:pre-commit +php ./vendor/bin/grumphp git:commit-msg ``` +If you want to run the tests on the full codebase, you can run the command: +```sh +php ./vendor/bin/grumphp run +``` # Compatibility diff --git a/src/GrumPHP/Console/Command/Git/CommitMsgCommand.php b/src/GrumPHP/Console/Command/Git/CommitMsgCommand.php index c83d6fcc1..8946d8513 100644 --- a/src/GrumPHP/Console/Command/Git/CommitMsgCommand.php +++ b/src/GrumPHP/Console/Command/Git/CommitMsgCommand.php @@ -69,6 +69,7 @@ public function execute(InputInterface $input, OutputInterface $output) $commitMsgPath = $input->getArgument('commit-msg-file'); $commitMsgFile = new SplFileInfo($commitMsgPath); + $output->writeln('GrumPHP detected a commit-msg command.'); $context = new GitCommitMsgContext($files, $commitMsgFile, $gitUser, $gitEmail); return $this->taskRunner()->run($output, $context); } diff --git a/src/GrumPHP/Console/Command/Git/PreCommitCommand.php b/src/GrumPHP/Console/Command/Git/PreCommitCommand.php index a893a55c0..4c4fd2a67 100644 --- a/src/GrumPHP/Console/Command/Git/PreCommitCommand.php +++ b/src/GrumPHP/Console/Command/Git/PreCommitCommand.php @@ -68,6 +68,7 @@ public function execute(InputInterface $input, OutputInterface $output) $context = new GitPreCommitContext($files); $skipSuccessOutput = (bool) $input->getOption('skip-success-output'); + $output->writeln('GrumPHP detected a pre-commit command.'); return $this->taskRunner()->run($output, $context, $skipSuccessOutput); } From e07c40811f89d9f1789424370922bbbd8fb94bd2 Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Sat, 24 Oct 2015 13:44:11 +0200 Subject: [PATCH 03/11] Improve documentation --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index a8ab4f7ea..b89d5d6ad 100644 --- a/README.md +++ b/README.md @@ -439,7 +439,7 @@ It is possible to hook in to GrumPHP with events. Internally the Symfony event dispatcher is being used. This means it can be configured just like you would in Symfony: -```sh +```yml # grumphp.yml services: listener.some_listener: @@ -457,12 +457,12 @@ Following events are triggered during execution: | Event name | Event class | Triggered | ----------------------- | ----------------- | ---------- -| grumphp.task.run | TaskEvent | Triggered before a task is executed. -| grumphp.task.failed | TaskFailedEvent | Triggered when a task fails. -| grumphp.task.complete | TaskEvent | Triggered when a task succeeds. -| grumphp.runner.run | RunnerEvent | Triggered before the tasks are executed. -| grumphp.runner.failed | RunnerFailedEvent | Triggered when one task failed. -| grumphp.runner.complete | RunnerEvent | Triggered when all tasks succeed. +| grumphp.task.run | TaskEvent | before a task is executed +| grumphp.task.failed | TaskFailedEvent | when a task fails +| grumphp.task.complete | TaskEvent | when a task succeeds +| grumphp.runner.run | RunnerEvent | before the tasks are executed +| grumphp.runner.failed | RunnerFailedEvent | when one task failed +| grumphp.runner.complete | RunnerEvent | when all tasks succeed ## Roadmap From 8e1fb017f3174fbf28f9ce44c242822825be6a67 Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Sat, 24 Oct 2015 13:55:43 +0200 Subject: [PATCH 04/11] Fix PHP5.3 --- spec/GrumPHP/Event/RunnerFailedEventSpec.php | 4 ++-- spec/GrumPHP/Locator/RegisteredFilesSpec.php | 2 +- src/GrumPHP/Event/Subscriber/ProgressSubscriber.php | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/GrumPHP/Event/RunnerFailedEventSpec.php b/spec/GrumPHP/Event/RunnerFailedEventSpec.php index 4e8ea9fc2..72b249f7f 100644 --- a/spec/GrumPHP/Event/RunnerFailedEventSpec.php +++ b/spec/GrumPHP/Event/RunnerFailedEventSpec.php @@ -10,7 +10,7 @@ class RunnerFailedEventSpec extends ObjectBehavior { function let(TasksCollection $tasks) { - $this->beConstructedWith($tasks, []); + $this->beConstructedWith($tasks, array()); } function it_is_initializable() @@ -30,6 +30,6 @@ function it_has_tasks(TasksCollection $tasks) function it_should_contain_the_error_messages() { - $this->getMessages()->shouldBe([]); + $this->getMessages()->shouldBe(array()); } } diff --git a/spec/GrumPHP/Locator/RegisteredFilesSpec.php b/spec/GrumPHP/Locator/RegisteredFilesSpec.php index dda29e54e..8454d1e0d 100644 --- a/spec/GrumPHP/Locator/RegisteredFilesSpec.php +++ b/spec/GrumPHP/Locator/RegisteredFilesSpec.php @@ -25,7 +25,7 @@ function it_is_a_grumphp_locator() function it_will_list_all_diffed_files(Repository $repository) { - $files = ['file1.txt', 'file2.txt']; + $files = array('file1.txt', 'file2.txt'); $repository->run('ls-files')->willReturn(implode(PHP_EOL, $files)); $result = $this->locate(); diff --git a/src/GrumPHP/Event/Subscriber/ProgressSubscriber.php b/src/GrumPHP/Event/Subscriber/ProgressSubscriber.php index 1a453ca3d..b2bee0a21 100644 --- a/src/GrumPHP/Event/Subscriber/ProgressSubscriber.php +++ b/src/GrumPHP/Event/Subscriber/ProgressSubscriber.php @@ -50,12 +50,12 @@ public function __construct(OutputInterface $output, ProgressBar $progressBar) */ public static function getSubscribedEvents() { - return [ + return array( RunnerEvents::RUNNER_RUN => 'startProgress', TaskEvents::TASK_RUN => 'advanceProgress', RunnerEvents::RUNNER_COMPLETE => 'finishProgress', RunnerEvents::RUNNER_FAILED => 'finishProgress', - ]; + ); } /** From 3271207de0256d9b7b082c20af2862a3d173de91 Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Sat, 24 Oct 2015 13:57:53 +0200 Subject: [PATCH 05/11] Use GrumPHP for CI. Awesome! --- .travis.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 261d8fd11..c8593e869 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,6 +20,4 @@ install: - composer update --prefer-dist --no-scripts --no-interaction script: - - ./vendor/bin/phpcs --standard=PSR2 src - - ./vendor/bin/phpspec run - + - ./bin/grumphp run From 84aae5352aa99e5601bbb4ac987f149543453503 Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Sat, 24 Oct 2015 14:25:52 +0200 Subject: [PATCH 06/11] Describe how you can install and use grumphp system-wide. --- README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/README.md b/README.md index b89d5d6ad..8fee62887 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,28 @@ The only downfall is that you will have to initialize the git hook manually: php ./vendor/bin/grumphp git:init --config=path/to/grumphp.yml ``` +### Global installation + +It is possible to install or update GrumPHP on your system with following commands: + +```sh +composer global require phpro/grumphp +composer global update phpro/grumphp +``` + +This will install the `grumphp` executable in the `~/.composer/vendor/bin` folder. +Make sure to add this folder to your system `$PATH` variable: + +``` +# .zshrc or .bashrc +export PATH="$HOME/.composer/vendor/bin:$PATH" +``` + +That's all! The `grumphp` command will be available on your CLI and will be used by default. + +*Note:* that you might want to re-initialize your project git hooks to make sure the system-wide executable is being used. Run the `grumphp git:init` command in the project directory. +*Note:* When you globally installed 3rd party tools like e.g. `phpunit`, those will also be used instead of the composer executables. + ## Build your own conventions checker You can see [example](https://github.com/linkorb/conventions-checker) From 268d367f6fd010b5b5a5182e2862d0fe53463a19 Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Sat, 24 Oct 2015 14:28:04 +0200 Subject: [PATCH 07/11] Describe how you can install and use grumphp system-wide. --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8fee62887..7bec3b998 100644 --- a/README.md +++ b/README.md @@ -90,8 +90,9 @@ export PATH="$HOME/.composer/vendor/bin:$PATH" That's all! The `grumphp` command will be available on your CLI and will be used by default. -*Note:* that you might want to re-initialize your project git hooks to make sure the system-wide executable is being used. Run the `grumphp git:init` command in the project directory. -*Note:* When you globally installed 3rd party tools like e.g. `phpunit`, those will also be used instead of the composer executables. +**Note:** that you might want to re-initialize your project git hooks to make sure the system-wide executable is being used. Run the `grumphp git:init` command in the project directory. + +**Note:** When you globally installed 3rd party tools like e.g. `phpunit`, those will also be used instead of the composer executables. ## Build your own conventions checker From b48ee2cf236434eb4e96d902a5d0178940e0f419 Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Sat, 24 Oct 2015 14:35:02 +0200 Subject: [PATCH 08/11] Improve documentation about suggested packages. --- README.md | 4 +++- composer.json | 11 ++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7bec3b998..c9d930e54 100644 --- a/README.md +++ b/README.md @@ -32,10 +32,12 @@ You will see following message in the composer logs: To make GrumPHP even more awesome, it will suggest installing some extra packages: -- squizlabs/php_codesniffer : ~2.3 +- behat/behat : ~3.0 +- fabpot/php-cs-fixer: ~1.10 - phpspec/phpspec : ~2.1 - phpunit/phpunit : ~4.5 - roave/security-advisories : dev-master@dev +- squizlabs/php_codesniffer : ~2.3 GrumPHP will never push you into using a specific task. You can choose the tasks that fit your needs, and activate or deactivate any task in no time! diff --git a/composer.json b/composer.json index 50f737957..27261e6e7 100644 --- a/composer.json +++ b/composer.json @@ -26,11 +26,12 @@ "fabpot/php-cs-fixer": "~1.0" }, "suggest": { - "roave/security-advisories": "Lets GrumPHP be sure that there are no known security issues.", - "squizlabs/php_codesniffer": "Lets GrumPHP sniff on your code.", - "phpspec/phpspec": "Lets GrumPHP spec your code.", - "phpunit/phpunit": "Lets GrumPHP run your unit tests.", - "fabpot/php-cs-fixer": "Lets GrumPHP automatically fix your codestyle." + "behat/behat": "Lets GrumPHP validate your project features.", + "fabpot/php-cs-fixer": "Lets GrumPHP automatically fix your codestyle.", + "phpspec/phpspec": "Lets GrumPHP spec your code.", + "phpunit/phpunit": "Lets GrumPHP run your unit tests.", + "squizlabs/php_codesniffer": "Lets GrumPHP sniff on your code.", + "roave/security-advisories": "Lets GrumPHP be sure that there are no known security issues." }, "authors": [ { From 76b32d9a15b454c1ad5e44e22be2fb5f3d7f14bd Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Sat, 24 Oct 2015 14:42:53 +0200 Subject: [PATCH 09/11] Improve documentation. --- README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c9d930e54..eae902116 100644 --- a/README.md +++ b/README.md @@ -494,13 +494,22 @@ Following events are triggered during execution: Following tasks are still on the roadmap: -- composer.json and composer.lock need to be committed at the same time +- composer validate command - phpmd - phpcpd - phpdcd +- twig lint +- json lint +- yaml lint +- xml lint / dtd validation +- grunt tests +- gulp tests +- npm test tests - ... -In a future version, it will also be possible to use GrumPHP as a Continious Integration tool. +New features or bugfixes can be logged at the [https://github.com/phpro/grumphp/issues](issues list). +Want to help out? Feel free to contact us! + # Execution From a3c2c25d023a47138eeb4c470eb7219e4e7dfe1e Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Sat, 24 Oct 2015 16:26:05 +0200 Subject: [PATCH 10/11] Small bugfix --- spec/GrumPHP/Runner/TaskRunnerSpec.php | 3 +-- src/GrumPHP/Runner/TaskRunner.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/spec/GrumPHP/Runner/TaskRunnerSpec.php b/spec/GrumPHP/Runner/TaskRunnerSpec.php index 7e640aa70..5fbecd8fb 100644 --- a/spec/GrumPHP/Runner/TaskRunnerSpec.php +++ b/spec/GrumPHP/Runner/TaskRunnerSpec.php @@ -97,11 +97,10 @@ function it_triggers_events_during_error_flow( ContextInterface $context ) { $task1->run($context)->willThrow('GrumPHP\Exception\RuntimeException'); - $task2->run($context)->shouldBeCalled(); + $task2->run($context)->willThrow('GrumPHP\Exception\RuntimeException'); $eventDispatcher->dispatch(RunnerEvents::RUNNER_RUN, Argument::type('GrumPHP\Event\RunnerEvent'))->shouldBeCalled(); $eventDispatcher->dispatch(TaskEvents::TASK_RUN, Argument::type('GrumPHP\Event\TaskEvent'))->shouldBeCalled(); - $eventDispatcher->dispatch(TaskEvents::TASK_COMPLETE, Argument::type('GrumPHP\Event\TaskEvent'))->shouldBeCalled(); $eventDispatcher->dispatch(TaskEvents::TASK_FAILED, Argument::type('GrumPHP\Event\TaskFailedEvent'))->shouldBeCalled(); $eventDispatcher->dispatch(RunnerEvents::RUNNER_FAILED, Argument::type('GrumPHP\Event\RunnerFailedEvent'))->shouldBeCalled(); diff --git a/src/GrumPHP/Runner/TaskRunner.php b/src/GrumPHP/Runner/TaskRunner.php index 904dff0c3..255e7dc86 100644 --- a/src/GrumPHP/Runner/TaskRunner.php +++ b/src/GrumPHP/Runner/TaskRunner.php @@ -80,12 +80,12 @@ public function run(ContextInterface $context) try { $this->eventDispatcher->dispatch(TaskEvents::TASK_RUN, new TaskEvent($task)); $task->run($context); + $this->eventDispatcher->dispatch(TaskEvents::TASK_COMPLETE, new TaskEvent($task)); } catch (RuntimeException $e) { $this->eventDispatcher->dispatch(TaskEvents::TASK_FAILED, new TaskFailedEvent($task, $e)); $messages[] = $e->getMessage(); $failures = true; } - $this->eventDispatcher->dispatch(TaskEvents::TASK_COMPLETE, new TaskEvent($task)); } if ($failures) { From 091ae9c78def27e080a24276b07966974e5e01a0 Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Mon, 26 Oct 2015 09:56:39 +0100 Subject: [PATCH 11/11] Remove empty lines. --- src/GrumPHP/Event/TaskFailedEvent.php | 1 - src/GrumPHP/Task/Context/RunContext.php | 1 - 2 files changed, 2 deletions(-) diff --git a/src/GrumPHP/Event/TaskFailedEvent.php b/src/GrumPHP/Event/TaskFailedEvent.php index 84e6c9d98..655fac6c1 100644 --- a/src/GrumPHP/Event/TaskFailedEvent.php +++ b/src/GrumPHP/Event/TaskFailedEvent.php @@ -12,7 +12,6 @@ */ class TaskFailedEvent extends TaskEvent { - /** * @var Exception */ diff --git a/src/GrumPHP/Task/Context/RunContext.php b/src/GrumPHP/Task/Context/RunContext.php index 9462497fe..134ac96bc 100644 --- a/src/GrumPHP/Task/Context/RunContext.php +++ b/src/GrumPHP/Task/Context/RunContext.php @@ -11,7 +11,6 @@ */ class RunContext implements ContextInterface { - /** * @var FilesCollection */