Repository navigation
Issue/575 console boot that cannot lock out core:env - #577
Conversation
…v file exists Add a non-throwing fileExists() that tells whether the environment file the app is configured for exists. It follows the same resolution as load(): the app_env of shared/config/env.php picks .env or .env.<app_env>. The resolution is shared with resolveEnvironmentFile() through two small private helpers, and it uses App::getBaseDir() instead of the base_dir() helper, so the method can be asked before the helpers are loaded. load() behaves as before. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ironment Add a requiresEnvironment property to CliCommand, true by default, with a public requiresEnvironment() getter, and set it to false in EnvCommand, which creates the environment file and must run when there is none. Nothing uses the getter yet; the run stage will in a following commit. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…v file is missing After the unknown command guard, RunCommandStage now asks the resolved command. A CliCommand that requires the environment is stopped with the same EnvException the boot raises when the environment file does not exist, before anything runs. Commands that declare they do not need it, such as core:env, and plain Symfony commands, such as list and help, still run. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…t is decided Add characterization tests for the boot done by the console adapter: an unknown command gets the full boot, core:env with an option still gets the reduced boot, the environment is mutable after a full boot, and the Symfony application is named from the app config after a full boot and UNKNOWN after the reduced boot. They pass on the current code and guard the following change that decides the boot by the environment file instead of the command name. The boot for a missing command name is deliberately not pinned, because that behavior is meant to change later. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…t by the command name The console adapter no longer compares the first argument with core:env. It asks Environment::fileExists() once and uses the answer for both the boot stages and the mutable environment step: with the environment file the app boots fully, whatever the command; without it only the helpers are loaded, so core:env can create the file. Commands that need the environment are stopped by RunCommandStage with the usual EnvException, and list and help now work without the file. Behavior change: core:env now gets the full boot when the environment file exists. Three tests used core:env with the file present as the trigger for the reduced boot (BootsReducedStagesForCoreEnvCommand, ...WithOptions and NamesTheApplicationUnknownAfterTheReducedBoot); they keep their assertions and now hide the environment file instead. New tests cover the full boot of core:env with the file, the reduced boot of any command without it, and start() with and without the file. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…e dir The overwrite check of core:env used the relative path .env, which PHP resolves against the current working directory, while the copy always went to the base dir. Running the command from another directory therefore skipped the confirmation and silently overwrote the project's existing .env. The check now uses the same base dir path as the copy. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The console run will continue after a failed boot and decide per command whether the failure matters, so the context needs to hold it. The new constructor argument is optional, so existing callers are unchanged. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…failure per command Deciding the boot by the env file could not repair a broken .env: an empty or malformed file got the full boot, which failed, so `core:env --yes` was locked out where the old name check could still repair it. The adapter now runs the whole boot in a try, keeps the failure and continues. RunCommandStage re-throws that failure only for a command that requires the environment, so `core:env`, `list` and `help` run in a failed boot and every other command reports the original error. start() throws the recorded failure when anything else fails first (for example a command constructor). The application starts as UNKNOWN and is named from the app config after a successful boot, and the environment becomes mutable only then. Replaced on purpose: the three tests that pinned the reduced boot for a missing env file, and the RunCommandStage tests that pinned the file-missing guard; both now describe the recorded boot failure. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…y it any more The console no longer asks whether the env file exists: it boots, keeps the failure and decides per command. fileExists(), its two private helpers, the getBaseDir() switch in resolveEnvironmentFile() and the tests that came with them are removed, so the Environment package is back to what master has. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 34 minutes. View limit details
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Merge Risk: ⚪ Minimal · up to
|
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 58840f4357
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…cing them The application is named from the app config after a successful boot, and `?:` also replaced an empty string or '0' with UNKNOWN. `??` still covers the null name that used to crash the console and keeps every other value. The two tests that set the app config before building the adapter now load the helpers themselves, so they also pass when run alone. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Closes #575
What changed
ConsoleAppAdapterno longer compares the first argument withcore:env. It runs oneBootPipelineinside atry; when the boot fails it keeps the failure and continues. The SymfonyApplicationis created once asUNKNOWNand named from the app config after a successful boot, and the environment becomes mutable only after a successful boot.RunCommandStagere-throws that original failure only for aCliCommandthat requires the environment, socore:env,listandhelpstill run in a failed boot.start()throws the recorded failure when anything else fails first, for example a command constructor.CliCommand::$requiresEnvironment(defaulttrue) withrequiresEnvironment();EnvCommandsets it tofalse.ConsoleContexttakes an optional boot failure and exposes it withgetBootFailure().EnvCommandlooks for the existing.envin the application base directory instead of the current working directory, so the overwrite confirmation is no longer skipped when the command runs from another directory.Why
The reduced boot was keyed to the string
core:env, so the adapter had to know a command name. Deciding by whether the env file exists looked like the fix, but a broken.env(empty, or a Dotenv syntax error) then got the full boot, which failed, andcore:env --yescould not repair it, where master could. The boot is now attempted, the failure is recorded and enforced per command, the same way Django does it. The change of approach is explained in the comment on #575.Breaking changes
None for applications.
CliCommandgains a property and a getter with a default that keeps today's behavior, andConsoleContextgains an optional constructor argument. The reduced boot forcore:envno longer exists:core:envgoes through the same boot as every command, and a failed boot no longer stops it.How behavior was proven
quantum/project, master against this branch: 7 project states (ok,.envmissing, empty, malformed, broken app config, broken logging config,fs.phpcallingenv()with no.env) by 5 commands (core:env --yes,list,core:version, unknown command, no command). The branch is never worse than master.core:env --yesrepairs wherever master did,listworks in the failure states where master crashed, and commands that require the environment show the same original error as master..env, a requiring and an opt-out command,list, an unknown command, and a command constructor that throws.Validation
vendor/bin/phpunit: 1680 tests, 4022 assertions, 28 errors (Redis/Memcached connections, the same 28 as on master), 4 skipped (optional Twig not installed)composer cs:checkandcomposer phpstanpassedNotes for reviewers
core:envruns in whatever state a failed boot leaves, so it must not rely on config.fs.phpthat callsenv()with no.envstill cannot be repaired. The same happens on master..envno longer crashes: the app runs with the nameUNKNOWN.ErrorHandleris a separate change.quantum-php-docs:cli/qt-command-line-tool.md,cli/console-commands.md,packages/console/*,packages/environment/*,packages/app/adapters.md,packages/app/architecture.md.Summary by CodeRabbit
.envfile in the application directory, even when run from another working directory.