Problem/Motivation
Something which is pretty common in other frameworks and standalone applications is getting the current environment from an environment variable. Rather than a hardcoded 'prod' we should be able to easily configure this value from the environment.
Proposed resolution
A call to getenv() will give us a value, I would suggest 'DRUPAL_ENV' maybe? So you could set this in the following ways:
- In your actual environment: export DRUPAL_ENV=staging
- Apache: SetEnv DRUPAL_ENV staging
- Nginx: fastcgi_param DRUPAL_ENV staging
- Using putenv() (settings.php etc..)
- Using Symfony's dotenv component or phpdotenv library
Everything else is in place to dump an environment specific container. The 'kernel.environment' variable will also be available to use (already there too).
So E.g. you could set this in a test like: putenv('DRUPAL_ENV=test') too.
Remaining tasks
Document the new DRUPAL_ENV environment variable.
- http://railsapps.github.io/rails-environment-variables.html
- https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/
- ... more ...
User interface changes
None.
API changes
Facilitates an environment variable: DRUPAL_ENV
| Comment | File | Size | Author |
|---|---|---|---|
| #1 | d8-env-var.patch | 413 bytes | damiankloip |
| d8-env-var.patch | 0 bytes | damiankloip |
Comments
Comment #1
damiankloip commentedComment #2
damiankloip commentedComment #3
damiankloip commentedComment #4
damiankloip commentedComment #5
dawehnerThat doesn't work for actual webtests ... there I guess we want to use prod anyway?
Added a couple of examples that environment variables are a common thing.
Comment #6
damiankloip commentedYeah, I guess that is a bad example :), the main point is, if you really wanted to, you could set that in your php code too.
Comment #7
fabianx commentedI kinda like the idea :).
Comment #8
damiankloip commentedhttps://github.com/vlucas/phpdotenv is also not bad.
Comment #9
damiankloip commentedComment #10
damiankloip commentedComment #11
dawehnerI just love the patch, still!
Comment #12
johannez commented+1 for PHPDotEnv
Comment #13
andrewmacpherson commentedUpdating issue summary. I'm not clear if this counts as a Drupal API change, but it's a far-reaching DX change that should be documented.
Where is the appropriate place to document it in core itself?
Comment #14
damiankloip commentedWhy is it a far reaching change? Or an API change? It's an optional use of an environment variable passed to the Drupal kernel. This is just an addition that people can use if they need.
It also doesn't create an environment variable, as the updated summary now suggests.
Comment #15
damiankloip commentedAs for documentation, maybe on the drupal kernel itself?
Comment #16
andrewmacpherson commentedI did say I wasn't clear whether to call this an API change. I sought clarification, because I'm not sure what to call it really - configuration, policy, ...? Before this patch, there wasn't an official way to tell the kernel about the environment, now there is.
It's far-reaching precisely because any developer can respond to it in any way they please. They can already use any arbitrary environment variables, of course, but this standardizes one which "belongs" to Drupal. If a sys-admin is to consider setting it, they need to know what it's supposed to be for.
My point is: if it has a big official-sounding "DRUPAL_" at the start then it's purpose and/or usage-guidelines should be documented somewhere. I'd expect to be able to find it on api.drupal.org for instance. If it doesn't have a clear purpose, then we're introducing something that can be used and abused arbitrarily.
I'm playing the fool, but this doesn't sound like a trivial addition to me.
Comment #17
andrewmacpherson commentedReworded the API section. How does "facilitates use of an environment variable" sound?
Comment #18
andrewmacpherson commentedYes, going by the patch in #1, it ought to be documented in DrupalKernel.
It should probably be documented somewhere else too, though. If it's an official Drupal environment variable, then a developer can react to it directly with getenv(), regardless of what the kernel does with it.
Perhaps in INSTALL.txt, or whichever handbook pages deal with server set-up. Maybe some examples of how to use it.
Comment #19
damiankloip commentedAgree, we would need some documentation. No one said it shouldn't have any. The past few comments seem a bit over dramatic though tbh.
People could use and abuse almost anything if you think about it like that. Not sure what you would do to abuse it? We aren't really adding anything, just checking for something. This is not a complete paradigm shift, and I don't think adding a pretty standard environment variable check will open the floodgates to anything. Why would people all of a sudden start adding getenv('DRUPAL_ENV') everywhere in their code?
Thinking about it, DrupalKernel is also not the right place to document this. It doesn't care about where the env parameter came from.
I am also happy to just leave this and switch out the front controller on sites that need to use something like this myself.
Comment #20
fabianx commented#19: I personally would still like to see this change.
What about adding an official API to DrupalKernel to get the running version:
e.g.
\Drupal::service('kernel')->getEnvironment()
or something like this?
Then anyone could do so as they please, but it would work the same with exchanged front-controller and with environment.
A getenv('DRUPAL_ENV') would then be a non-recommended API mis-use as it could not match and there is an official way, which means this is mainly important for sysadmins / devops then.
Comment #21
dawehnerWell, IMHO we should pass that as container parameter and this is all.
Comment #22
damiankloip commentedDon't we already have this as a container parameter?
Comment #23
dawehnerOh indeed, there is
kernel.environmentComment #27
dawehnerI added a general plan issue for environment variables: #2879846: Provide better support for environment variables
Comment #31
aaronmchaleAdding Symfony's dotenv component to the Issues Summary as another possible option.
Since Drupal is already heavily using Symfony I believe it makes more sense to stick with Symfony, but left the phpdotevn library there as an alternative option.
Comment #32
mfbPresumably lots of folks already use dotenv (symfony or otherwise) w/ Drupal; I know I do. Adopting it "officially" seems like a great idea.
Comment #33
dawehnerThat seems absolutely sensible. Having a big of a bigger plan for environment variables #2879846: Provide better support for environment variables would probably be nice for framework maintainers to make a comment about it.
Comment #34
mpotter commentedIn order to support the environment-specific config, #3028179: Config Environment module (original issue) wants to store the environment within the Drupal State system and will add a service for switching between environments (causing the appropriate config changes via ConfigTransform #2991683: Move configuration transformation API in \Drupal\Core\Config namespace).
While people are still fleshing this out, there will be some way to set the environment from the command line (e.g. drush) or via a service method. This is more complicated than just "change this variable in settings.php" as it requires updating the active config.
The new service should support "getEnvironment" and "setEnvironment" methods to hide the implementation details of using the State variable and rather than querying kernel.environment directly. The fact that Kernel already has an "environment" makes this more complex as that is used for container caching and might not be the same as the "config environment".
Since there is another issue for discussing support for environment variables more generally, perhaps this discussion can focus on the proper service API for getting/setting the environment to be compatible with the needs of Kernel and for environment-specific config.
Comment #36
mile23I'd suggest that we have a few different environments for use by core dev and CI: 'prod', 'update', 'functionaltest', 'kerneltest'.
This would allow us to factor all the brittle edge cases out of the kernel itself, and swap out
CoreServiceProviderforFunctionalTestCoreServiceProviderand so forth.In this way, the kernel could get rid of having to ask about
DRUPAL_TEST_IN_CHILD_SITEand just act as if it's a site under test because we told it explicitly.This would mean we don't allow the kernel to be configured by an environment variable because it should be configured by the caller.
index.phpwould say 'prod',update.phpwould say 'update', and so forth.Comment #37
mfbHmm, I would have thought that update could be running in prod, dev or test environment but wouldn't itself be an environment.
Comment #39
edgr commentedMaybe we should question this practice first. For example the twelve-factor app methodology is advising against grouping like stage, production, etc. See: https://www.12factor.net/config
Comment #40
mfbI personally am not proposing configuration grouping, I just wanted a way to identify which environment the app is running in (prod/dev/test). Some internal logic could use the environment parameter, while typical configs that need to be set for each instance/deploy would still use environment variables.
Comment #41
ghost of drupal pastThis is a massive, potentially fatal error introducing change. I think the time is now or never -- if we announced it six months ahead that D9 will ship like this then people running containers (because that's where you'll use this mostly) can verify they don't have anything named DRUPAL_ENV. But that's just my opinion, I do not feel ... specified ... to set this to 9.x-dev.
Comment #42
volegerI think kernel has to handle environments first (see #36) in existing callers, and then we can try to introduce DRUPAL_ENV to actually handle them.
Meanwhile filled issue for the 'update' environment #3126222: Introduce 'update' environment for DrupalKernel
Comment #50
kingdutchIn my recent blogpost (Web Archive Link) I've outlined how this comes essentially for free with #3313404: Use symfony/runtime for less bespoke bootstrap/compatibility with varied runtime environments while providing end-users an easy way to swap out the logic if needed.