diff options
author | diosmosis <diosmosis@users.noreply.github.com> | 2018-08-11 11:13:55 +0300 |
---|---|---|
committer | Matthieu Aubry <mattab@users.noreply.github.com> | 2018-08-11 11:13:55 +0300 |
commit | 2d7896c3df5540bc109e89782880c0780a6b7bc2 (patch) | |
tree | 75584e348745db16b22a4d74f99c9d7c259f0af0 | |
parent | bc33259f6b6fc730826eceeb2a029eef63e97fc0 (diff) |
If warning/error log detected in console command exit w/ code = 1. (#13275)
-rw-r--r-- | core/Console.php | 11 | ||||
-rw-r--r-- | plugins/Monolog/Handler/FailureLogMessageDetector.php | 49 | ||||
-rw-r--r-- | plugins/Monolog/config/cli.php | 2 | ||||
-rw-r--r-- | tests/PHPUnit/System/ConsoleTest.php | 100 |
4 files changed, 161 insertions, 1 deletions
diff --git a/core/Console.php b/core/Console.php index a5d5773009..21b8b5b6f3 100644 --- a/core/Console.php +++ b/core/Console.php @@ -12,6 +12,7 @@ use Piwik\Application\Environment; use Piwik\Config\ConfigNotFoundException; use Piwik\Container\StaticContainer; use Piwik\Plugin\Manager as PluginManager; +use Piwik\Plugins\Monolog\Handler\FailureLogMessageDetector; use Piwik\Version; use Symfony\Bridge\Monolog\Handler\ConsoleHandler; use Symfony\Component\Console\Application; @@ -85,9 +86,17 @@ class Console extends Application } $self = $this; - return Access::doAsSuperUser(function () use ($input, $output, $self) { + $exitCode = Access::doAsSuperUser(function () use ($input, $output, $self) { return call_user_func(array($self, 'Symfony\Component\Console\Application::doRun'), $input, $output); }); + + $importantLogDetector = StaticContainer::get(FailureLogMessageDetector::class); + if ($exitCode === 0 && $importantLogDetector->hasEncounteredImportantLog()) { + $output->writeln("Error: error or warning logs detected, exit 1"); + $exitCode = 1; + } + + return $exitCode; } private function addCommandIfExists($command) diff --git a/plugins/Monolog/Handler/FailureLogMessageDetector.php b/plugins/Monolog/Handler/FailureLogMessageDetector.php new file mode 100644 index 0000000000..ea37f4ba08 --- /dev/null +++ b/plugins/Monolog/Handler/FailureLogMessageDetector.php @@ -0,0 +1,49 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +namespace Piwik\Plugins\Monolog\Handler; + +use Monolog\Handler\AbstractHandler; +use Monolog\Logger; + +/** + * Handler used to detect whether a certain level of log has been emitted. + */ +class FailureLogMessageDetector extends AbstractHandler +{ + /** + * @var boolean + */ + private $hasEncounteredImportantLog = false; + + public function __construct($level = Logger::WARNING) + { + parent::__construct($level, $bubble = true); + } + + public function handle(array $record) + { + $this->hasEncounteredImportantLog = true; + } + + /** + * @return bool + */ + public function hasEncounteredImportantLog() + { + return $this->hasEncounteredImportantLog; + } + + /** + * for tests + */ + public function reset() + { + $this->hasEncounteredImportantLog = false; + } +}
\ No newline at end of file diff --git a/plugins/Monolog/config/cli.php b/plugins/Monolog/config/cli.php index 0b33f04c7b..146943120b 100644 --- a/plugins/Monolog/config/cli.php +++ b/plugins/Monolog/config/cli.php @@ -2,6 +2,7 @@ use Interop\Container\ContainerInterface; use Monolog\Logger; +use Piwik\Plugins\Monolog\Handler\FailureLogMessageDetector; use Symfony\Bridge\Monolog\Formatter\ConsoleFormatter; use Symfony\Bridge\Monolog\Handler\ConsoleHandler; use Symfony\Component\Console\Output\OutputInterface; @@ -10,6 +11,7 @@ return array( // Log 'log.handlers' => array( + DI\get(FailureLogMessageDetector::class), DI\get('Symfony\Bridge\Monolog\Handler\ConsoleHandler'), ), 'Symfony\Bridge\Monolog\Handler\ConsoleHandler' => function (ContainerInterface $c) { diff --git a/tests/PHPUnit/System/ConsoleTest.php b/tests/PHPUnit/System/ConsoleTest.php new file mode 100644 index 0000000000..ad45405718 --- /dev/null +++ b/tests/PHPUnit/System/ConsoleTest.php @@ -0,0 +1,100 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +namespace Piwik\Tests\System; + +use Piwik\Container\StaticContainer; +use Piwik\Plugin\ConsoleCommand; +use Piwik\Plugins\Monolog\Handler\FailureLogMessageDetector; +use Psr\Log\LoggerInterface; +use Monolog\Logger; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Piwik\Tests\Framework\TestCase\ConsoleCommandTestCase; + +class TestCommandWithWarning extends ConsoleCommand +{ + public function configure() + { + parent::configure(); + + $this->setName('test-command-with-warning'); + } + + public function execute(InputInterface $input, OutputInterface $output) + { + StaticContainer::get(LoggerInterface::class)->warning('warn'); + } +} + +class TestCommandWithError extends ConsoleCommand +{ + public function configure() + { + parent::configure(); + + $this->setName('test-command-with-error'); + $this->addOption('no-error', null, InputOption::VALUE_NONE); + } + + public function execute(InputInterface $input, OutputInterface $output) + { + if (!$input->getOption('no-error')) { + StaticContainer::get(LoggerInterface::class)->error('error'); + } + } +} + +class ConsoleTest extends ConsoleCommandTestCase +{ + public function setUp() + { + parent::setUp(); + $this->application->addCommands([ + new TestCommandWithWarning(), + new TestCommandWithError(), + ]); + + StaticContainer::get(FailureLogMessageDetector::class)->reset(); + } + + public function test_Console_ReturnsCorrectExitCode_IfCommandEmitsWarning() + { + $exitCode = $this->applicationTester->run([ + 'command' => 'test-command-with-warning', + ]); + $this->assertEquals(1, $exitCode); + } + + public function test_Console_ReturnsCorrectExitCode_IfCommandEmitsError() + { + $exitCode = $this->applicationTester->run([ + 'command' => 'test-command-with-error', + ]); + $this->assertEquals(1, $exitCode); + } + + public function test_Console_ReturnsCorrectExitCode_IfCommandDoesNotEmitAnything() + { + $exitCode = $this->applicationTester->run([ + 'command' => 'test-command-with-error', + '--no-error' => true, + ]); + $this->assertEquals(0, $exitCode); + } + + public static function provideContainerConfigBeforeClass() + { + return [ + 'log.handlers' => [\DI\get(FailureLogMessageDetector::class)], + LoggerInterface::class => \DI\object(Logger::class) + ->constructor('piwik', \DI\get('log.handlers'), \DI\get('log.processors')), + ]; + } +}
\ No newline at end of file |