Skip to content

Update docker-compose CI #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Dec 13, 2024
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
31 changes: 23 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,42 @@ jobs:

test:

runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
continue-on-error: ${{ matrix.experimental }}

strategy:
matrix:
include:
- mediawiki_version: '1.35'
chameleon_version: '4.1.0'
php_version: 7.4
chameleon_version: 4.2.1
database_type: mysql
database_image: "mysql:5.7"
coverage: true
experimental: false
- mediawiki_version: '1.36'
chameleon_version: dev-master
- mediawiki_version: '1.39'
php_version: 8.1
chameleon_version: 4.2.1
database_type: mysql
database_image: "mysql:8"
coverage: false
experimental: true
experimental: false

env:
MW_VERSION: ${{ matrix.mediawiki_version }}
CHAMELEON_VERSION: ${{ matrix.chameleon_version }}
PHP_VERSION: ${{ matrix.php_version }}
DB_TYPE: ${{ matrix.database_type }}
DB_IMAGE: ${{ matrix.database_image }}

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: recursive

- name: Update submodules
run: git submodule update --init --remote

- name: Run tests
run: make ci
Expand All @@ -43,7 +57,8 @@ jobs:
if: matrix.coverage == true

- name: Upload code coverage
uses: codecov/codecov-action@v2
uses: codecov/codecov-action@v4
with:
files: coverage/php/coverage.xml,coverage/js/clover.xml
token: ${{ secrets.CODECOV_TOKEN }}
files: coverage/php/coverage.xml
if: matrix.coverage == true
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "build"]
path = build
url = https://github.com/gesinn-it-pub/docker-compose-ci.git
13 changes: 13 additions & 0 deletions .phpcs.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0"?>
<ruleset>
<rule ref="./vendor/mediawiki/mediawiki-codesniffer/MediaWiki">
<exclude name="MediaWiki.NamingConventions.ValidGlobalName.allowedPrefix" />
<exclude name="MediaWiki.Commenting.MissingCovers.MissingCovers" />
<exclude name="MediaWiki.Commenting.FunctionComment.MissingDocumentationPrivate" />
<exclude name="MediaWiki.Commenting.FunctionComment.MissingDocumentationPublic" />
</rule>
<file>.</file>
<arg name="bootstrap" value="./vendor/mediawiki/mediawiki-codesniffer/utils/bootstrap-ci.php"/>
<arg name="extensions" value="php"/>
<arg name="encoding" value="UTF-8"/>
</ruleset>
67 changes: 23 additions & 44 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,52 +1,31 @@
EXTENSION := ConfIDentSkin

MW_VERSION ?= 1.35
CHAMELEON_VERSION ?= 4.1.0

EXTENSION_FOLDER := /var/www/html/extensions/${EXTENSION}
COVERAGE_FOLDER := ${EXTENSION_FOLDER}/coverage
PWD := $(shell bash -c "pwd -W 2>/dev/null || pwd")# this way it works on Windows and Linux
IMAGE_NAME := confident-skin:test-${MW_VERSION}-${CHAMELEON_VERSION}
DOCKER_RUN := docker run --rm -v ${PWD}/coverage:${COVERAGE_FOLDER} ${IMAGE_NAME}
PHPUNIT := ${DOCKER_RUN} php tests/phpunit/phpunit.php --testdox -c ${EXTENSION_FOLDER}
NPM := docker run --rm -v ${PWD}/coverage:${COVERAGE_FOLDER} -w ${EXTENSION_FOLDER} ${IMAGE_NAME} npm
-include .env-39
export

.PHONY: all
all:
# setup for docker-compose-ci build directory
# delete "build" directory to update docker-compose-ci

.PHONY: ci
ci: build test
ifeq (,$(wildcard ./build/))
$(shell git submodule update --init --remote)
endif

.PHONY: ci-coverage
ci-coverage: build test-coverage

.PHONY: build
build:
docker build --tag ${IMAGE_NAME} \
--build-arg=MW_VERSION=${MW_VERSION} \
--build-arg=CHAMELEON_VERSION=${CHAMELEON_VERSION} \
.

.PHONY: test
test: phpunit npm-test
EXTENSION := ConfIDentSkin

.PHONY: test-coverage
test-coverage: phpunit-coverage npm-test-coverage
# docker images
MW_VERSION?=1.35
PHP_VERSION?=7.4
DB_TYPE?=sqlite
DB_IMAGE?=""

.PHONY: phpunit
phpunit:
${PHPUNIT} ${EXTENSION_FOLDER}/tests/phpunit
# extensions
CHAMELEON_VERSION?=4.2.1

.PHONY:
phpunit-coverage:
${PHPUNIT} ${EXTENSION_FOLDER}/tests/phpunit \
--coverage-html ${COVERAGE_FOLDER}/php \
--coverage-clover ${COVERAGE_FOLDER}/php/coverage.xml
# composer
# Enables "composer update" inside of extension
COMPOSER_EXT?=true

