Affects MW 1.32+
Summary
Given a tree with mediawiki/core and an extension having some requirements defined in extension.json (for example: WikibaseMediaInfo).
When running the Web installer, at the ?page=Options step, the extension should be shown with a disabled checkbox and hints at its dependencies. Instead the Extensions section is not even shown.
When running CLI installer with --with-extensions, the extension is skipped entirely and not added to LocalSettings.php. Which is to be expected since it is not functional due to the lack of dependency. However the installer keep processing just fine.
That has hit us on CI for which WikibaseMediaInfo lacked a dependency upon WikibaseCirrusSearch. Hence its PHPUnit tests were never run since the extension was not loaded. That has been solved by injecting the required dependency.
Expected
The WebInstaller should shows any extension that got cloned. Even if their registration is not valid.
install.php should fail when a requirement is missing instead of ignoring the extension and a status message shown to the user.
The root cause is Installer::findExtensionsByType() which just skip them. A summary would be:
$status = $this->getExtensionInfo( $type, $directory, $file ); if ( $status->isOK() ) { $exts[$file] = $status->value; } return $exts;
Which gets its informations from Installer::getExtensionInfo:
if ( $isJson ) { $jsonStatus = $this->readExtension( $fullJsonFile ); if ( !$jsonStatus->isOK() ) { return $jsonStatus; } $info += $jsonStatus->value; }
Since $jsonStatus is not ok, the extension is not added :-(
Reproduction
mkdir workspace2 quibble --db=sqlite \ --workspace=/home/hashar/workspace2 --git-cache=/home/hashar/projects \ --skip=all --skip-deps \ mediawiki/extensions/WikibaseMediaInfo
$ grep wfLoadExtension workspace2/src/LocalSettings.php $
Details
@Cparle had a nice issue today, the WikibaseMediaInfo extension was not showing in Special:Version after installing MediaWiki with install.php --with-extensions.
A way I reproduced it to run the installer with solely WikibaseMediaInfo cloned:
mkdir workspace2 quibble --db=sqlite \ --workspace=/home/hashar/workspace2 --git-cache=/home/hashar/projects \ --skip=all --skip-deps \ mediawiki/extensions/WikibaseMediaInfo
The install works fine. Looking at the generated LocalSettings.php:
# Enabled skins. # The following skins were automatically enabled: wfLoadSkin( 'Vector' ); # End of automatically generated settings. # Add more configuration options below.
Or in short, the extension has not been injected in the config which should have wfLoadExtension( 'WikibaseMediaInfo' );.
CI / Quibble does clone some repositories then runs install.php --with-extensions. I would eventually expect it to bail out immediately.
For the debugging session I have added a few var_dump in the installer with https://gerrit.wikimedia.org/r/#/c/mediawiki/core/+/502488/ then created a change depending on it https://gerrit.wikimedia.org/r/#/c/mediawiki/extensions/WikibaseMediaInfo/+/502489/ . The console log is at https://integration.wikimedia.org/ci/job/quibble-vendor-mysql-hhvm-docker/44086/consoleText
Installer::getExtensionInfo( type = extension, parentRelPath = extensions, name = WikibaseMediaInfo ) Installer::getExtensionInfoconfig comes from json Notice: Array to string conversion in /workspace/src/includes/installer/Installer.php on line 1312 object(Status)#778 (7) { ["cleanCallback"]=> bool(false) ["ok":protected]=> bool(false) ["errors":protected]=> array(1) { [0]=> array(3) { ["type"]=> string(5) "error" ["message"]=> string(26) "config-extension-not-found" ["params"]=> array(1) { [0]=> string(20) "WikibaseCirrusSearch" } } } ["value"]=> NULL ["success"]=> array(0) { } ["successCount"]=> int(0) ["failCount"]=> int(0) } string(24) "Json status is not OK :(" string(59) "Installer::findExtensionsByType(): getExtensionInfo got us:" object(Status)#778 (7) { ["cleanCallback"]=> bool(false) ["ok":protected]=> bool(false) ["errors":protected]=> array(1) { [0]=> array(3) { ["type"]=> string(5) "error" ["message"]=> string(26) "config-extension-not-found" ["params"]=> array(1) { [0]=> string(20) "WikibaseCirrusSearch" } } } ["value"]=> NULL ["success"]=> array(0) { } ["successCount"]=> int(0) ["failCount"]=> int(0) }
The whole logic is in Installer::readExtension
- WikibaseMediaInfo json is passed to the extension with a require for WikibaseCirrusSearch
- The ExtensionRegistry is used to load the file. That raises an ExtensionDependencyError due to the missing requires
- readExtension() is called again passing the missing extension a a hint (that causes the second var dump above?)
- the extension is not present, thus readExtension returns Status::newFatal( 'config-extension-not-found' );
- getExtensionInfo() returns the Status
In Installer::findExtensionsByType(), the extension is only added when getExtensionInfo() returned an OK status.