-
-
Notifications
You must be signed in to change notification settings - Fork 495
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
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.
@@ -35,6 +36,27 @@ public function registerBundles() | |||
} | |||
} | |||
|
|||
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.
@@ -5,16 +5,16 @@ | |||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/6.1/phpunit.xsd" | |||
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! |
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.
@@ -35,6 +36,27 @@ public function registerBundles() | |||
} | |||
} | |||
|
|||
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
} | ||
(new Dotenv())->load(__DIR__.'/../.env'); | ||
} | ||
|
||
$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.
symfony/console/3.3/bin/console
Outdated
$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
@@ -35,6 +36,27 @@ public function registerBundles() | |||
} | |||
} | |||
|
|||
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)) {
// ...
}
// ...
@@ -35,6 +36,27 @@ public function registerBundles() | |||
} | |||
} | |||
|
|||
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
> | ||
<php> | ||
<ini name="error_reporting" value="-1" /> | ||
<env name="KERNEL_CLASS" value="App\Kernel" /> | ||
<env name="SHELL_VERBOSITY" value="-1" /> | ||
|
||
<!-- 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
.env
when needed - If
APP_ENV
is still not set, set$_SERVER['APP_ENV'] = 'dev'
; - Except, if
$env
is passed tobootstrapEnvironment()
(like for console), set that$env
value 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! |
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
.env
and.env.test
values will override.env
ones 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.