diff --git a/PHPCI/BuildLogger.php b/PHPCI/BuildLogger.php deleted file mode 100644 index ccb6288a..00000000 --- a/PHPCI/BuildLogger.php +++ /dev/null @@ -1,31 +0,0 @@ - */ -class Builder implements LoggerAwareInterface, BuildLogger +class Builder implements LoggerAwareInterface { /** * @var string @@ -75,12 +77,9 @@ class Builder implements LoggerAwareInterface, BuildLogger protected $lastOutput; /** - * An array of key => value pairs that will be used for - * interpolation and environment variables - * @var array - * @see setInterpolationVars() + * @var BuildInterpolator */ - protected $interpolation_vars = array(); + protected $interpolator; /** * @var \PHPCI\Store\BuildStore @@ -102,21 +101,34 @@ class Builder implements LoggerAwareInterface, BuildLogger */ protected $commandExecutor; + /** + * @var Logging\BuildLogger + */ + protected $buildLogger; + /** * Set up the builder. * @param \PHPCI\Model\Build $build * @param LoggerInterface $logger */ - public function __construct(Build $build, $logger = null) + public function __construct(Build $build, LoggerInterface $logger = null) { - if ($logger) { - $this->setLogger($logger); - } $this->build = $build; $this->store = Store\Factory::getStore('Build'); - $this->pluginExecutor = new Plugin\Util\Executor($this->buildPluginFactory($build), $this); - $this->commandExecutor = new CommandExecutor($this, PHPCI_DIR, $this->quiet, $this->verbose); + $this->buildLogger = new BuildLogger($logger, $build); + + $this->pluginExecutor = new Plugin\Util\Executor($this->buildPluginFactory($build), $this->buildLogger); + + $this->commandExecutor = new CommandExecutor( + $this->buildLogger, + PHPCI_DIR, + $this->quiet, + $this->verbose + ); + + $this->interpolator = new BuildInterpolator(); + } /** @@ -195,15 +207,15 @@ class Builder implements LoggerAwareInterface, BuildLogger if ($this->success) { $this->pluginExecutor->executePlugins($this->config, 'success'); - $this->logSuccess('BUILD SUCCESSFUL!'); + $this->buildLogger->logSuccess('BUILD SUCCESSFUL!'); } else { $this->pluginExecutor->executePlugins($this->config, 'failure'); - $this->logFailure("BUILD FAILURE"); + $this->buildLogger->logFailure("BUILD FAILURE"); } // Clean up: - $this->log('Removing build.'); + $this->buildLogger->log('Removing build.'); shell_exec(sprintf('rm -Rf "%s"', $this->buildPath)); // Update the build in the database, ping any external services, etc. @@ -239,107 +251,14 @@ class Builder implements LoggerAwareInterface, BuildLogger } /** - * Add an entry to the build log. - * @param string|string[] $message - * @param string $level - * @param mixed[] $context - */ - public function log($message, $level = LogLevel::INFO, $context = array()) - { - // Skip if no logger has been loaded. - if (!$this->logger) { - return; - } - - if (!is_array($message)) { - $message = array($message); - } - - // The build is added to the context so the logger can use - // details from it if required. - $context['build'] = $this->build; - - foreach ($message as $item) { - $this->logger->log($level, $item, $context); - } - } - - /** - * Add a success-coloured message to the log. - * @param string - */ - public function logSuccess($message) - { - $this->log("\033[0;32m" . $message . "\033[0m"); - } - - /** - * Add a failure-coloured message to the log. - * @param string $message - * @param \Exception $exception The exception that caused the error. - */ - public function logFailure($message, \Exception $exception = null) - { - $context = array(); - - // The psr3 log interface stipulates that exceptions should be passed - // as the exception key in the context array. - if ($exception) { - $context['exception'] = $exception; - } - - $this->log( - "\033[0;31m" . $message . "\033[0m", - LogLevel::ERROR, - $context - ); - } - - /** - * Replace every occurance of the interpolation vars in the given string + * Replace every occurrence of the interpolation vars in the given string * Example: "This is build %PHPCI_BUILD%" => "This is build 182" * @param string $input * @return string */ public function interpolate($input) { - $keys = array_keys($this->interpolation_vars); - $values = array_values($this->interpolation_vars); - return str_replace($keys, $values, $input); - } - - /** - * Sets the variables that will be used for interpolation. This must be run - * from setupBuild() because prior to that, we don't know the buildPath - */ - protected function setInterpolationVars() - { - $this->interpolation_vars = array(); - $this->interpolation_vars['%PHPCI%'] = 1; - $this->interpolation_vars['%COMMIT%'] = $this->build->getCommitId(); - $this->interpolation_vars['%PROJECT%'] = $this->build->getProjectId(); - $this->interpolation_vars['%BUILD%'] = $this->build->getId(); - $this->interpolation_vars['%PROJECT_TITLE%'] = $this->getBuildProjectTitle( - ); - $this->interpolation_vars['%BUILD_PATH%'] = $this->buildPath; - $this->interpolation_vars['%BUILD_URI%'] = PHPCI_URL . "build/view/" . $this->build->getId( - ); - $this->interpolation_vars['%PHPCI_COMMIT%'] = $this->interpolation_vars['%COMMIT%']; - $this->interpolation_vars['%PHPCI_PROJECT%'] = $this->interpolation_vars['%PROJECT%']; - $this->interpolation_vars['%PHPCI_BUILD%'] = $this->interpolation_vars['%BUILD%']; - $this->interpolation_vars['%PHPCI_PROJECT_TITLE%'] = $this->interpolation_vars['%PROJECT_TITLE%']; - $this->interpolation_vars['%PHPCI_BUILD_PATH%'] = $this->interpolation_vars['%BUILD_PATH%']; - $this->interpolation_vars['%PHPCI_BUILD_URI%'] = $this->interpolation_vars['%BUILD_URI%']; - - putenv('PHPCI=1'); - putenv('PHPCI_COMMIT=' . $this->interpolation_vars['%COMMIT%']); - putenv('PHPCI_PROJECT=' . $this->interpolation_vars['%PROJECT%']); - putenv('PHPCI_BUILD=' . $this->interpolation_vars['%BUILD%']); - putenv( - 'PHPCI_PROJECT_TITLE=' . $this->interpolation_vars['%PROJECT_TITLE%'] - ); - putenv('PHPCI_BUILD_PATH=' . $this->interpolation_vars['%BUILD_PATH%']); - putenv('PHPCI_BUILD_URI=' . $this->interpolation_vars['%BUILD_URI%']); + return $this->interpolator->interpolate($input); } /** @@ -352,7 +271,11 @@ class Builder implements LoggerAwareInterface, BuildLogger $this->ciDir = dirname(__FILE__) . '/../'; $this->buildPath = $this->ciDir . 'build/' . $buildId . '/'; - $this->setInterpolationVars(); + $this->interpolator->setupInterpolationVars( + $this->build, + $this->buildPath, + PHPCI_URL + ); // Create a working copy of the project: if (!$this->build->createWorkingCopy($this, $this->buildPath)) { @@ -369,7 +292,7 @@ class Builder implements LoggerAwareInterface, BuildLogger $this->ignore = $this->config['build_settings']['ignore']; } - $this->logSuccess('Working copy created: ' . $this->buildPath); + $this->buildLogger->logSuccess('Working copy created: ' . $this->buildPath); return true; } @@ -381,17 +304,31 @@ class Builder implements LoggerAwareInterface, BuildLogger */ public function setLogger(LoggerInterface $logger) { - $this->logger = $logger; + $this->buildLogger->setLogger($logger); + } + + public function log($message, $level = LogLevel::INFO, $context = array()) + { + $this->buildLogger->log($message, $level, $context); + } + + /** + * Add a success-coloured message to the log. + * @param string + */ + public function logSuccess($message) + { + $this->buildLogger->logSuccess($message); } /** - * returns the logger attached to this builder. - * - * @return LoggerInterface + * Add a failure-coloured message to the log. + * @param string $message + * @param \Exception $exception The exception that caused the error. */ - public function getLogger() + public function logFailure($message, \Exception $exception = null) { - return $this->logger; + $this->buildLogger->logFailure($message, $exception); } private function buildPluginFactory(Build $build) diff --git a/PHPCI/Command/RunCommand.php b/PHPCI/Command/RunCommand.php index 8415fafe..140a971c 100644 --- a/PHPCI/Command/RunCommand.php +++ b/PHPCI/Command/RunCommand.php @@ -10,9 +10,9 @@ namespace PHPCI\Command; use Monolog\Logger; -use PHPCI\Helper\BuildDBLogHandler; -use PHPCI\Helper\LoggedBuildContextTidier; -use PHPCI\Helper\OutputLogHandler; +use PHPCI\Logging\BuildDBLogHandler; +use PHPCI\Logging\LoggedBuildContextTidier; +use PHPCI\Logging\OutputLogHandler; use Psr\Log\LoggerAwareInterface; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; diff --git a/PHPCI/Helper/BuildInterpolator.php b/PHPCI/Helper/BuildInterpolator.php new file mode 100644 index 00000000..d4609793 --- /dev/null +++ b/PHPCI/Helper/BuildInterpolator.php @@ -0,0 +1,61 @@ + value pairs that will be used for + * interpolation and environment variables + * @var mixed[] + * @see setupInterpolationVars() + */ + protected $interpolation_vars = array(); + + /** + * Sets the variables that will be used for interpolation. + * @param Build $build + * @param string $buildPath + * @param string $phpCiUrl + */ + public function setupInterpolationVars(Build $build, $buildPath, $phpCiUrl) + { + $this->interpolation_vars = array(); + $this->interpolation_vars['%PHPCI%'] = 1; + $this->interpolation_vars['%COMMIT%'] = $build->getCommitId(); + $this->interpolation_vars['%PROJECT%'] = $build->getProjectId(); + $this->interpolation_vars['%BUILD%'] = $build->getId(); + $this->interpolation_vars['%PROJECT_TITLE%'] = $build->getProjectTitle(); + $this->interpolation_vars['%BUILD_PATH%'] = $buildPath; + $this->interpolation_vars['%BUILD_URI%'] = $phpCiUrl . "build/view/" . $build->getId(); + $this->interpolation_vars['%PHPCI_COMMIT%'] = $this->interpolation_vars['%COMMIT%']; + $this->interpolation_vars['%PHPCI_PROJECT%'] = $this->interpolation_vars['%PROJECT%']; + $this->interpolation_vars['%PHPCI_BUILD%'] = $this->interpolation_vars['%BUILD%']; + $this->interpolation_vars['%PHPCI_PROJECT_TITLE%'] = $this->interpolation_vars['%PROJECT_TITLE%']; + $this->interpolation_vars['%PHPCI_BUILD_PATH%'] = $this->interpolation_vars['%BUILD_PATH%']; + $this->interpolation_vars['%PHPCI_BUILD_URI%'] = $this->interpolation_vars['%BUILD_URI%']; + + putenv('PHPCI=1'); + putenv('PHPCI_COMMIT=' . $this->interpolation_vars['%COMMIT%']); + putenv('PHPCI_PROJECT=' . $this->interpolation_vars['%PROJECT%']); + putenv('PHPCI_BUILD=' . $this->interpolation_vars['%BUILD%']); + putenv('PHPCI_PROJECT_TITLE=' . $this->interpolation_vars['%PROJECT_TITLE%']); + putenv('PHPCI_BUILD_PATH=' . $this->interpolation_vars['%BUILD_PATH%']); + putenv('PHPCI_BUILD_URI=' . $this->interpolation_vars['%BUILD_URI%']); + } + + /** + * Replace every occurrence of the interpolation vars in the given string + * Example: "This is build %PHPCI_BUILD%" => "This is build 182" + * @param string $input + * @return string + */ + public function interpolate($input) + { + $keys = array_keys($this->interpolation_vars); + $values = array_values($this->interpolation_vars); + return str_replace($keys, $values, $input); + } +} \ No newline at end of file diff --git a/PHPCI/Helper/CommandExecutor.php b/PHPCI/Helper/CommandExecutor.php index 43813924..60061404 100644 --- a/PHPCI/Helper/CommandExecutor.php +++ b/PHPCI/Helper/CommandExecutor.php @@ -3,12 +3,12 @@ namespace PHPCI\Helper; -use PHPCI\BuildLogger; +use \PHPCI\Logging\BuildLogger; class CommandExecutor { /** - * @var \PHPCI\BuildLogger + * @var \PHPCI\Logging\BuildLogger */ protected $logger; diff --git a/PHPCI/Helper/BuildDBLogHandler.php b/PHPCI/Logging/BuildDBLogHandler.php similarity index 96% rename from PHPCI/Helper/BuildDBLogHandler.php rename to PHPCI/Logging/BuildDBLogHandler.php index 6ae34379..60cf48d3 100644 --- a/PHPCI/Helper/BuildDBLogHandler.php +++ b/PHPCI/Logging/BuildDBLogHandler.php @@ -1,6 +1,6 @@ logger = $logger; + $this->build = $build; + } + + /** + * Add an entry to the build log. + * @param string|string[] $message + * @param string $level + * @param mixed[] $context + */ + public function log($message, $level = LogLevel::INFO, $context = array()) + { + // Skip if no logger has been loaded. + if (!$this->logger) { + return; + } + + if (!is_array($message)) { + $message = array($message); + } + + // The build is added to the context so the logger can use + // details from it if required. + $context['build'] = $this->build; + + foreach ($message as $item) { + $this->logger->log($level, $item, $context); + } + } + + /** + * Add a success-coloured message to the log. + * @param string + */ + public function logSuccess($message) + { + $this->log("\033[0;32m" . $message . "\033[0m"); + } + + /** + * Add a failure-coloured message to the log. + * @param string $message + * @param \Exception $exception The exception that caused the error. + */ + public function logFailure($message, \Exception $exception = null) + { + $context = array(); + + // The psr3 log interface stipulates that exceptions should be passed + // as the exception key in the context array. + if ($exception) { + $context['exception'] = $exception; + } + + $this->log( + "\033[0;31m" . $message . "\033[0m", + LogLevel::ERROR, + $context + ); + } + + /** + * Sets a logger instance on the object + * + * @param LoggerInterface $logger + * @return null + */ + public function setLogger(LoggerInterface $logger) + { + $this->logger = $logger; + } +} \ No newline at end of file diff --git a/PHPCI/Helper/LoggedBuildContextTidier.php b/PHPCI/Logging/LoggedBuildContextTidier.php similarity index 96% rename from PHPCI/Helper/LoggedBuildContextTidier.php rename to PHPCI/Logging/LoggedBuildContextTidier.php index a67dd88d..aa852ae5 100644 --- a/PHPCI/Helper/LoggedBuildContextTidier.php +++ b/PHPCI/Logging/LoggedBuildContextTidier.php @@ -1,6 +1,6 @@ getProject()->getTitle(); + } + + /** * Set Project - Accepts an ID, an array representing a Project or a Project model. * diff --git a/PHPCI/Plugin/Util/Executor.php b/PHPCI/Plugin/Util/Executor.php index 5bec1820..ceb1de55 100644 --- a/PHPCI/Plugin/Util/Executor.php +++ b/PHPCI/Plugin/Util/Executor.php @@ -2,7 +2,7 @@ namespace PHPCI\Plugin\Util; -use PHPCI\BuildLogger; +use \PHPCI\Logging\BuildLogger; class Executor { @@ -17,7 +17,7 @@ class Executor */ protected $pluginFactory; - function __construct(Factory $pluginFactory, BuildLogger $logger) + function __construct(Factory $pluginFactory,BuildLogger $logger) { $this->pluginFactory = $pluginFactory; $this->logger = $logger; diff --git a/Tests/PHPCI/Helper/BuildInterpolatorTest.php b/Tests/PHPCI/Helper/BuildInterpolatorTest.php new file mode 100644 index 00000000..c45e1b8c --- /dev/null +++ b/Tests/PHPCI/Helper/BuildInterpolatorTest.php @@ -0,0 +1,49 @@ +testedInterpolator = new BuildInterpolator(); + } + + public function testInterpolate_LeavesStringsUnchangedByDefault() + { + $string = "Hello World"; + $expectedOutput = "Hello World"; + + $actualOutput = $this->testedInterpolator->interpolate($string); + + $this->assertEquals($expectedOutput, $actualOutput); + } + + public function testInterpolate_LeavesStringsUnchangedWhenBuildIsSet() + { + $build = $this->prophesize('PHPCI\\Model\\Build')->reveal(); + + $string = "Hello World"; + $expectedOutput = "Hello World"; + + $this->testedInterpolator->setupInterpolationVars( + $build, + "/buildpath/", + "phpci.com" + ); + + $actualOutput = $this->testedInterpolator->interpolate($string); + + $this->assertEquals($expectedOutput, $actualOutput); + } +} + \ No newline at end of file diff --git a/Tests/PHPCI/Helper/CommandExecutorTest.php b/Tests/PHPCI/Helper/CommandExecutorTest.php index 008443e9..047f4258 100644 --- a/Tests/PHPCI/Helper/CommandExecutorTest.php +++ b/Tests/PHPCI/Helper/CommandExecutorTest.php @@ -15,7 +15,7 @@ class CommandExecutorTest extends ProphecyTestCase protected function setUp() { parent::setUp(); - $mockBuildLogger = $this->prophesize('\PHPCI\BuildLogger'); + $mockBuildLogger = $this->prophesize('PHPCI\Logging\BuildLogger'); $this->testedExecutor = new CommandExecutor($mockBuildLogger->reveal(), __DIR__ . "/"); } diff --git a/Tests/PHPCI/Logging/BuildLoggerTest.php b/Tests/PHPCI/Logging/BuildLoggerTest.php new file mode 100644 index 00000000..ed0e7341 --- /dev/null +++ b/Tests/PHPCI/Logging/BuildLoggerTest.php @@ -0,0 +1,107 @@ +mockLogger = $this->prophesize('\Psr\Log\LoggerInterface'); + $this->mockBuild = $this->prophesize('\PHPCI\Model\Build'); + + $this->testedBuildLogger = new BuildLogger( + $this->mockLogger->reveal(), + $this->mockBuild->reveal() + ); + } + + public function testLog_CallsWrappedLogger() + { + $level = LogLevel::NOTICE; + $message = "Testing"; + $contextIn = array(); + + $this->mockLogger->log($level, $message, Argument::type('array')) + ->shouldBeCalledTimes(1); + + $this->testedBuildLogger->log($message, $level, $contextIn); + } + + public function testLog_CallsWrappedLoggerForEachMessage() + { + $level = LogLevel::NOTICE; + $message = array("One", "Two", "Three"); + $contextIn = array(); + + $this->mockLogger->log($level, "One", Argument::type('array')) + ->shouldBeCalledTimes(1); + + $this->mockLogger->log($level, "Two", Argument::type('array')) + ->shouldBeCalledTimes(1); + + $this->mockLogger->log($level, "Three", Argument::type('array')) + ->shouldBeCalledTimes(1); + + $this->testedBuildLogger->log($message, $level, $contextIn); + } + + public function testLog_AddsBuildToContext() + { + $level = LogLevel::NOTICE; + $message = "Testing"; + $contextIn = array(); + + $expectedContext = array( + 'build' => $this->mockBuild->reveal() + ); + + $this->mockLogger->log($level, $message, $expectedContext) + ->shouldBeCalledTimes(1); + + $this->testedBuildLogger->log($message, $level, $contextIn); + } + + public function testLogFailure_LogsAsErrorLevel() + { + $message = "Testing"; + $expectedLevel = LogLevel::ERROR; + + $this->mockLogger->log($expectedLevel, + Argument::type('string'), + Argument::type('array')) + ->shouldBeCalledTimes(1); + + $this->testedBuildLogger->logFailure($message); + } + + public function testLogFailure_AddsExceptionContext() + { + $message = "Testing"; + + $exception = new \Exception("Expected Exception"); + + + $this->mockLogger->log(Argument::type('string'), + Argument::type('string'), + Argument::withEntry('exception', $exception)) + ->shouldBeCalledTimes(1); + + $this->testedBuildLogger->logFailure($message, $exception); + } +} + \ No newline at end of file diff --git a/Tests/PHPCI/Helper/LoggerConfigTest.php b/Tests/PHPCI/Logging/LoggerConfigTest.php similarity index 84% rename from Tests/PHPCI/Helper/LoggerConfigTest.php rename to Tests/PHPCI/Logging/LoggerConfigTest.php index 95ea3d62..68f28f3a 100644 --- a/Tests/PHPCI/Helper/LoggerConfigTest.php +++ b/Tests/PHPCI/Logging/LoggerConfigTest.php @@ -1,8 +1,10 @@ function() use ($expectedHandler) { return array($expectedHandler); @@ -36,7 +38,7 @@ class LoggerConfigTest extends PHPUnit_Framework_TestCase public function testGetFor_AttachesSpecificHandlers() { - $expectedHandler = new Monolog\Handler\NullHandler(); + $expectedHandler = new \Monolog\Handler\NullHandler(); $config = new LoggerConfig(array( "Specific" => function() use ($expectedHandler) { return array($expectedHandler); @@ -52,8 +54,8 @@ class LoggerConfigTest extends PHPUnit_Framework_TestCase public function testGetFor_IgnoresAlternativeHandlers() { - $expectedHandler = new Monolog\Handler\NullHandler(); - $alternativeHandler = new Monolog\Handler\NullHandler(); + $expectedHandler = new \Monolog\Handler\NullHandler(); + $alternativeHandler = new \Monolog\Handler\NullHandler(); $config = new LoggerConfig(array( "Specific" => function() use ($expectedHandler) { diff --git a/Tests/PHPCI/Plugin/Util/ExecutorTest.php b/Tests/PHPCI/Plugin/Util/ExecutorTest.php index ec640e95..01267217 100644 --- a/Tests/PHPCI/Plugin/Util/ExecutorTest.php +++ b/Tests/PHPCI/Plugin/Util/ExecutorTest.php @@ -22,7 +22,7 @@ class ExecutorTest extends ProphecyTestCase protected function setUp() { parent::setUp(); - $this->mockBuildLogger = $this->prophesize('\PHPCI\BuildLogger'); + $this->mockBuildLogger = $this->prophesize('\PHPCI\Logging\BuildLogger'); $this->mockFactory = $this->prophesize('\PHPCI\Plugin\Util\Factory'); $this->testedExecutor = new Executor($this->mockFactory->reveal(), $this->mockBuildLogger->reveal()); } diff --git a/console b/console index f855f5ab..47b14f99 100644 --- a/console +++ b/console @@ -20,7 +20,7 @@ use PHPCI\Command\DaemonCommand; use PHPCI\Command\PollCommand; use Symfony\Component\Console\Application; -$loggerConfig = \PHPCI\Helper\LoggerConfig::newFromFile(__DIR__ . "/loggerconfig.php"); +$loggerConfig = \PHPCI\Logging\LoggerConfig::newFromFile(__DIR__ . "/loggerconfig.php"); $application = new Application();