From f6866fafce7b66c8e9c924869806f21c20af399a Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Thu, 19 Oct 2023 19:45:29 +0100 Subject: [PATCH] feature: build mode closes #262 --- src/Build.php | 6 ++- src/BuildRunner.php | 17 +++++++-- src/Cli/RunCommand.php | 11 +++++- src/Configuration/Manifest.php | 19 +++++++++- src/Configuration/TaskBlock.php | 3 ++ src/TaskList.php | 8 +++- test/phpunit/Helper/Json/build.json | 18 +++++++++ .../phpunit/Helper/Json/build.other-mode.json | 10 +++++ test/phpunit/ManifestTest.php | 38 +++++++++++++++++++ 9 files changed, 120 insertions(+), 10 deletions(-) create mode 100644 test/phpunit/Helper/Json/build.json create mode 100644 test/phpunit/Helper/Json/build.other-mode.json create mode 100644 test/phpunit/ManifestTest.php diff --git a/src/Build.php b/src/Build.php index aef3d69..6a84307 100644 --- a/src/Build.php +++ b/src/Build.php @@ -10,11 +10,13 @@ class Build { public function __construct( string $jsonFilePath, - string $workingDirectory + string $workingDirectory, + ?string $mode = null ) { $this->taskList = new TaskList( $jsonFilePath, - $workingDirectory + $workingDirectory, + $mode, ); } diff --git a/src/BuildRunner.php b/src/BuildRunner.php index e67ed16..9b31b09 100644 --- a/src/BuildRunner.php +++ b/src/BuildRunner.php @@ -29,7 +29,10 @@ public function __construct(?string $path = null, ?Stream $stream = null) { } /** @SuppressWarnings(PHPMD.ExitExpression) */ - public function run(bool $continue = true):void { + public function run( + bool $continue = true, + ?string $mode = null + ):void { $workingDirectory = $this->formatWorkingDirectory(); $jsonPath = $this->getJsonPath($workingDirectory); @@ -40,7 +43,7 @@ public function run(bool $continue = true):void { // reference will suppress exceptions, instead filling the array with error // strings for output back to the terminal. $errors = []; - $build = $this->checkRequirements($jsonPath, $workingDirectory, $errors); + $build = $this->checkRequirements($jsonPath, $workingDirectory, $errors, $mode); if(!empty($errors)) { $this->showErrors($errors); @@ -92,11 +95,17 @@ protected function getJsonPath(string $workingDirectory):string { } /** @SuppressWarnings(PHPMD.ExitExpression) */ - protected function checkRequirements(string $jsonPath, string $workingDirectory, array $errors):Build { + protected function checkRequirements( + string $jsonPath, + string $workingDirectory, + array $errors, + ?string $mode + ):Build { try { $build = new Build( $jsonPath, - $workingDirectory + $workingDirectory, + $mode, ); } catch(JsonParseException $exception) { $this->stream->writeLine("Syntax error in $jsonPath", Stream::ERROR); diff --git a/src/Cli/RunCommand.php b/src/Cli/RunCommand.php index 3d58a36..e51549e 100644 --- a/src/Cli/RunCommand.php +++ b/src/Cli/RunCommand.php @@ -13,7 +13,10 @@ public function run(ArgumentValueList $arguments = null):void { if($arguments->contains("default")) { $buildRunner->setDefaultPath($arguments->get("default")); } - $buildRunner->run($arguments->contains("watch")); + $buildRunner->run( + $arguments->contains("watch"), + $arguments->get("mode"), + ); } public function getName():string { @@ -60,6 +63,12 @@ public function getOptionalParameterList():array { "d", "Path to a default build.json to use if there is no build.json in the project root." ), + new Parameter( + true, + "mode", + "m", + "Which version of build.json to build (e.g. production/development)." + ), ]; } } diff --git a/src/Configuration/Manifest.php b/src/Configuration/Manifest.php index 4a06983..be6499b 100644 --- a/src/Configuration/Manifest.php +++ b/src/Configuration/Manifest.php @@ -17,7 +17,7 @@ class Manifest implements Iterator { /** @var int Numerical index to use in iteration */ protected $iteratorIndex; - public function __construct(string $jsonFilePath) { + public function __construct(string $jsonFilePath, ?string $mode = null) { if(!is_file($jsonFilePath)) { throw new MissingBuildFileException($jsonFilePath); } @@ -27,6 +27,23 @@ public function __construct(string $jsonFilePath) { throw new JsonParseException(json_last_error_msg()); } + if($mode) { + $modeJsonFilePath = substr( + $jsonFilePath, + 0, + -strlen(".json"), + ); + $modeJsonFilePath .= ".$mode.json"; + if(!is_file($modeJsonFilePath)) { + throw new MissingBuildFileException($modeJsonFilePath); + } + $modeJson = json_decode(file_get_contents($modeJsonFilePath)); +// For legacy reasons, stdClass is used to represent the block details. +// This code might look weird, but it remains backwards compatible until an OOP +// refactoring is made. + $json = (object)array_merge((array)$json, (array)$modeJson); + } + $this->taskBlockList = []; foreach($json as $glob => $details) { $this->taskBlockList []= new TaskBlock( diff --git a/src/Configuration/TaskBlock.php b/src/Configuration/TaskBlock.php index 4135449..1d419a4 100644 --- a/src/Configuration/TaskBlock.php +++ b/src/Configuration/TaskBlock.php @@ -26,6 +26,9 @@ public function __construct(string $glob, object $details) { $this->require = null; } + if(is_null($details->execute)) { + throw new MissingConfigurationKeyException("execute"); + } $this->execute = new ExecuteBlock($details->execute); $this->name = $details->name ?? $this->execute->command; } diff --git a/src/TaskList.php b/src/TaskList.php index e24f7cc..f0c5e6c 100644 --- a/src/TaskList.php +++ b/src/TaskList.php @@ -12,12 +12,16 @@ class TaskList implements Iterator { /** @var int Numerical index to use in iteration */ protected $iteratorIndex; - public function __construct(string $jsonFilePath, string $baseDir = null) { + public function __construct( + string $jsonFilePath, + ?string $baseDir = null, + ?string $mode = null + ) { if(is_null($baseDir)) { $baseDir = dirname($jsonFilePath); } - $specification = new Manifest($jsonFilePath); + $specification = new Manifest($jsonFilePath, $mode); foreach($specification as $glob => $taskBlock) { $this->taskList[$glob] = new Task($taskBlock); } diff --git a/test/phpunit/Helper/Json/build.json b/test/phpunit/Helper/Json/build.json new file mode 100644 index 0000000..4a08cc2 --- /dev/null +++ b/test/phpunit/Helper/Json/build.json @@ -0,0 +1,18 @@ +{ + "/tmp/phpgt/build/*.txt": { + "name": "Example dev TXT", + "require": {}, + "execute": { + "command": "echo", + "arguments": ["hello", "text"] + } + }, + "/tmp/phpgt/build/*.md": { + "name": "Example dev MD", + "require": {}, + "execute": { + "command": "echo", + "arguments": ["hello", "markdown"] + } + } +} diff --git a/test/phpunit/Helper/Json/build.other-mode.json b/test/phpunit/Helper/Json/build.other-mode.json new file mode 100644 index 0000000..bc21fb6 --- /dev/null +++ b/test/phpunit/Helper/Json/build.other-mode.json @@ -0,0 +1,10 @@ +{ + "/tmp/phpgt/build/*.txt": { + "name": "Example other mode TXT", + "require": {}, + "execute": { + "command": "echo", + "arguments": ["hello", "text", "other"] + } + } +} diff --git a/test/phpunit/ManifestTest.php b/test/phpunit/ManifestTest.php new file mode 100644 index 0000000..cac75e5 --- /dev/null +++ b/test/phpunit/ManifestTest.php @@ -0,0 +1,38 @@ +getName()); + self::assertSame($currentJsonObj["execute"]["arguments"], $taskBlock->getExecuteBlock()->arguments); + next($jsonObj); + } + } + + public function testIterator_mode():void { + $jsonFile = "test/phpunit/Helper/Json/build.json"; + $jsonFileOther = "test/phpunit/Helper/Json/build.other-mode.json"; + $jsonObjOther = json_decode(file_get_contents($jsonFileOther), true); + $jsonObj = json_decode(file_get_contents($jsonFile), true); + $jsonObj = array_merge($jsonObj, $jsonObjOther); + + $sut = new Manifest($jsonFile, "other-mode"); + /** @var TaskBlock $taskBlock */ + foreach($sut as $taskBlock) { + $currentJsonObj = current($jsonObj); + self::assertSame($currentJsonObj["name"], $taskBlock->getName()); + self::assertSame($currentJsonObj["execute"]["arguments"], $taskBlock->getExecuteBlock()->arguments); + next($jsonObj); + } + } +}