.PHONY: npm-test
npm-test:
${NPM} run test
# nodejs
# Enables node.js related tests and "npm install"
NODE_JS?=true

.PHONY: npm-test-coverage
npm-test-coverage:
${NPM} run test-coverage
# check for build dir and git submodule init if it does not exist
include build/Makefile
1 change: 1 addition & 0 deletions build
Submodule build added at d54a8c
19 changes: 19 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"require-dev": {
"mediawiki/mediawiki-codesniffer": "^39.0",
"phpstan/phpstan": "^1.7",
"vimeo/psalm": "^4.23"
},
"scripts": {
"fix": [ "@phpcs-fix" ],
"test": [ "@analyze", "@phpunit" ],
"test-coverage": [ "@analyze", "@phpunit-coverage" ],
"analyze": ["@phpcs", "@phpstan"],
"phpcs": "phpcs -p -s src tests/phpunit",
"phpcs-fix": "phpcbf src tests/phpunit",
"psalm": "psalm --config=psalm.xml",
"psalm-baseline": "psalm --config=psalm.xml --set-baseline=psalm-baseline.xml",
"phpunit": "php ../../tests/phpunit/phpunit.php -c phpunit.xml.dist --testdox",
"phpunit-coverage": "php ../../tests/phpunit/phpunit.php -c phpunit.xml.dist --testdox --coverage-text --coverage-html coverage/php --coverage-clover coverage/php/coverage.xml"
}
}
3 changes: 0 additions & 3 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@
<testsuite name="confident-skin-unit">
<directory>tests/phpunit/Unit</directory>
</testsuite>
<testsuite name="confident-skin-integration">
<directory>tests/phpunit/Integration</directory>
</testsuite>
</testsuites>
<filter>
<whitelist addUncoveredFilesFromWhitelist="true">
Expand Down
4 changes: 2 additions & 2 deletions src/Components/ConfidentVersions.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ public function getHtml(): string {

return $this->indent() . '<!-- versions -->' . $this->indent() .
'<div id="confident-versions" class="' . $this->getClassString() . '" >' .
$this->indent(1) .
$this->indent( 1 ) .
'<span class="openresearch-stack-version">OpenResearchStack: ' .
$wgOpenResearchStackVersion . '</span>' . $this->indent() .
'<span class="confident-version">Confident: ' .
$wgConfidentVersion . '</span>' . $this->indent(-1) .
$wgConfidentVersion . '</span>' . $this->indent( -1 ) .
'</div>';
}
}
4 changes: 2 additions & 2 deletions src/Components/MainContentWithSideBar.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ class MainContentWithSideBar extends Component {
*/
public function getHtml(): string {
$mainContent = new MainContent(
$this->getSkinTemplate(), $this->getDomElement(), $this->getIndent());
return SideBarDecorator::for($mainContent)->getHtml();
$this->getSkinTemplate(), $this->getDomElement(), $this->getIndent() );
return SideBarDecorator::for( $mainContent )->getHtml();
}

}
47 changes: 26 additions & 21 deletions src/Components/SideBarDecorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,57 +3,62 @@
namespace Skins\Chameleon\Components;

use ConfIDentSkin\DomHelpers;
use Skins\Chameleon\ChameleonTemplate;

