jenkins-bot has submitted this change and it was merged.
Change subject: registration: Version the extension.json schema
......................................................................
registration: Version the extension.json schema
Versioning the extension.json schema will allow us to make breaking changes
to the schema in a non-breaking manner.
Extensiosn and skins will set a 'manifest_version' value, stating which
version of the schema the file is written for. Processor::extractInfo() will
be passed the version number, and can switch behavior depending upon it.
For backwards-compatability, a version number of 1 is assumed if none is set.
The validateRegistrationFile.php script will emit a warning if this is the
case.
Bug: T99344
Change-Id: I2086a1465ceaeedd1ccc6804fda2c304ad16ffa0
---
M docs/extension.schema.json
M includes/registration/ExtensionProcessor.php
M includes/registration/ExtensionRegistry.php
M includes/registration/Processor.php
M maintenance/convertExtensionToRegistration.php
M maintenance/validateRegistrationFile.php
M tests/phpunit/includes/registration/ExtensionProcessorTest.php
7 files changed, 61 insertions(+), 13 deletions(-)
Approvals:
Ori.livneh: Looks good to me, approved
Legoktm: Looks good to me, approved
jenkins-bot: Verified
diff --git a/docs/extension.schema.json b/docs/extension.schema.json
index d5c17a1..34cfe2c 100644
--- a/docs/extension.schema.json
+++ b/docs/extension.schema.json
@@ -3,6 +3,11 @@
"description": "MediaWiki extension.json schema",
"type": "object",
"properties": {
+ "manifest_version": {
+ "type": "integer",
+ "description": "Version of the extension.json schema
the extension.json file is in.",
+ "required": true
+ },
"name": {
"type": "string",
"description": "The extension's canonical name.",
diff --git a/includes/registration/ExtensionProcessor.php
b/includes/registration/ExtensionProcessor.php
index b0398eb..0a09ff5 100644
--- a/includes/registration/ExtensionProcessor.php
+++ b/includes/registration/ExtensionProcessor.php
@@ -81,6 +81,7 @@
'config',
'ParserTestFiles',
'AutoloadClasses',
+ 'manifest_version',
);
/**
@@ -125,9 +126,10 @@
/**
* @param string $path
* @param array $info
+ * @param int $version manifest_version for info
* @return array
*/
- public function extractInfo( $path, array $info ) {
+ public function extractInfo( $path, array $info, $version ) {
$this->extractConfig( $info );
$this->extractHooks( $info );
$dir = dirname( $path );
diff --git a/includes/registration/ExtensionRegistry.php
b/includes/registration/ExtensionRegistry.php
index ac39699..1c36407 100644
--- a/includes/registration/ExtensionRegistry.php
+++ b/includes/registration/ExtensionRegistry.php
@@ -12,6 +12,16 @@
class ExtensionRegistry {
/**
+ * Version of the highest supported manifest version
+ */
+ const MANIFEST_VERSION = 1;
+
+ /**
+ * Version of the oldest supported manifest version
+ */
+ const OLDEST_MANIFEST_VERSION = 1;
+
+ /**
* @var BagOStuff
*/
protected $cache;
@@ -128,11 +138,19 @@
if ( !is_array( $info ) ) {
throw new Exception( "$path is not a valid JSON
file." );
}
+ if ( !isset( $info['manifest_version' ] ) ) {
+ // For backwards-compatability, assume a
version of 1
+ $info['manifest_version'] = 1;
+ }
+ $version = $info['manifest_version'];
+ if ( $version < self::OLDEST_MANIFEST_VERSION ||
$version > self::MANIFEST_VERSION ) {
+ throw new Exception( "$path: unsupported
manifest_version: {$version}" );
+ }
$autoload = $this->processAutoLoader( dirname( $path ),
$info );
// Set up the autoloader now so custom processors will
work
$GLOBALS['wgAutoloadClasses'] += $autoload;
$autoloadClasses += $autoload;
- $processor->extractInfo( $path, $info );
+ $processor->extractInfo( $path, $info, $version );
}
$data = $processor->getExtractedInfo();
// Need to set this so we can += to it later
diff --git a/includes/registration/Processor.php
b/includes/registration/Processor.php
index 391f108..e1aaca7 100644
--- a/includes/registration/Processor.php
+++ b/includes/registration/Processor.php
@@ -16,9 +16,10 @@
*
* @param string $path Absolute path of JSON file
* @param array $info
+ * @param int $version manifest_version for info
* @return array "credits" information to store
*/
- public function extractInfo( $path, array $info );
+ public function extractInfo( $path, array $info, $version );
/**
* @return array With following keys:
diff --git a/maintenance/convertExtensionToRegistration.php
b/maintenance/convertExtensionToRegistration.php
index e0631a7..8adae2d 100644
--- a/maintenance/convertExtensionToRegistration.php
+++ b/maintenance/convertExtensionToRegistration.php
@@ -118,7 +118,8 @@
}
}
$out += $this->json;
-
+ // Put this at the bottom
+ $out['manifest_version'] = ExtensionRegistry::MANIFEST_VERSION;
$type = $this->hasOption( 'skin' ) ? 'skin' : 'extension';
$fname = "{$this->dir}/$type.json";
$prettyJSON = FormatJson::encode( $out, "\t",
FormatJson::ALL_OK );
diff --git a/maintenance/validateRegistrationFile.php
b/maintenance/validateRegistrationFile.php
index e764661..08af11a 100644
--- a/maintenance/validateRegistrationFile.php
+++ b/maintenance/validateRegistrationFile.php
@@ -12,18 +12,39 @@
$this->error( 'The JsonSchema library cannot be found,
please install it through composer.', 1 );
}
- $retriever = new JsonSchema\Uri\UriRetriever();
- $schema = $retriever->retrieve('file://' . dirname( __DIR__ ) .
'/docs/extension.schema.json' );
$path = $this->getArg( 0 );
$data = json_decode( file_get_contents( $path ) );
if ( !is_object( $data ) ) {
$this->error( "$path is not a valid JSON file.", 1 );
}
+ if ( !isset( $data->manifest_version ) ) {
+ $this->output("Warning: No manifest_version set,
assuming 1.\n" );
+ // For backwards-compatability assume 1
+ $data->manifest_version = 1;
+ }
+ $version = $data->manifest_version;
+ if ( $version !== ExtensionRegistry::MANIFEST_VERSION ) {
+ $schemaPath = dirname( __DIR__ ) .
"/docs/extension.schema.v$version.json";
+ } else {
+ $schemaPath = dirname( __DIR__ ) .
'/docs/extension.schema.json';
+ }
+
+ if ( $version < ExtensionRegistry::OLDEST_MANIFEST_VERSION
+ || $version > ExtensionRegistry::MANIFEST_VERSION
+ ) {
+ $this->error( "Error: $path is using a non-supported
schema version, it should use "
+ . ExtensionRegistry::MANIFEST_VERSION, 1 );
+ } elseif ( $version < ExtensionRegistry::MANIFEST_VERSION ) {
+ $this->output( "Warning: $path is using a deprecated
schema, and should be updated to "
+ . ExtensionRegistry::MANIFEST_VERSION . "\n" );
+ }
+ $retriever = new JsonSchema\Uri\UriRetriever();
+ $schema = $retriever->retrieve('file://' . $schemaPath );
$validator = new JsonSchema\Validator();
$validator->check( $data, $schema );
if ( $validator->isValid() ) {
- $this->output( "$path validates against the schema!\n"
);
+ $this->output( "$path validates against the version
$version schema!\n" );
} else {
foreach ( $validator->getErrors() as $error ) {
$this->output( "[{$error['property']}]
{$error['message']}\n" );
diff --git a/tests/phpunit/includes/registration/ExtensionProcessorTest.php
b/tests/phpunit/includes/registration/ExtensionProcessorTest.php
index 9474496..2df5568 100644
--- a/tests/phpunit/includes/registration/ExtensionProcessorTest.php
+++ b/tests/phpunit/includes/registration/ExtensionProcessorTest.php
@@ -28,7 +28,7 @@
'@metadata' => array( 'foobarbaz' ),
'AnAttribute' => array( 'omg' ),
'AutoloadClasses' => array( 'FooBar' =>
'includes/FooBar.php' ),
- ) );
+ ), 1 );
$extracted = $processor->getExtractedInfo();
$attributes = $extracted['attributes'];
@@ -95,7 +95,7 @@
*/
public function testRegisterHooks( $pre, $info, $expected ) {
$processor = new MockExtensionProcessor( array( 'wgHooks' =>
$pre ) );
- $processor->extractInfo( $this->dir, $info );
+ $processor->extractInfo( $this->dir, $info, 1 );
$extracted = $processor->getExtractedInfo();
$this->assertEquals( $expected,
$extracted['globals']['wgHooks'] );
}
@@ -112,7 +112,7 @@
'@IGNORED' => 'yes',
),
) + self::$default;
- $processor->extractInfo( $this->dir, $info );
+ $processor->extractInfo( $this->dir, $info, 1 );
$extracted = $processor->getExtractedInfo();
$this->assertEquals( 'somevalue',
$extracted['globals']['wgBar'] );
$this->assertEquals( 10, $extracted['globals']['wgFoo'] );
@@ -149,7 +149,7 @@
*/
public function testExtracttExtensionMessagesFiles( $input, $expected )
{
$processor = new ExtensionProcessor();
- $processor->extractInfo( $this->dir, $input + self::$default );
+ $processor->extractInfo( $this->dir, $input + self::$default, 1
);
$out = $processor->getExtractedInfo();
foreach ( $expected as $key => $value ) {
$this->assertEquals( $value, $out['globals'][$key] );
@@ -177,7 +177,7 @@
*/
public function testExtractMessagesDirs( $input, $expected ) {
$processor = new ExtensionProcessor();
- $processor->extractInfo( $this->dir, $input + self::$default );
+ $processor->extractInfo( $this->dir, $input + self::$default, 1
);
$out = $processor->getExtractedInfo();
foreach ( $expected as $key => $value ) {
$this->assertEquals( $value, $out['globals'][$key] );
@@ -190,7 +190,7 @@
*/
public function testExtractResourceLoaderModules( $input, $expected ) {
$processor = new ExtensionProcessor();
- $processor->extractInfo( $this->dir, $input + self::$default );
+ $processor->extractInfo( $this->dir, $input + self::$default, 1
);
$out = $processor->getExtractedInfo();
foreach ( $expected as $key => $value ) {
$this->assertEquals( $value, $out['globals'][$key] );
--
To view, visit https://gerrit.wikimedia.org/r/212239
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I2086a1465ceaeedd1ccc6804fda2c304ad16ffa0
Gerrit-PatchSet: 5
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Legoktm <[email protected]>
Gerrit-Reviewer: Legoktm <[email protected]>
Gerrit-Reviewer: Ori.livneh <[email protected]>
Gerrit-Reviewer: Parent5446 <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits