Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 34 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php: [ '7.4' ]
php: [ '8.3' ]
steps:
- name: Setup PHP
uses: shivammathur/setup-php@v2
Expand All @@ -28,7 +28,7 @@ jobs:
tools: composer, phplint

- name: Setup Extension
uses: actions/checkout@v5
uses: actions/checkout@v6

- name: Setup Composer
run: composer update
Expand All @@ -45,8 +45,20 @@ jobs:
strategy:
fail-fast: false
matrix:
php: [ '7.4' ]
mediawiki: [ REL1_35 ]
php: [ '7.4', '8.1', '8.3' ]
mediawiki: [ REL1_39, REL1_43 ]
# Ideally we would also add Phan for MW 1.35 and PHP 7.4, but it
# crashes when analyzing the AlwaysSafeRunner.php file and that version
# of phan is so old (3.2.6) that it isn't going to be supported
exclude:
# MW 1.43 requires PHP 8.1+
- php: '7.4'
mediawiki: REL1_43
# MW 1.39 requires mediawiki/mediawiki-phan-config@0.12.1 which
# requires mediawiki/phan-taint-check-plugin@4.0.0 which crashes
# on PHP 8.2+ due to use of deprecated string interpolation
- php: '8.3'
mediawiki: REL1_39
steps:
- name: Setup PHP
uses: shivammathur/setup-php@v2
Expand All @@ -57,13 +69,13 @@ jobs:
tools: composer

- name: Setup MediaWiki
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
repository: wikimedia/mediawiki
ref: ${{ matrix.mediawiki }}

- name: Setup Extension
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
path: extensions/${{ env.EXTNAME }}

Expand All @@ -81,12 +93,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Setup node
uses: actions/setup-node@v5
uses: actions/setup-node@v6
with:
node-version: 22

- name: Setup Extension
uses: actions/checkout@v5
uses: actions/checkout@v6

- name: Install dependencies
run: npm ci
Expand All @@ -102,18 +114,26 @@ jobs:
strategy:
fail-fast: false
matrix:
php: [ '7.4' ]
mediawiki: [ REL1_35 ]
php: [ '7.4', '8.1', '8.3' ]
mediawiki: [ REL1_39, REL1_43 ]
include:
# Only test MW 1.35 with PHP 7.4
- php: '7.4'
mediawiki: REL1_35
exclude:
# MW 1.43 requires PHP 8.1+
- php: '7.4'
mediawiki: REL1_43
steps:
- name: Setup Extension
uses: actions/checkout@v5
uses: actions/checkout@v6

- name: Setup test extension - examples
uses: actions/checkout@v6
with:
repository: wikimedia/mediawiki-extensions-examples
path: ${{ github.workspace }}/examples
ref: REL1_35
ref: ${{ matrix.mediawiki }}
fetch-depth: 10

# Examples is pinned to using minus-x 1.1.0, we use 1.1.3, and our
Expand All @@ -131,3 +151,5 @@ jobs:
mwbranch: ${{ matrix.mediawiki }}
extension: ${{ env.EXTNAME }}
extra_file: .github/PHPUnitSettings.php
# Examples extension on 1.43 complains about AUTO_INCREMENT
use_mysql: true
8 changes: 4 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"czproject/git-php": "^4.3"
},
"require-dev": {
"mediawiki/mediawiki-codesniffer": "48.0.0 || 38.0.0",
"mediawiki/mediawiki-phan-config": "0.10.6",
"mediawiki/mediawiki-codesniffer": "50.0.0 || 45.0.0 || 38.0.0",
"mediawiki/mediawiki-phan-config": "0.14.0 || 0.12.1 || 0.10.6",
"mediawiki/minus-x": "1.1.3",
"php-parallel-lint/php-console-highlighter": "0.5",
"php-parallel-lint/php-parallel-lint": "1.2.0"
"php-parallel-lint/php-console-highlighter": "1.0.0 || 0.5",
"php-parallel-lint/php-parallel-lint": "1.4.0 || 1.3.1 || 1.2.0"
},
"scripts": {
"test": [
Expand Down
3 changes: 2 additions & 1 deletion extension.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@
"AutoloadClasses": {
"WikiExtensions\\WikiExtensions": "includes/WikiExtensions.php",
"WikiExtensions\\SpecialExtensions": "includes/SpecialExtensions.php",
"WikiExtensions\\WikiExtensionsApi": "includes/WikiExtensionsApi.php"
"WikiExtensions\\WikiExtensionsApi": "includes/WikiExtensionsApi.php",
"WikiExtensions\\AlwaysSafeRunner": "includes/AlwaysSafeRunner.php"
},
"SpecialPages": {
"Extensions": "WikiExtensions\\SpecialExtensions"
Expand Down
4 changes: 3 additions & 1 deletion i18n/api/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@
"Daniel Scherzer"
]
},
"apihelp-wikiextensions-summary": "Manage extensions"
"apihelp-wikiextensions-summary": "Manage extensions",
"apihelp-wikiextensions-param-do": "Action to perform (list, extension, or update)",
"apihelp-wikiextensions-param-extension": "Extension to target (for information or updating)"
}
4 changes: 3 additions & 1 deletion i18n/api/qqq.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@
"Daniel Scherzer"
]
},
"apihelp-wikiextensions-summary": "{{doc-apihelp-summary|wikiextensions}}"
"apihelp-wikiextensions-summary": "{{doc-apihelp-summary|wikiextensions}}",
"apihelp-wikiextensions-param-do": "{{doc-apihelp-param|wikiextensions|do}}",
"apihelp-wikiextensions-param-extension": "{{doc-apihelp-param|wikiextensions|extension}}"
}
35 changes: 35 additions & 0 deletions includes/AlwaysSafeRunner.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace WikiExtensions;

