-
-
Notifications
You must be signed in to change notification settings - Fork 504
Bootstrap environment #408
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
ghost
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request passes validation.
|
|
||
| public static function bootstrapEnvironment(string $env = null) | ||
| { | ||
| $env = $env ?? $_SERVER['APP_ENV'] ?? null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we decide to include $env ?? $_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null we can remove the tenerary on phpunit bootsrap.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should do this. But, read $_ENV['APP_ENV'] first - it should take priority. This is consistent with how env vars are read in the container:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@weaverryan according to with what you just reviewed later:
So, for me, this $env argument is more of an optional, "override" - for a case where you want to use this $env even IF $_SERVER['APP_ENV'] is already set. So, it should be optional and should not be passed, except from the console.
This is the whole purpose of $env, so i think it should be read first, and fallback to the APP_ENV if we are not overriding it.
| backupGlobals="false" | ||
| colors="true" | ||
| bootstrap="vendor/autoload.php" | ||
| bootstrap="tests/bootstrap.php" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we update phpunit bridge configuration too ? or should this be done in phpunit bridge script instead?
|
Thanks for taking care of this @joshlopes! |
ghost
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request passes validation.
| } | ||
|
|
||
| $envFiles = ["$projectDir/.env"]; | ||
| if (file_exists($file = "$projectDir/.env.$env")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$env can be null here; under windows file_exists('.env.') will return true. So, if null === $env, then $envFiles will contain two elements: with .env and with .env.
| } | ||
| } | ||
|
|
||
| public static function bootstrapEnvironment(string $env = null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think $env should not be null here.
You already pass not null value from bin/console. You can pass a same value from public/index.php (you call bootstrapEnvironment and create $env var on the next line, just swap that lines and pass $env to bootstrapEnvironment!). Also you can pass $_SERVER['APP_ENV'] ?? 'test' from tests/bootstrap.php.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current logic (which we want to keep) says that the .env file should ONLY be loaded if !isset($_SERVER['APP_ENV']). That means that we do need to use $_SERVER['APP_ENV'] inside this method. So, for me, this $env argument is more of an optional, "override" - for a case where you want to use this $env even IF $_SERVER['APP_ENV'] is already set. So, it should be optional and should not be passed, except from the console.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@weaverryan environment could be not set if 'test' === $_SERVER['APP_ENV'] if symfony/flex#318 will be accepted. And if so, then .env file(s) should be loaded (or .env.test?). And if so, then $env should be passed from tests/bootstrap.php too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if $_SERVER['APP_ENV'] was defined, we assume we already have the enviromnents loaded.
symfony/console/3.3/bin/console
Outdated
| } | ||
|
|
||
| $input = new ArgvInput(); | ||
| $env = $input->getParameterOption(['--env', '-e'], $_SERVER['APP_ENV'] ?? 'dev', true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This means that the environment from .env will not be considered anymore as fallback
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think i got you now, i think we should default this to null if $_SERVER['APP_ENV'] does not exist. That way the .env file will still be loaded and the environment of .env will be used as fallback.
| $input = new ArgvInput(); | ||
| $env = $input->getParameterOption(['--env', '-e'], $_SERVER['APP_ENV'] ?? 'dev', true); | ||
|
|
||
| Kernel::bootstrapEnvironment($env); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see an issue here: as soon as you use --env, the .env file won't be loaded anymore, meaning the flag won't be usable anymore locally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
even when you don't use it btw, due to the default to dev
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stof not sure what you mean, the env will always be loaded if there is a .env file and DotEnv is registered. It will also load both .env and .env.{ENV}. The default Server APP_ENV that is for, say, production. Whereas the default would then be prod for the cases without the option defined and then bootstrap would not happen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any definition of APP_ENV in this file would not work btw, as it will always be set to a default value here to define $env
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stof i've changed so it loads .env and after that load whatever .env.$serverAppEnv was set there
| } | ||
| } | ||
|
|
||
| public static function bootstrapEnvironment(string $env = null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current logic (which we want to keep) says that the .env file should ONLY be loaded if !isset($_SERVER['APP_ENV']). That means that we do need to use $_SERVER['APP_ENV'] inside this method. So, for me, this $env argument is more of an optional, "override" - for a case where you want to use this $env even IF $_SERVER['APP_ENV'] is already set. So, it should be optional and should not be passed, except from the console.
| { | ||
| $env = $env ?? $_SERVER['APP_ENV'] ?? null; | ||
| $projectDir = __DIR__.'/..'; | ||
| if (!$env && !class_exists(Dotenv::class)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current functionality is to load .env if and only if !isset($_SERVER['APP_ENV']). To stay consistent, I think this logic should change to:
if (isset($_SERVER['APP_ENV'])) {
// environment is set, do not load .env
return;
}
// then the rest of the code
if (!class_exists(Dotenv::class)) {
// ...
}
// ...|
|
||
| public static function bootstrapEnvironment(string $env = null) | ||
| { | ||
| $env = $env ?? $_SERVER['APP_ENV'] ?? null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should do this. But, read $_ENV['APP_ENV'] first - it should take priority. This is consistent with how env vars are read in the container:
phpunit/phpunit/4.7/phpunit.xml.dist
Outdated
|
|
||
| <!-- override or set env variables for the test env here --> | ||
| <env name="APP_ENV" value="test" /> | ||
| <env name="APP_DEBUG" value="1" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe this even works. This will be a string "1". I think we should remove it.
| } | ||
| (new Dotenv())->load(__DIR__.'/../.env'); | ||
| } | ||
| Kernel::bootstrapEnvironment(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if we should SET $_SERVER['APP_ENV'] inside Kernel::bootstrapEnvironment();. Basically, move this logic there. We would:
- Load
.envwhen needed - If
APP_ENVis still not set, set$_SERVER['APP_ENV'] = 'dev'; - Except, if
$envis passed tobootstrapEnvironment()(like for console), set that$envvalue into$_SERVER['APP_ENV'].
We could do the same for $_SERVER['APP_DEBUG']. The idea would be to simplify / de-duplicate all of the APP_ENV and APP_DEBUG logic. We could even move the umask & Debug code into bootstrapEnvironment()
|
Ping @joshlopes! |
ghost
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request passes validation.
|
@weaverryan @dunglas should i just close this PR in favor of your PR's? I don't oppose to make it consistent with how react app is doing now for the env. |
|
+1 Let's close @joshlopes - but I would love your input on the other PR's that are being made for this :). |
…s dotenv behavior (dunglas) This PR was merged into the 4.2-dev branch. Discussion ---------- [DotEnv] Add a new loadForEnv() method mimicking Ruby's dotenv behavior | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no <!-- see https://symfony.com/bc --> | Deprecations? |no <!-- don't forget to update UPGRADE-*.md and src/**/CHANGELOG.md files --> | Tests pass? | yes <!-- please add some, will be required by reviewers --> | Fixed tickets | helps for symfony/recipes#465, symfony/recipes#408 | License | MIT | Doc PR | todo This PR adds a new `loadForEnv()` method that mimics the behavior of [Create React App](https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#what-other-env-files-can-be-used), [Rails' DotEnv](https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use) and probably some other libs: `DotEnv::loadForEnv()` will load the following files, starting from the bottom. The first value set (or those already defined in the environment) take precedence: - `.env` - The Original® - `.env.dev`, `.env.test`, `.env.prod`... - Environment-specific settings. - `.env.local` - Local overrides. This file is loaded for all environments _except_ `test`. - `.env.dev.local`, `.env.test.local`, `.env.prod.local`... - Local overrides of environment-specific settings. The plan is to use this method in the default SF installation (symfony/recipes#466). Commits ------- 774a78c [DotEnv] Add a new loadForEnv() method mimicking Ruby's dotenv behavior
Picking up one of @weaverryan branches and helping out glue everything together having in consideration the discussion on his PR #366 and the DotEnvLoad from @ogizanagi.
Below is the copy of that PR.
Fixes symfony/flex#251
WIP
Needs to be reviewed and need tests?
Problem
The problem is that currently, environment variables must be completely duplicated between .env and phpunit.xml.dist
Solution
Extend the Kernel to allow different env to be loaded, falling back to the old behaviour ($_SERVER['APP_ENV']). The env files are overwritten, so we always load
.envand.env.testvalues will override.envones and so on..env is read in the same way as bin/console and public/index.php
Environment variables in phpunit.xml.dist WIN over .env.