class SideBarDecorator extends Component {

public static function for(Component $component) {
return new self($component);
public static function for( Component $component ) {
return new self( $component );
}

/**
* The component being decorated.
*
* @var Component
*/
private Component $decoratee;

public function __construct(Component $decoratee) {
public function __construct( Component $decoratee ) {
$this->decoratee = $decoratee;
parent::__construct($decoratee->getSkinTemplate(), $decoratee->getDomElement(),
$decoratee->getIndent());
parent::__construct( $decoratee->getSkinTemplate(), $decoratee->getDomElement(),
$decoratee->getIndent() );
}

/**
* @inheritDoc
* @throws \MWException
*/
public function getHtml(): string {
[$decorateeHtml, $sidebarHtml] =
[ $decorateeHtml, $sidebarHtml ] =
self::createSidebar( $this->decoratee->getHtml() );

return $this->indent() .
'<div class="row">' . $this->indent(1) .
($sidebarHtml != '' ?
'<aside id="sidebar" class="col-12 col-lg-4 order-lg-2">' . $this->indent(1) .
$sidebarHtml . $this->indent(-1) .
'<div class="row">' . $this->indent( 1 ) .
( $sidebarHtml != '' ?
'<aside id="sidebar" class="col-12 col-lg-4 order-lg-2">' . $this->indent( 1 ) .
$sidebarHtml . $this->indent( -1 ) .
'</aside>' :
''
) . $this->indent() .
'<div class="col">'. $this->indent(1) .
$decorateeHtml . $this->indent(-1) .
'</div>' . $this->indent(-1) .
'<div class="col">' . $this->indent( 1 ) .
$decorateeHtml . $this->indent( -1 ) .
'</div>' . $this->indent( -1 ) .
'</div>';
}

private static function createSidebar( $mainHtml ) {
$sidebarHtml = '';
if (str_contains($mainHtml, 'sidebarItem')) {
[$mainHtml, $sidebarHtml] =
DomHelpers::cutElements($mainHtml, fn($n) => self::isSidebarElement($n));
if ( str_contains( $mainHtml, 'sidebarItem' ) ) {
[ $mainHtml, $sidebarHtml ] =
DomHelpers::cutElements( $mainHtml, fn( $n ) => self::isSidebarElement( $n ) );
}
return [$mainHtml, $sidebarHtml];
return [ $mainHtml, $sidebarHtml ];
}

private static function isSidebarElement( $node ) {
if (!$node->hasAttributes())
if ( !$node->hasAttributes() ) {
return false;
$classes = explode(' ', $node->getAttribute('class'));
return in_array('sidebarItem', $classes);
}
$classes = explode( ' ', $node->getAttribute( 'class' ) );
return in_array( 'sidebarItem', $classes );
}
}
11 changes: 6 additions & 5 deletions src/DomHelpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,29 @@ public static function cutElements( string $source, callable $predicate
$sourceNode = self::load( $source );
$targetNode = self::load();

$toCut = iterator_to_array(self::filter( $sourceNode, $predicate ), false);
$toCut = iterator_to_array( self::filter( $sourceNode, $predicate ), false );
foreach ( $toCut as $cut ) {
$cut->parentNode->removeChild($cut);
$cut->parentNode->removeChild( $cut );
self::append( $cut, $targetNode );
}

return [self::save( $sourceNode ), self::save( $targetNode )];
return [ self::save( $sourceNode ), self::save( $targetNode ) ];
}

private static function filter( DOMNode $n, $predicate ): \Generator {
if ( $predicate( $n ) ) {
yield $n;
} else {
foreach ( $n->childNodes as $c )
foreach ( $n->childNodes as $c ) {
yield from self::filter( $c, $predicate );
}
}
}

private static function load( string $source = null ): DOMNode {
$source ??= '<body>';
$doc = new DOMDocument();
$doc->loadHTML('<?xml encoding="utf-8"?>' . $source, LIBXML_NOERROR);
$doc->loadHTML( '<?xml encoding="utf-8"?>' . $source, LIBXML_NOERROR );
return $doc->getElementsByTagName( 'body' )->item( 0 );
}

Expand Down
10 changes: 7 additions & 3 deletions src/Hooks.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,26 @@

namespace ConfIDentSkin;

use MediaWiki\Hook\BeforeInitializeHook;
use MediaWiki\Hook\BeforePageDisplayHook;
use MediaWiki\Hook\MediaWikiServicesHook;
use MediaWiki\MediaWikiServices;

class Hooks implements MediaWikiServicesHook, BeforePageDisplayHook {

/**
* List of SCSS files used by the extension or skin.
*
* @var string[] List of SCSS file identifiers.
*/
private $scssFiles = [
'extension-PageForms',
'skin-ContentHeader',
'skin-enableShowAllFieldsToggle',
];

public function __construct( $scssFiles = null ) {
if ($scssFiles !== null)
if ( $scssFiles !== null ) {
$this->scssFiles = $scssFiles;
}
}

/**
Expand Down
18 changes: 16 additions & 2 deletions tests/node-qunit/setup.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
const fs = require('fs');
const path = require('path');
const resetDom = createDom();
prepareMediaWiki();
const sinon = require('sinon');

// Define paths for both versions
const oojsJqueryPath = path.resolve(__dirname, '../../../../resources/lib/oojs/oojs.jquery.js');
const oojsPath = path.resolve(__dirname, '../../../../resources/lib/oojs/oojs.js');

QUnit.hooks.beforeEach(assert => {
sinon.assert.pass = message =>
assert.pushResult({ result: true, expected: true, actual: true, message });
sinon.assert.fail = message =>
assert.pushResult({ result: false, expected: true, actual: false, message });
});

prepareMediaWiki();

QUnit.hooks.afterEach(() => {
resetDom();
sinon.restore();
Expand Down Expand Up @@ -41,7 +48,14 @@ function createDom() {
* setup MediaWiki globals: OO, mw, ...
*/
function prepareMediaWiki() {
global.OO = require('../../../../resources/lib/oojs/oojs.jquery.js');
// Check if oojs.js exists (for MW 1.39+), otherwise use oojs.jquery.js (for MW 1.35)
if (fs.existsSync(oojsPath)) {
global.OO = require(oojsPath);
} else if (fs.existsSync(oojsJqueryPath)) {
global.OO = require(oojsJqueryPath);
} else {
throw new Error('Neither oojs.js nor oojs.jquery.js could be found.');
}
require('../../../../resources/lib/ooui/oojs-ui-core.js');
require('../../../../resources/lib/ooui/oojs-ui-widgets.js');
require('../../../../resources/lib/ooui/oojs-ui-wikimediaui');
Expand Down
Loading