use CzProject\GitPhp\IRunner;
use CzProject\GitPhp\Runners\CliRunner;

/**
* Version of CzProject\GitPhp's CLIRunner that adds `-c safe.directory=*` to
* all commands so that dubious ownership is ignored
*/
class AlwaysSafeRunner implements IRunner {

/** @var CliRunner */
private $baseRunner;

public function __construct( CliRunner $baseRunner ) {
$this->baseRunner = $baseRunner;
}

/** @inheritDoc */
public function run( $cwd, array $args, ?array $env = null ) {
return $this->baseRunner->run(
$cwd,
[ '-c', 'safe.directory=*', ...$args ],
$env
);
}

/** @inheritDoc */
public function getCwd() {
return $this->baseRunner->getCwd();
}

}
16 changes: 15 additions & 1 deletion includes/SpecialExtensions.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
<?php

// We run Phan with both MW 1.39 and MW 1.43, the suppression from 1.39 isn't
// needed on 1.43 and phan would complain about that
// @phan-file-suppress UnusedPluginSuppression,UnusedPluginFileSuppression

namespace WikiExtensions;

use PermissionsError;
Expand All @@ -19,7 +23,12 @@ public function __construct( $name = 'Extensions' ) {
*/
public function execute( $subPage = null ) {
$out = $this->getOutput();
$out->setPageTitle( $this->msg( 'wikiextensions-special-extensions-title' ) );
if ( version_compare( MW_VERSION, '1.41', '>=' ) ) {
// @phan-suppress-next-line PhanUndeclaredMethod
$out->setPageTitleMsg( $this->msg( 'wikiextensions-special-extensions-title' ) );
} else {
$out->setPageTitle( $this->msg( 'wikiextensions-special-extensions-title' ) );
}

if ( !$this->getUser()->isAllowed( 'wikiextensions_view' ) ) {
// it throws the PermissionsError exception
Expand All @@ -39,6 +48,11 @@ public function execute( $subPage = null ) {
$out->addHTML( $html );
}

/**
* Get the HTML that will be targetted by the JavaScript
*
* @return string
*/
private function renderHomepage() {
return "<div class='wikiextensions-wrapper'></div>";
}
Expand Down
17 changes: 7 additions & 10 deletions includes/WikiExtensions.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use CzProject\GitPhp\GitException;
use CzProject\GitPhp\GitRepository;
use CzProject\GitPhp\Runners\CliRunner;
use ExtensionRegistry;
use Status;

Expand Down Expand Up @@ -98,7 +99,7 @@ public function getExtension( $extensionName ) {
// Try to get some GIT information
try {
// Init the repository
$repo = new GitRepository( $path );
$repo = new GitRepository( $path, new AlwaysSafeRunner( new CliRunner() ) );
// Get local branch name
$localBranch = $repo->getCurrentBranchName();
$result['git']['branch'] = $localBranch;
Expand Down Expand Up @@ -138,8 +139,7 @@ public function getExtension( $extensionName ) {
$result['can_pull'] = (int)false;
}

}
catch ( GitException $e ) {
} catch ( GitException $e ) {
// Something gone wrong, do nothing
$result['error'] = $e->getMessage();
$result['can_pull'] = (int)false;
Expand All @@ -165,9 +165,8 @@ public function updateExtension( $extensionName ) {
$path = dirname( $this->things[$extensionName]['path'] );

try {
$repo = new GitRepository( $path );
}
catch ( GitException $e ) {
$repo = new GitRepository( $path, new AlwaysSafeRunner( new CliRunner() ) );
} catch ( GitException $e ) {
// We should not land here, not a repo
return Status::newFatal( $e->getMessage() );
}
Expand All @@ -176,8 +175,7 @@ public function updateExtension( $extensionName ) {
try {
// Work around https://github.com/czproject/git-php/issues/77
$repo->run( 'pull' );
}
catch ( GitException $e ) {
} catch ( GitException $e ) {
// A merge conflict?
if ( $e->getCode() === 1 ) {
try {
Expand Down Expand Up @@ -209,8 +207,7 @@ public function updateExtension( $extensionName ) {
'submodule',
'update'
] );
}
catch ( GitException $e ) {
} catch ( GitException $e ) {
return Status::newFatal( $e->getMessage() );
}
}
Expand Down
6 changes: 6 additions & 0 deletions includes/WikiExtensionsApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ private function updateExtension( $extension ) {
}
}

/**
* Can the user modify extension status based on being an anonymous user
* with an allowed IP address?
*
* @return bool
*/
private function isWhitelisted() {
$allowed = $this->getConfig()->get( 'WikiExtensionsAllowedIP' );
if ( $this->getUser()->isAnon() && IPUtils::isIPAddress( $this->getUser()->getName() ) ) {
Expand Down
25 changes: 20 additions & 5 deletions tests/phpunit/integration/WikiExtensionsApiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class WikiExtensionsApiTest extends ApiTestCase {
/** @var string */
private string $extensionPath;

private string $branch;

protected function setUp(): void {
parent::setUp();

Expand All @@ -44,6 +46,14 @@ protected function setUp(): void {
$this->setMwGlobals( [
'wgWikiExtensionsAllowedIP' => [ '192.168.0.0' ],
] );

if ( version_compare( MW_VERSION, '1.43', '>=' ) ) {
$this->branch = 'REL1_43';
} elseif ( version_compare( MW_VERSION, '1.39', '>=' ) ) {
$this->branch = 'REL1_39';
} else {
$this->branch = 'REL1_35';
}
}

protected function tearDown(): void {
Expand All @@ -53,7 +63,7 @@ protected function tearDown(): void {
// phpcs:ignore MediaWiki.Usage.ForbiddenFunctions.exec
exec( "git -C $path config remote.origin.url https://github.com/wikimedia/mediawiki-extensions-examples" );
// phpcs:ignore MediaWiki.Usage.ForbiddenFunctions.exec
exec( "git -C $path reset --hard origin/REL1_35" );
exec( "git -C $path reset --hard origin/" . $this->branch );

parent::tearDown();
}
Expand Down Expand Up @@ -149,7 +159,11 @@ public function testUpdateFailure() {
$this->assertIsArray( $innerRes );
$this->assertArrayHasKey( 'status', $innerRes );
// Not sure where this key comes from, but it should be improved
$this->assertSame( "* \$1\n* \$2", $innerRes['status'] );
if ( version_compare( MW_VERSION, '1.43', '>=' ) ) {
$this->assertSame( 'rawmessage', $innerRes['status'] );
} else {
$this->assertSame( "* \$1\n* \$2", $innerRes['status'] );
}
$this->assertArrayHasKey( 'extension', $innerRes );
$this->assertCount( 2, $innerRes );

Expand Down Expand Up @@ -177,6 +191,7 @@ private function verifyExtensionData( $data ) {
unset( $data['git']['remote_commit_short'] );
unset( $data['git']['local_commit_short'] );

$branch = $this->branch;
$this->assertSame(
[
'name' => 'examples',
Expand All @@ -188,10 +203,10 @@ private function verifyExtensionData( $data ) {
'can_pull' => 0,
'has_submodules' => 0,
'git' => [
'branch' => 'REL1_35',
'branch' => $branch,
'status' => [
'On branch REL1_35',
'Your branch is up to date with \'origin/REL1_35\'.',
'On branch ' . $branch,
"Your branch is up to date with 'origin/$branch'.",
'',
'nothing to commit, working tree clean',
],
Expand Down
Loading
Loading