Skip to content

[Dotenv] DebugCommand must respect dotenv_path runtime configuration #47901

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

alamirault
Copy link
Contributor

Q A
Branch? 5.4
Bug fix? yes
New feature? no
Deprecations? no
Tickets Fix #47880
License MIT
Doc PR symfony/symfony-docs#...

Attempt to fix #47880. DebugCommand must respect dotenv_path when it's defined in composer.json. When it is defined, output will show relative path ✓ sub/path/.env.local.php

I took example on DotenvDumpCommand

$config = [];
if (is_file($projectDir = $this->projectDir)) {
$config = ['dotenv_path' => basename($projectDir)];
$projectDir = \dirname($projectDir);
}
$composerFile = $projectDir.'/composer.json';
$config += (is_file($composerFile) ? json_decode(file_get_contents($composerFile), true) : [])['extra']['runtime'] ?? [];
$dotenvPath = $projectDir.'/'.($config['dotenv_path'] ?? '.env');

@alamirault
Copy link
Contributor Author

@carsonbot find me a reviewer please

@carsonbot
Copy link

@rmikalkenas could maybe review this PR?

@rmikalkenas
Copy link
Contributor

LGTM!

Copy link
Member

@GromNaN GromNaN left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for taking care of this bug fix. Reading the directory from the config is too restrictive as the name of the file can be modified too.

The initial issue is that the file name .env is hardcoded in getEnvFiles. By using the config to generate the list of files, the dir path don't have to be passed separately from the file name and the code can be simplified.

(please ask if my comment is not clear)

@alamirault
Copy link
Contributor Author

Thank you @GromNaN, your explanations are very clear :)

I updated PR, I think is prettier now

Copy link
Member

@GromNaN GromNaN left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the update. That's a lot more lisible and correct.

The dotenv_path can be configured in several places. We cannot cover all the cases and guess when the Dotenv class is instantiated in the code with a custom path.

It would be possible if we added a new variable SYMFONY_DOTENV_PATH initialized by Dotenv (like SYMFONY_DOTENV_VARS), to store the configured path. But that kind of change cannot be done in a minor version (as a bugfix) and then it will have to target 6.3 as a new feature.

