Description
Summary
Hello,
As disclaimer, I'm not 100% sure if I'm doing everything good around this. I just want to be sure that this is an intended behavior.
Description:
Related documentation : https://developer.adobe.com/commerce/testing/guide/integration/
When executing integration testing on a magento custom instance, I encountered a crash :
---- /magento/dev/tests/integration> /usr/local/bin/php /magento/./vendor/phpunit/phpunit/phpunit
Exception: Starting Magento installation:
File permissions check...
[Progress: 1 / 1791]
Required extensions check...
[Progress: 2 / 1791]
Enabling Maintenance Mode...
[Progress: 3 / 1791]
Installing deployment configuration...
[Progress: 4 / 1791]
Installing database schema:
In Mysql.php line 672:
[Magento\Framework\DB\Adapter\TableNotFoundException (1146)]
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'test_database.eav_entity_type' doesn't exist, query was: SELECT `main_table`.* FROM `eav_entity_type` AS `main_table`
Exception trace:
at /magento/vendor/magento/framework/DB/Adapter/Pdo/Mysql.php:672
Magento\Framework\DB\Adapter\Pdo\Mysql->performQuery() at /magento/vendor/magento/framework/DB/Adapter/Pdo/Mysql.php:614
[...]
By diving into this to understand the issue, I find out the following :
- The first step of the test is to execute an install command to run the tests on a clean database (See the stack trace error)
Magento\Setup\Model\Installer->installSchema() at n/a:n/a
call_user_func_array() at /magento/setup/src/Magento/Setup/Model/Installer.php:407
Magento\Setup\Model\Installer->install() at /magento/setup/src/Magento/Setup/Console/Command/InstallCommand.php:237
Magento\Setup\Console\Command\InstallCommand->execute() at /magento/vendor/symfony/console/Command/Command.php:326
Symfony\Component\Console\Command\Command->run() at /magento/vendor/symfony/console/Application.php:1078
Symfony\Component\Console\Application->doRunCommand() at /magento/vendor/symfony/console/Application.php:324
Symfony\Component\Console\Application->doRun() at /magento/vendor/magento/framework/Console/Cli.php:118
Magento\Framework\Console\Cli->doRun() at /magento/vendor/symfony/console/Application.php:175
Symfony\Component\Console\Application->run() at /magento/bin/magento:23
During the installation script, the object manager is loaded in the following file :
https://github.com/magento/magento2/blob/2.4-develop/setup/src/Magento/Setup/Model/Installer.php
[...] // l.957 in the current file
public function installSchema(array $request)
{
/** @var \Magento\Framework\Registry $registry */
$registry = $this->objectManagerProvider->get()->get(\Magento\Framework\Registry::class); // <=== This call is triggering the error
//For backward compatibility in install and upgrade scripts with enabled parallelization.
$registry->register('setup-mode-enabled', true);
[...]
Stack trace is quiet unclear as the object manager is creating multiple instances of multiples objects for multiple DI.
What I found is that :
I have a module with a declared command using \Magento\Catalog\Api\ProductRepositoryInterface
Any repository or ResourceModel would have the same effect as \Magento\Eav\Model\Config::getEntityType is called by every \Magento\Eav\Model\Entity\AbstractEntity::setType which is called by any ResourceModel.
As we are currently installing the database (So tables are not available yet), the following call with always fail :
[...]
$this->entityTypeCollectionFactory->create()->getData();
[...]
For me, the issue is not that deep but my understanding of the install process is really low.
IMHO :
- Commands can use entity repository without impact.
- Install command must not try to load all listed commands as these commands are not necessary at this point (Obviously, we just want to registry object for legacy purpose, no need to have all commands loaded)
Issue would be in the following file :
https://github.com/magento/magento2/blob/2.4-develop/setup/src/Magento/Setup/Model/ObjectManagerProvider.php
[...]
public function get()
[...]
if (PHP_SAPI == 'cli') {
$this->createCliCommands(); // <== For me, this is the issue here
}
[...]
Magento should load a minimal object manager to get only the registry we want at this point and not load CliCommands here.
Commenting this line fixes the issue.
Please let me know if you can confirm that this is a code issue or if it's the intended behavior.
Kind Regards,
Baptiste
Examples
Adding a minimal command with the following code would probably trigger the issue
namespace Test\TestModule\Console;
class CommandWithRepositoryTest extends \Symfony\Component\Console\Command\Command
{
public function __construct(
private readonly \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
){
parent::__construct();
}
/**
* @inheritDoc
*/
protected function configure()
{
$this->setName('test:command');
parent::configure();
}
/**
* @inheritDoc
*/
protected function execute(
\Symfony\Component\Console\Input\InputInterface $input,
\Symfony\Component\Console\Output\OutputInterface $output)
: int{
// Useless, we just want to test the command
$this->productRepository->get('test');
return 0;
}
}
di.xml file :
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Framework\Console\CommandList">
<arguments>
<argument name="commands" xsi:type="array">
<item name="TestCommand" xsi:type="object">Test\TestModule\Console\CommandWithRepositoryTest</item>
</argument>
</arguments>
</type>
</config>
Then run a phpunit integration test (An install command should trigger the bug too)
Proposed solution
As I said before :
In my humble opinion, Magento should load a minimal object manager to get only the registry we want at this point and not load CliCommands here. This can be done by adding another method or a parameter to the ObjectManagerProvider to allow getting an ObjectManager without CliCommands.
Release note
No response
Triage and priority
- Severity: S0 - Affects critical data or functionality and leaves users without workaround.
- Severity: S1 - Affects critical data or functionality and forces users to employ a workaround.
- Severity: S2 - Affects non-critical data or functionality and forces users to employ a workaround.
- Severity: S3 - Affects non-critical data or functionality and does not force users to employ a workaround.
- Severity: S4 - Affects aesthetics, professional look and feel, “quality” or “usability”.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status