diff --git a/resources/lang/en/translations.php b/resources/lang/en/translations.php index 67f73c8..d5d3d0f 100644 --- a/resources/lang/en/translations.php +++ b/resources/lang/en/translations.php @@ -2,7 +2,10 @@ return [ 'every_var_has_been_set' => 'Every required .env variable has been set', - 'not_every_var_has_been_set' => 'Not every required .env variable has been set!', 'missing_vars_list' => 'Missing .env variables: :list', 'missing_vars_list_in_environment' => "Missing .env variables in ':environment' environment: :list", + 'not_every_var_has_been_set' => 'Not every required .env variable has been set!', + 'var_not_matching_value' => ":name is set to ':actual' instead of ':expected'", + 'vars_not_matching_values' => 'Some variables does not match their expected value', + 'vars_not_matching_values_list' => "Some variables does not match their expected value in ':environment' environment: :list", ]; diff --git a/resources/lang/it/translations.php b/resources/lang/it/translations.php index 17e66bc..82a0135 100644 --- a/resources/lang/it/translations.php +++ b/resources/lang/it/translations.php @@ -2,7 +2,10 @@ return [ 'every_var_has_been_set' => 'Tutte le variabili .env richieste sono state valorizzate', - 'not_every_var_has_been_set' => 'Non tutte le variabili .env richieste sono state valorizzate!', 'missing_vars_list' => 'Variabili .env mancanti: :list', 'missing_vars_list_in_environment' => "Variabili .env mancanti nell'ambiente ':environment': :list", + 'not_every_var_has_been_set' => 'Non tutte le variabili .env richieste sono state valorizzate!', + 'var_not_matching_value' => ":name รจ valorizzata a ':actual' invece di ':expected'", + 'vars_not_matching_values' => 'Alcune variabili non sono state valorizzate come previsto', + 'vars_not_matching_values_list' => "Alcune variabili non sono state valorizzate come previsto nell'ambiente ':environment': :list", ]; diff --git a/src/Health/Checks/CheckResultDto.php b/src/Health/Checks/CheckResultDto.php new file mode 100644 index 0000000..06e5d1c --- /dev/null +++ b/src/Health/Checks/CheckResultDto.php @@ -0,0 +1,46 @@ + */ + public array $meta, + public string $summary, + public string $message + ) { + // + } + + public static function ok(): self + { + return new self( + ok: true, + meta: [], + summary: '', + message: '' + ); + } + + /** + * @param array $meta + */ + public static function error(array $meta, string $summary, string $message): self + { + return new self( + ok: false, + meta: $meta, + summary: $summary, + message: $message + ); + } + + public function hasFailed(): bool + { + return ! $this->ok; + } +} diff --git a/src/Health/Checks/EnvVars.php b/src/Health/Checks/EnvVars.php index 588852d..0f0b579 100755 --- a/src/Health/Checks/EnvVars.php +++ b/src/Health/Checks/EnvVars.php @@ -14,19 +14,34 @@ class EnvVars extends Check /** @var Collection */ protected Collection $requiredVars; - /** @var Collection */ + /** @var Collection */ + protected Collection $requiredVarsWithValues; + + /** @var Collection */ protected Collection $environmentSpecificVars; + /** @var Collection> */ + protected Collection $environmentSpecificVarsWithValues; + /** * Run the check and return the Result */ public function run(): Result { - $this->requiredVars ??= Collection::empty(); - $this->environmentSpecificVars ??= Collection::empty(); + $this->requiredVars ??= collect(); + $this->environmentSpecificVars ??= collect(); + $this->requiredVarsWithValues ??= collect(); $result = Result::make(); + // Check required vars with values + $check = $this->checkRequiredVarsWithValues($this->requiredVarsWithValues); + if ($check->hasFailed()) { + return $result->meta($check->meta) + ->shortSummary($check->summary) + ->failed($check->message); + } + // Check all provided variable names match .env variables with non-empty value $missingVars = $this->missingVars($this->requiredVars); @@ -43,9 +58,9 @@ public function run(): Result /** @var string $currentEnvironment */ $currentEnvironment = App::environment(); // Same for environment specific vars (if any), returning different error messages - $missingVars = $this->missingVars( - $this->environmentSpecificVars->get($currentEnvironment, Collection::empty()) - ); + /** @var Collection $environmentSpecificVars */ + $environmentSpecificVars = $this->environmentSpecificVars->get($currentEnvironment, collect()); + $missingVars = $this->missingVars($environmentSpecificVars); if ($missingVars->count() > 0) { return $result->meta($missingVars->toArray()) @@ -75,6 +90,20 @@ public function requireVars(array $names): self return $this; } + /** + * Require the given variable names to be set (no matter in which environment) to the + * values supplied. + * + * @param array $values + * @return $this + */ + public function requireVarsMatchValues(array $values): self + { + $this->requiredVarsWithValues = collect($values); + + return $this; + } + /** * Require the given variable names to be set in the given environment * @@ -128,4 +157,38 @@ protected function missingVars(Collection $vars): Collection return $missingVars; } + + /** + * @param Collection $requiredVarsWithValues + */ + protected function checkRequiredVarsWithValues(Collection $requiredVarsWithValues): CheckResultDto + { + $failingVarNames = collect(); + $failingVarMessages = collect(); + + $requiredVarsWithValues->each(function ($expectedValue, $name) use ($failingVarNames, $failingVarMessages) { + $actualValue = getenv($name); + if ($expectedValue != $actualValue) { + $failingVarNames->push($name); + $failingVarMessages->push(trans('health-env-vars::translations.var_not_matching_value', [ + 'name' => $name, + 'expected' => $expectedValue, + 'actual' => $actualValue, + ])); + } + }); + + if ($failingVarNames->isEmpty()) { + return CheckResultDto::ok(); + } + + return CheckResultDto::error( + meta: $failingVarNames->toArray(), + summary: trans('health-env-vars::translations.vars_not_matching_values'), + message: trans('health-env-vars::translations.vars_not_matching_values_list', [ + 'environment' => App::environment(), + 'list' => $failingVarMessages->implode('; '), + ]) + ); + } } diff --git a/tests/MultipleEnvironmentTest.php b/tests/MultipleEnvironmentTest.php index 359af72..66043a0 100644 --- a/tests/MultipleEnvironmentTest.php +++ b/tests/MultipleEnvironmentTest.php @@ -5,6 +5,53 @@ const ENVIRONMENTS = ['staging', 'qa', 'production']; +afterEach(function () { + unsetEnvVars(['VAR1', 'VAR2', 'VAR3', 'VAR4']); +}); + +describe('when vars need to match values', function () { + it( + "returns an error if a var doesn't match the expected value in the current environment", + function (string $currentEnvironment) { + // ARRANGE + + $environments = ENVIRONMENTS; + $variableName = 'VAR1'; + $variableExpectedValue = 'expected value'; + $variableActualValue = 'another value'; + $missingList = "$variableName is set to '$variableActualValue' instead of '$variableExpectedValue'"; + + expect($currentEnvironment)->toBeIn($environments); + mockCurrentEnvironment($currentEnvironment); + + // init variable with a value different from the expected one + initEnvVars([ + $variableName => $variableActualValue, + ]); + expect(env($variableName))->not->toEqual($variableExpectedValue); + + // ACT & ASSERT + $result = EnvVars::new() + ->requireVarsMatchValues([ + $variableName => $variableExpectedValue, + ]) + ->run(); + + expect($result) + ->meta->toEqual([$variableName]) + ->status->toBe(Status::failed()) + ->shortSummary->toBe(trans('health-env-vars::translations.vars_not_matching_values')) + ->notificationMessage->toBe( + trans('health-env-vars::translations.vars_not_matching_values_list', [ + 'environment' => currentEnvironment(), + 'list' => $missingList, + ]) + ); + + } + )->with(ENVIRONMENTS); +}); + it( "returns an error if vars are required in multiple environments and at least one var hasn't been set in the ". 'current environment', diff --git a/tests/Pest.php b/tests/Pest.php index d18cdcf..cb680a9 100644 --- a/tests/Pest.php +++ b/tests/Pest.php @@ -13,7 +13,17 @@ function initEnvVars(array $vars): void { foreach ($vars as $name => $value) { - putenv("{$name}={$value}"); + putenv("$name=$value"); + } +} + +/** + * Unset the given .env variables. + */ +function unsetEnvVars(array $vars): void +{ + foreach ($vars as $name) { + putenv($name); } }