From 17e656497f7d3b70b950e6f539897d22b4e57108 Mon Sep 17 00:00:00 2001 From: Blaize M Kaye Date: Wed, 30 Aug 2023 05:41:36 +1200 Subject: [PATCH 1/5] First example of conditionals --- src/Runner.php | 18 +++- src/Step/Test.php | 22 +++- tests/RunnerTest.php | 100 ++++++++++++++++++ tests/assets/RunnerTestBasicCase.yaml | 3 + .../assets/RunnerTestConditionalDidntRun.yaml | 10 ++ tests/assets/RunnerTestConditionalRun.yaml | 10 ++ 6 files changed, 159 insertions(+), 4 deletions(-) create mode 100644 tests/RunnerTest.php create mode 100644 tests/assets/RunnerTestBasicCase.yaml create mode 100644 tests/assets/RunnerTestConditionalDidntRun.yaml create mode 100644 tests/assets/RunnerTestConditionalRun.yaml diff --git a/src/Runner.php b/src/Runner.php index ffa3a5a..6e31628 100644 --- a/src/Runner.php +++ b/src/Runner.php @@ -2,6 +2,8 @@ namespace Migrator; +use Migrator\Step\StepParent; + class Runner { use LoggerTrait; @@ -40,8 +42,20 @@ public function __get($name) public function run() { foreach ($this->steps as $step) { - //determine if this is a step or an assertion - if (!empty($step['assertTrue']) || !empty($step['assertFalse'])) { + + //determine if this is a step or an assertion or conditional + if($step['type'] == "conditional") { + // we determine if the condition is "true" - if so, we run the steps recursively + if(!isset($step['condition'])) { + throw new \Exception(sprintf("Failed on step '%s' - no condition attached", $step['name'])); + } + if($step['condition'] === true) { + $args = $this->args; + $args->steps = $step['steps']; + $runner = new Runner($args); + $runner->run(); + } + } else if (!empty($step['assertTrue']) || !empty($step['assertFalse'])) { $this->runAssertion($step); } else { $this->runStep($step); diff --git a/src/Step/Test.php b/src/Step/Test.php index 9a69da5..75fc85b 100644 --- a/src/Step/Test.php +++ b/src/Step/Test.php @@ -6,10 +6,28 @@ class Test extends StepParent { + public static $callbacks = []; + + public static function setCallback(callable $cb) + { + self::$callbacks[] = $cb; + } + + public static function clearCallbacks() + { + self::$callbacks = []; + } + public function runImplementation(array $args) { - //check we have all the args we need - //TODO: can be used to test things - will be removed + // check we have all the args we need + // we just run through all the registered callbacks and call them with the args + // This allows tests to attach their functions + foreach (self::$callbacks as $callback) { + if(is_callable($callback)) { + $callback($args); + } + } } } \ No newline at end of file diff --git a/tests/RunnerTest.php b/tests/RunnerTest.php new file mode 100644 index 0000000..ea59de6 --- /dev/null +++ b/tests/RunnerTest.php @@ -0,0 +1,100 @@ +getStepsFromFile( + __DIR__ . "/assets/RunnerTestBasicCase.yaml" + ); + $args = new \Migrator\RunnerArgs(); + $args->steps = $steps['steps']; + $runner = new \Migrator\Runner($args); + $runner->run(); + $this->assertTrue($testRan); + \Migrator\Step\Test::clearCallbacks(); + } + + /** + * This drives/tests the conditional system - basic conditional + * Further tests will work on textual substitutions etc. + * + * @return void + */ + function testConditionalRun() + { + //just testing the test case callback + $conditionalStepRan = false; + $cb = function ($args) use (&$conditionalStepRan) { + var_dump($args); + if(!empty($args['testid']) && $args['testid'] == 1) + { + $conditionalStepRan = true; + } + }; + \Migrator\Step\Test::setCallback($cb); + + $steps = $this->getStepsFromFile( + __DIR__ . "/assets/RunnerTestConditionalRun.yaml" + ); + $args = new \Migrator\RunnerArgs(); + $args->steps = $steps['steps']; + $runner = new \Migrator\Runner($args); + $runner->run(); + $this->assertTrue($conditionalStepRan); + \Migrator\Step\Test::clearCallbacks(); + } + + /** + * This drives/tests the conditional system - basic conditional + * Further tests will work on textual substitutions etc. + * + * @return void + */ + function testConditionalDidntRun() + { + //just testing the test case callback + $conditionalStepRan = false; + $cb = function ($args) use (&$conditionalStepRan) { + if(!empty($args['testid']) && $args['testid'] == 1) + { + $conditionalStepRan = true; + } + }; + \Migrator\Step\Test::setCallback($cb); + + $steps = $this->getStepsFromFile( + __DIR__ . "/assets/RunnerTestConditionalDidntRun.yaml" + ); + $args = new \Migrator\RunnerArgs(); + $args->steps = $steps['steps']; + $runner = new \Migrator\Runner($args); + $runner->run(); + $this->assertFalse($conditionalStepRan); + \Migrator\Step\Test::clearCallbacks(); + } + +} diff --git a/tests/assets/RunnerTestBasicCase.yaml b/tests/assets/RunnerTestBasicCase.yaml new file mode 100644 index 0000000..e567ed2 --- /dev/null +++ b/tests/assets/RunnerTestBasicCase.yaml @@ -0,0 +1,3 @@ +steps: + - name: basic run test + type: test \ No newline at end of file diff --git a/tests/assets/RunnerTestConditionalDidntRun.yaml b/tests/assets/RunnerTestConditionalDidntRun.yaml new file mode 100644 index 0000000..3115888 --- /dev/null +++ b/tests/assets/RunnerTestConditionalDidntRun.yaml @@ -0,0 +1,10 @@ +steps: + - name: basic run test + type: test + - name: conditional will always run + type: conditional + condition: false + steps: + - name: conditional first level + type: test + testid: 1 \ No newline at end of file diff --git a/tests/assets/RunnerTestConditionalRun.yaml b/tests/assets/RunnerTestConditionalRun.yaml new file mode 100644 index 0000000..9ac71c5 --- /dev/null +++ b/tests/assets/RunnerTestConditionalRun.yaml @@ -0,0 +1,10 @@ +steps: + - name: basic run test + type: test + - name: conditional will always run + type: conditional + condition: true + steps: + - name: conditional first level + type: test + testid: 1 \ No newline at end of file From 26541657c5d95f97b74cd59d6c607735bb5bf274 Mon Sep 17 00:00:00 2001 From: Blaize M Kaye Date: Wed, 30 Aug 2023 06:01:12 +1200 Subject: [PATCH 2/5] Factors out dynamic environment to its own trait --- src/Step/DynamicEnvironmentTrait.php | 54 ++++++++++++++++++++++++++++ src/Step/StepParent.php | 50 +------------------------- 2 files changed, 55 insertions(+), 49 deletions(-) create mode 100644 src/Step/DynamicEnvironmentTrait.php diff --git a/src/Step/DynamicEnvironmentTrait.php b/src/Step/DynamicEnvironmentTrait.php new file mode 100644 index 0000000..5ec5f3b --- /dev/null +++ b/src/Step/DynamicEnvironmentTrait.php @@ -0,0 +1,54 @@ + $val) { + if($key == "JSON_PAYLOAD") { + self::fillDynamicEnvironmentFromJSONPayload($val); + } else { + self::setVariable(sprintf("%s", $key), $val); + } + + } + } + + public static function fillDynamicEnvironmentFromJSONPayload($payload) { + + $decodedJson = base64_decode($payload); + if(!$decodedJson) { + throw new \Exception("Found JSON_PAYLOAD but could not decode it"); + } + + $vars = json_decode($decodedJson, true); + + if(json_last_error() > 0) { + throw new \Exception(sprintf("Could not decode JSONPAYLOAD: %s ", json_last_error_msg())); + } + + foreach ($vars as $key => $val) { + self::setVariable($key, $val); + } + } + + public static function setVariable($name, $value) { + self::$dynamicEnvironment[$name] = $value; + } + + public static function getVariable($name) { + if(!key_exists($name, self::$dynamicEnvironment)) { + throw new \Exception("Unable to find variable {$name} in dynamic environment - have you previously set it?"); + } + return self::$dynamicEnvironment[$name]; + } + + public static function getAllVariables() { + return self::$dynamicEnvironment; + } + +} diff --git a/src/Step/StepParent.php b/src/Step/StepParent.php index 397d37a..664ab01 100644 --- a/src/Step/StepParent.php +++ b/src/Step/StepParent.php @@ -12,7 +12,7 @@ abstract class StepParent implements StepInterface { - use LoggerTrait; + use LoggerTrait, DynamicEnvironmentTrait; protected $cluster; protected $namespace; protected $utilityBelt; @@ -20,54 +20,6 @@ abstract class StepParent implements StepInterface protected $args; protected $commandName; - static $dynamicEnvironment = []; - - - public static function fillDynamicEnvironmentFromEnv() { - $envVars = getenv(); - foreach ($envVars as $key => $val) { - if($key == "JSON_PAYLOAD") { - self::fillDynamicEnvironmentFromJSONPayload($val); - } else { - self::setVariable(sprintf("%s", $key), $val); - } - - } - } - - public static function fillDynamicEnvironmentFromJSONPayload($payload) { - - $decodedJson = base64_decode($payload); - if(!$decodedJson) { - throw new \Exception("Found JSON_PAYLOAD but could not decode it"); - } - - $vars = json_decode($decodedJson, true); - - if(json_last_error() > 0) { - throw new \Exception(sprintf("Could not decode JSONPAYLOAD: %s ", json_last_error_msg())); - } - - foreach ($vars as $key => $val) { - self::setVariable($key, $val); - } - } - - public static function setVariable($name, $value) { - self::$dynamicEnvironment[$name] = $value; - } - - public static function getVariable($name) { - if(!key_exists($name, self::$dynamicEnvironment)) { - throw new \Exception("Unable to find variable {$name} in dynamic environment - have you previously set it?"); - } - return self::$dynamicEnvironment[$name]; - } - - public static function getAllVariables() { - return self::$dynamicEnvironment; - } - public function __construct(LagoonUtilityBeltInterface $utilityBelt, RunnerArgs $args) { $this->cluster = $args->cluster; From 3e6a495b78423a65b9c9dcd72f9502adb23ec175 Mon Sep 17 00:00:00 2001 From: Blaize M Kaye Date: Wed, 30 Aug 2023 06:04:33 +1200 Subject: [PATCH 3/5] further factoring out of dynamic environment rendering --- src/Step/DynamicEnvironmentTrait.php | 8 ++++++++ src/Step/StepParent.php | 10 ++-------- tests/RunnerTest.php | 30 +++++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/Step/DynamicEnvironmentTrait.php b/src/Step/DynamicEnvironmentTrait.php index 5ec5f3b..0048330 100644 --- a/src/Step/DynamicEnvironmentTrait.php +++ b/src/Step/DynamicEnvironmentTrait.php @@ -2,6 +2,8 @@ namespace Migrator\Step; +use function WyriHaximus\Twig\render; + trait DynamicEnvironmentTrait { static $dynamicEnvironment = []; @@ -51,4 +53,10 @@ public static function getAllVariables() { return self::$dynamicEnvironment; } + public static function renderText($template, $extraVars = []) + { + $subs = array_merge(self::getAllVariables(), $extraVars); + return render($template, $subs); + } + } diff --git a/src/Step/StepParent.php b/src/Step/StepParent.php index 664ab01..c4d4928 100644 --- a/src/Step/StepParent.php +++ b/src/Step/StepParent.php @@ -58,19 +58,13 @@ public function run(array $args) { */ public function doTextSubstitutions($string) { - $substitutions = [ + $extraSubs = [ 'project' => $this->args->project, 'environment' => $this->args->environment, 'namespace' => $this->args->namespace, ]; - //Here we reach into the dynamic environment to grab any other arbitrarily defined vars - foreach (self::getAllVariables() as $key => $value) { - $substitutions[$key] = $value; - } - - - return render($string, $substitutions); + return self::renderText($string, $extraSubs); } // We use dynamic dispatch to allow us to do some logging and diff --git a/tests/RunnerTest.php b/tests/RunnerTest.php index ea59de6..ab00a71 100644 --- a/tests/RunnerTest.php +++ b/tests/RunnerTest.php @@ -49,7 +49,6 @@ function testConditionalRun() //just testing the test case callback $conditionalStepRan = false; $cb = function ($args) use (&$conditionalStepRan) { - var_dump($args); if(!empty($args['testid']) && $args['testid'] == 1) { $conditionalStepRan = true; @@ -97,4 +96,33 @@ function testConditionalDidntRun() \Migrator\Step\Test::clearCallbacks(); } + /** + * This drives/tests the conditional system - basic conditional + * Further tests will work on textual substitutions etc. + * + * @return void + */ + function testConditionalWithTwigConditions() + { + //just testing the test case callback + $conditionalStepRan = false; + $cb = function ($args) use (&$conditionalStepRan) { + if(!empty($args['testid']) && $args['testid'] == 1) + { + $conditionalStepRan = true; + } + }; + \Migrator\Step\Test::setCallback($cb); + + $steps = $this->getStepsFromFile( + __DIR__ . "/assets/RunnerTestConditionalDidntRun.yaml" + ); + $args = new \Migrator\RunnerArgs(); + $args->steps = $steps['steps']; + $runner = new \Migrator\Runner($args); + $runner->run(); + $this->assertFalse($conditionalStepRan); + \Migrator\Step\Test::clearCallbacks(); + } + } From d21abe1437a401d0a2dac3ff3b941b4271f4e0ad Mon Sep 17 00:00:00 2001 From: Blaize M Kaye Date: Wed, 30 Aug 2023 06:25:38 +1200 Subject: [PATCH 4/5] Conditional twig test --- src/Runner.php | 6 +++++- tests/RunnerTest.php | 19 ++++++++++++++----- tests/assets/RunnerTestConditionalTwig.yaml | 17 +++++++++++++++++ 3 files changed, 36 insertions(+), 6 deletions(-) create mode 100644 tests/assets/RunnerTestConditionalTwig.yaml diff --git a/src/Runner.php b/src/Runner.php index 6e31628..b7407cd 100644 --- a/src/Runner.php +++ b/src/Runner.php @@ -2,6 +2,7 @@ namespace Migrator; +use Migrator\Step\DynamicEnvironmentTrait; use Migrator\Step\StepParent; class Runner @@ -49,7 +50,10 @@ public function run() if(!isset($step['condition'])) { throw new \Exception(sprintf("Failed on step '%s' - no condition attached", $step['name'])); } - if($step['condition'] === true) { + + $condition = DynamicEnvironmentTrait::renderText($step['condition']); + + if($condition == true) { $args = $this->args; $args->steps = $step['steps']; $runner = new Runner($args); diff --git a/tests/RunnerTest.php b/tests/RunnerTest.php index ab00a71..f9a4ca4 100644 --- a/tests/RunnerTest.php +++ b/tests/RunnerTest.php @@ -105,23 +105,32 @@ function testConditionalDidntRun() function testConditionalWithTwigConditions() { //just testing the test case callback - $conditionalStepRan = false; - $cb = function ($args) use (&$conditionalStepRan) { + $conditionalStepShouldHaveRun = false; + \Migrator\Step\DynamicEnvironmentTrait::setVariable('RUN_THIS', "true"); + \Migrator\Step\DynamicEnvironmentTrait::setVariable('DONT_RUN_THAT', "true"); + $conditionalStepShouldNotHaveRun = true; + $cb = function ($args) use (&$conditionalStepShouldHaveRun, &$conditionalStepShouldNotHaveRun) { if(!empty($args['testid']) && $args['testid'] == 1) { - $conditionalStepRan = true; + $conditionalStepShouldHaveRun = true; + } + if(!empty($args['testid']) && $args['testid'] == 2) + { + $conditionalStepShouldNotHaveRun = false; } }; \Migrator\Step\Test::setCallback($cb); $steps = $this->getStepsFromFile( - __DIR__ . "/assets/RunnerTestConditionalDidntRun.yaml" + __DIR__ . "/assets/RunnerTestConditionalTwig.yaml" ); $args = new \Migrator\RunnerArgs(); $args->steps = $steps['steps']; $runner = new \Migrator\Runner($args); $runner->run(); - $this->assertFalse($conditionalStepRan); + $this->assertTrue($conditionalStepShouldHaveRun); + $this->assertTrue($conditionalStepShouldNotHaveRun); + \Migrator\Step\Test::clearCallbacks(); } diff --git a/tests/assets/RunnerTestConditionalTwig.yaml b/tests/assets/RunnerTestConditionalTwig.yaml new file mode 100644 index 0000000..f54bdc2 --- /dev/null +++ b/tests/assets/RunnerTestConditionalTwig.yaml @@ -0,0 +1,17 @@ +steps: + - name: basic run test + type: test + - name: conditional will run if RUN_THIS is set to true + type: conditional + condition: '{{ RUN_THIS == "true" ? true : false }}' + steps: + - name: conditional first level + type: test + testid: 1 + - name: conditional will run if DONT_RUN_THAT is set to false + type: conditional + condition: '{{ DONT_RUN_THAT == "false" ? true : false }}' + steps: + - name: conditional first level + type: test + testid: 2 \ No newline at end of file From 7912252c7dd67d36afd879680b1cd4b45aab7333 Mon Sep 17 00:00:00 2001 From: Blaize M Kaye Date: Wed, 30 Aug 2023 06:36:30 +1200 Subject: [PATCH 5/5] Fixes test --- tests/DeployTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/DeployTest.php b/tests/DeployTest.php index d4a5651..1f78387 100644 --- a/tests/DeployTest.php +++ b/tests/DeployTest.php @@ -48,7 +48,7 @@ public function testStandardTextualSubstitutionsInArgs() { // Here we replace LAGOON_BACKUPS_DISABLED with whatever is // placed into the dynamic environment - $buildVars = ['LAGOON_BACKUPS_DISABLED', '{{ LAGOON_BACKUPS_DISABLED }}']; + $buildVars = [["name" => 'LAGOON_BACKUPS_DISABLED', "value"=>'{{ LAGOON_BACKUPS_DISABLED }}']]; $args = [ 'project' => 'testproject', @@ -58,7 +58,7 @@ public function testStandardTextualSubstitutionsInArgs() { ]; // Once the textual subs for $buildVars is done, we expect the following... - $buildWithSubs = ['LAGOON_BACKUPS_DISABLED', 'false']; + $buildWithSubs = [["name" => 'LAGOON_BACKUPS_DISABLED', "value"=>'false']]; $lub->expects($this->once()) ->method("deployEnvironment")