{
$projectDir = is_file($projectDir = $this->projectDirectory) ? basename($projectDir) : $projectDir;

$composerFile = $projectDir.'/composer.json';
Copy link
Member

@GromNaN GromNaN Nov 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the dotenv_path can be configured for Symfony Runtime in APP_RUNTIME_OPTIONS env var. We can look at it too, but I don't know what is the priority.

* In addition to the options managed by GenericRuntime, it accepts the following options:
* - "env" to define the name of the environment the app runs in;
* - "disable_dotenv" to disable looking for .env files;
* - "dotenv_path" to define the path of dot-env files - defaults to ".env";

$runtime = $_SERVER['APP_RUNTIME'] ?? $_ENV['APP_RUNTIME'] ?? %runtime_class%;
$runtime = new $runtime(($_SERVER['APP_RUNTIME_OPTIONS'] ?? $_ENV['APP_RUNTIME_OPTIONS'] ?? []) + %runtime_options%);

Copy link
Member

@GromNaN GromNaN left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's apply the bug fix like this and work on improving the feature in the new PR.

Co-authored-by: Jérôme Tamarelle <jerome@tamarelle.net>
Copy link
Member

@nicolas-grekas nicolas-grekas left a 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 not read from composer.json.
Instead, @GromNaN puts us on the correct path to me: we should only read from $_ENV['APP_RUNTIME_CONFIG'], and we should do this change as a sidekick:

--- a/src/Symfony/Component/Runtime/Internal/autoload_runtime.template
+++ b/src/Symfony/Component/Runtime/Internal/autoload_runtime.template
@@ -19,7 +19,7 @@ if (!is_object($app)) {
 }
 
 $runtime = $_SERVER['APP_RUNTIME'] ?? $_ENV['APP_RUNTIME'] ?? %runtime_class%;
-$runtime = new $runtime(($_SERVER['APP_RUNTIME_OPTIONS'] ?? $_ENV['APP_RUNTIME_OPTIONS'] ?? []) + %runtime_options%);
+$runtime = new $runtime($_ENV['APP_RUNTIME_OPTIONS'] = ($_SERVER['APP_RUNTIME_OPTIONS'] ?? $_ENV['APP_RUNTIME_OPTIONS'] ?? []) + %runtime_options%);
 

@GromNaN
Copy link
Member

GromNaN commented Dec 13, 2022

@nicolas-grekas symfony/dotenv is not always used with symfony/runtime. That's why I want to add a new variable SYMFONY_DOTENV_PATH that is initialized by Dotenv::bootEnv() with the path argument it received. This is more agnostic.

@nicolas-grekas
Copy link
Member

@GromNaN I missed that part. I'm not sure we should do this. Dotenv should remain clear of such concerns to me. The runtime is a better place - and would expose all options, not just a subset.

@GromNaN
Copy link
Member

GromNaN commented Dec 13, 2022

This command already rely on SYMFONY_DOTENV_VARS.

To make things cleaner, the path have to be injected into the command constructor instead of being discovered from env vars.
That way, if someone builds a symfony/console + symfony/dotenv application, they can explicitly set the dotenv path if needed.
We can use env var processors to extract the path (something like %env(key:dotenv_path:json:APP_RUNTIME_OPTIONS)%) when the command is registered in the container.

@nicolas-grekas nicolas-grekas modified the milestones: 5.4, 6.3 Dec 15, 2022
@nicolas-grekas
Copy link
Member

Constructor injection FTW I agree.
Works for you @alamirault?
I'm moving to the 6.3 milestone as this turned into an improvement.

@alamirault
Copy link
Contributor Author

@nicolas-grekas I will change to constructor injection. However which service will populate APP_RUNTIME_OPTIONS based on composer.json ?
SymfonyRuntime construct use composer extra but I think is never set in env APP_RUNTIME_OPTIONS, should we add a putenv somewhere ?

@GromNaN
Copy link
Member

GromNaN commented Nov 17, 2023

I haven't found how the dotenv_path could be injected into the command constructor as it is not known by the container.

I'm still convinced that there should be a SYMFONY_DOTENV_FILE variable containing the path to the .env file that has been parsed. It could even have the ordered list of parsed files, which would eliminate the need to reimplement the logic in getEnvFiles.

Symfony Runtime is optional. If people wants to call DotEnv explicitly with an other name, "the old way" on an other file, the command would work.

(new Dotenv())->bootEnv(dirname(__DIR__).'/custom/app.env');

@GromNaN
Copy link
Member

GromNaN commented Nov 17, 2023

I reworked this PR for 7.1, adding an env var #52638

@nicolas-grekas
Copy link
Member

Closing in favor of #52638, thanks for submitting.

nicolas-grekas added a commit that referenced this pull request Jan 2, 2024
…:dotenv` for custom `.env` path (GromNaN)

This PR was merged into the 7.1 branch.

Discussion
----------

[Dotenv] Add `SYMFONY_DOTENV_PATH`, consumed by `debug:dotenv` for custom `.env` path

| Q             | A
| ------------- | ---
| Branch?       | 7.1
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Issues        | Fix #47880
| License       | MIT

Continuation of #47901

Introduce `SYMFONY_DOTENV_PATH` set by DotEnv class and read by the `debug:dotenv` command to contextualize the debug info with the file that was actually parsed.

The custom path can be set in many ways:

- Doing a call to `(new Dotenv())->bootEnv(dirname(__DIR__).'my/custom/path/to/.env');`
- In `composer.json`: `"extra": { "runtime": { "dotenv_path": "my/custom/path/to/.env" }`
- With the env var: `$_SERVER['APP_RUNTIME_OPTIONS'] = ['dotenv_path' => 'my/custom/path/to/.env'];`

The dotenv file can be outside of the `project_dir`.

Commits
-------

52b6416 DotEnv debug command aware of custom dotenv_path
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants