diff --git a/src/Runner.php b/src/Runner.php index ffa3a5a..b7407cd 100644 --- a/src/Runner.php +++ b/src/Runner.php @@ -2,6 +2,9 @@ namespace Migrator; +use Migrator\Step\DynamicEnvironmentTrait; +use Migrator\Step\StepParent; + class Runner { use LoggerTrait; @@ -40,8 +43,23 @@ 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'])); + } + + $condition = DynamicEnvironmentTrait::renderText($step['condition']); + + if($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/DynamicEnvironmentTrait.php b/src/Step/DynamicEnvironmentTrait.php new file mode 100644 index 0000000..0048330 --- /dev/null +++ b/src/Step/DynamicEnvironmentTrait.php @@ -0,0 +1,62 @@ + $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 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 397d37a..c4d4928 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; @@ -106,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/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/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") diff --git a/tests/RunnerTest.php b/tests/RunnerTest.php new file mode 100644 index 0000000..f9a4ca4 --- /dev/null +++ b/tests/RunnerTest.php @@ -0,0 +1,137 @@ +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) { + 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(); + } + + /** + * 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 + $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) + { + $conditionalStepShouldHaveRun = true; + } + if(!empty($args['testid']) && $args['testid'] == 2) + { + $conditionalStepShouldNotHaveRun = false; + } + }; + \Migrator\Step\Test::setCallback($cb); + + $steps = $this->getStepsFromFile( + __DIR__ . "/assets/RunnerTestConditionalTwig.yaml" + ); + $args = new \Migrator\RunnerArgs(); + $args->steps = $steps['steps']; + $runner = new \Migrator\Runner($args); + $runner->run(); + $this->assertTrue($conditionalStepShouldHaveRun); + $this->assertTrue($conditionalStepShouldNotHaveRun); + + \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 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