Compare commits

..

4 Commits

Author SHA1 Message Date
Dan Brown
2e2f59fa0f CI: Updated images to debian trixie 2026-04-27 13:36:47 +01:00
Dan Brown
cc6e9e0546 CI: Attempt a more robust avif support check 2026-04-27 13:17:58 +01:00
Dan Brown
0f59981932 CI: Updated tests using DB to set test DB URL 2026-04-27 12:52:05 +01:00
Dan Brown
a37f903dc7 CI: Migrated workflows to forgejo 2026-04-27 12:10:44 +01:00
9 changed files with 88 additions and 104 deletions

4
.forgejo/FUNDING.yml Normal file
View File

@@ -0,0 +1,4 @@
# These are supported funding model platforms
github: [ssddanbrown]
ko_fi: ssddanbrown

View File

@@ -1,6 +1,7 @@
name: analyse-php
on:
workflow_dispatch:
push:
paths:
- '**.php'
@@ -11,14 +12,16 @@ on:
jobs:
build:
if: ${{ github.ref != 'refs/heads/l10n_development' }}
runs-on: ubuntu-24.04
runs-on: docker
container:
image: docker.io/library/node:24-trixie
steps:
- uses: actions/checkout@v4
- uses: https://code.forgejo.org/actions/checkout@v6
- name: Setup PHP
uses: shivammathur/setup-php@v2
uses: https://github.com/shivammathur/setup-php@v2
with:
php-version: 8.3
php-version: 8.5
extensions: gd, mbstring, json, curl, xml, mysql, ldap
- name: Get Composer Cache Directory
@@ -27,14 +30,16 @@ jobs:
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache composer packages
uses: actions/cache@v4
uses: https://code.forgejo.org/actions/cache@v5
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-8.3
key: ${{ runner.os }}-composer-8.5
restore-keys: ${{ runner.os }}-composer-
- name: Install composer dependencies
run: composer install --prefer-dist --no-interaction --ansi
env:
COMPOSER_AUTH: '{"github-oauth": {"github.com": "${{ secrets.GH_TOKEN }}"}}'
- name: Run static analysis check
run: composer check-static

View File

@@ -1,6 +1,7 @@
name: lint-js
on:
workflow_dispatch:
push:
paths:
- '**.js'
@@ -13,9 +14,11 @@ on:
jobs:
build:
if: ${{ github.ref != 'refs/heads/l10n_development' }}
runs-on: ubuntu-24.04
runs-on: docker
container:
image: docker.io/library/node:24-trixie
steps:
- uses: actions/checkout@v4
- uses: https://code.forgejo.org/actions/checkout@v6
- name: Install NPM deps
run: npm ci

View File

@@ -1,6 +1,7 @@
name: lint-php
on:
workflow_dispatch:
push:
paths:
- '**.php'
@@ -11,14 +12,16 @@ on:
jobs:
build:
if: ${{ github.ref != 'refs/heads/l10n_development' }}
runs-on: ubuntu-24.04
runs-on: docker
container:
image: docker.io/library/node:24-trixie
steps:
- uses: actions/checkout@v4
- uses: https://code.forgejo.org/actions/checkout@v6
- name: Setup PHP
uses: shivammathur/setup-php@v2
uses: https://github.com/shivammathur/setup-php@v2
with:
php-version: 8.3
php-version: 8.5
tools: phpcs
- name: Run formatting check

View File

@@ -1,6 +1,7 @@
name: test-js
on:
workflow_dispatch:
push:
paths:
- '**.js'
@@ -15,9 +16,11 @@ on:
jobs:
build:
if: ${{ github.ref != 'refs/heads/l10n_development' }}
runs-on: ubuntu-24.04
runs-on: docker
container:
image: docker.io/library/node:24-trixie
steps:
- uses: actions/checkout@v6
- uses: https://code.forgejo.org/actions/checkout@v6
- name: Install NPM deps
run: npm ci

View File

@@ -1,6 +1,7 @@
name: test-migrations
on:
workflow_dispatch:
push:
paths:
- '**.php'
@@ -13,15 +14,25 @@ on:
jobs:
build:
if: ${{ github.ref != 'refs/heads/l10n_development' }}
runs-on: ubuntu-24.04
runs-on: docker
container:
image: docker.io/library/node:24-trixie
strategy:
matrix:
php: ['8.2', '8.3', '8.4', '8.5']
services:
mysql:
image: docker.io/library/mariadb:12.2.2-noble
env:
MARIADB_USER: bookstack-test
MARIADB_PASSWORD: bookstack-test
MARIADB_DATABASE: bookstack-test
MARIADB_ROOT_PASSWORD: password
steps:
- uses: actions/checkout@v4
- uses: https://code.forgejo.org/actions/checkout@v6
- name: Setup PHP
uses: shivammathur/setup-php@v2
uses: https://github.com/shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: gd, mbstring, json, curl, xml, mysql, ldap
@@ -32,34 +43,31 @@ jobs:
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache composer packages
uses: actions/cache@v4
uses: https://code.forgejo.org/actions/cache@v5
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ matrix.php }}
restore-keys: ${{ runner.os }}-composer-
- name: Start MySQL
run: |
sudo systemctl start mysql
- name: Create database & user
run: |
mysql -uroot -proot -e 'CREATE DATABASE IF NOT EXISTS `bookstack-test`;'
mysql -uroot -proot -e "CREATE USER 'bookstack-test'@'localhost' IDENTIFIED WITH mysql_native_password BY 'bookstack-test';"
mysql -uroot -proot -e "GRANT ALL ON \`bookstack-test\`.* TO 'bookstack-test'@'localhost';"
mysql -uroot -proot -e 'FLUSH PRIVILEGES;'
- name: Install composer dependencies
run: composer install --prefer-dist --no-interaction --ansi
env:
COMPOSER_AUTH: '{"github-oauth": {"github.com": "${{ secrets.GH_TOKEN }}"}}'
- name: Start migration test
env:
TEST_DATABASE_URL: 'mysql://bookstack-test:bookstack-test@mysql/bookstack-test'
run: |
php${{ matrix.php }} artisan migrate --force -n --database=mysql_testing
- name: Start migration:rollback test
env:
TEST_DATABASE_URL: 'mysql://bookstack-test:bookstack-test@mysql/bookstack-test'
run: |
php${{ matrix.php }} artisan migrate:rollback --force -n --database=mysql_testing
- name: Start migration rerun test
env:
TEST_DATABASE_URL: 'mysql://bookstack-test:bookstack-test@mysql/bookstack-test'
run: |
php${{ matrix.php }} artisan migrate --force -n --database=mysql_testing

View File

@@ -1,6 +1,7 @@
name: test-php
on:
workflow_dispatch:
push:
paths:
- '**.php'
@@ -13,15 +14,25 @@ on:
jobs:
build:
if: ${{ github.ref != 'refs/heads/l10n_development' }}
runs-on: ubuntu-24.04
runs-on: docker
container:
image: docker.io/library/node:24-trixie
strategy:
matrix:
php: ['8.2', '8.3', '8.4', '8.5']
services:
mysql:
image: docker.io/library/mariadb:12.2.2-noble
env:
MARIADB_USER: bookstack-test
MARIADB_PASSWORD: bookstack-test
MARIADB_DATABASE: bookstack-test
MARIADB_ROOT_PASSWORD: password
steps:
- uses: actions/checkout@v4
- uses: https://code.forgejo.org/actions/checkout@v6
- name: Setup PHP
uses: shivammathur/setup-php@v2
uses: https://github.com/shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: gd, mbstring, json, curl, xml, mysql, ldap, gmp
@@ -32,30 +43,25 @@ jobs:
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache composer packages
uses: actions/cache@v4
uses: https://code.forgejo.org/actions/cache@v5
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ matrix.php }}
restore-keys: ${{ runner.os }}-composer-
- name: Start Database
run: |
sudo systemctl start mysql
- name: Setup Database
run: |
mysql -uroot -proot -e 'CREATE DATABASE IF NOT EXISTS `bookstack-test`;'
mysql -uroot -proot -e "CREATE USER 'bookstack-test'@'localhost' IDENTIFIED WITH mysql_native_password BY 'bookstack-test';"
mysql -uroot -proot -e "GRANT ALL ON \`bookstack-test\`.* TO 'bookstack-test'@'localhost';"
mysql -uroot -proot -e 'FLUSH PRIVILEGES;'
- name: Install composer dependencies
run: composer install --prefer-dist --no-interaction --ansi
env:
COMPOSER_AUTH: '{"github-oauth": {"github.com": "${{ secrets.GH_TOKEN }}"}}'
- name: Migrate and seed the database
env:
TEST_DATABASE_URL: 'mysql://bookstack-test:bookstack-test@mysql/bookstack-test'
run: |
php${{ matrix.php }} artisan migrate --force -n --database=mysql_testing
php${{ matrix.php }} artisan db:seed --force -n --class=DummyContentSeeder --database=mysql_testing
- name: Run PHP tests
env:
TEST_DATABASE_URL: 'mysql://bookstack-test:bookstack-test@mysql/bookstack-test'
run: php${{ matrix.php }} ./vendor/bin/phpunit

View File

@@ -94,78 +94,30 @@ const extendedActionsByKeys: Record<string, ShortcutAction> = {
};
function createKeyDownListener(context: EditorUiContext, useExtended: boolean): (e: KeyboardEvent) => void {
const baseKeySetToUse = useExtended ? extendedActionsByKeys : baseActionsByKeys;
const keySetToUse = extendKeySetWithKeyCodes(baseKeySetToUse);
const keySetToUse = useExtended ? extendedActionsByKeys : baseActionsByKeys;
return (event: KeyboardEvent) => {
const comboStrings = keyboardEventToKeyComboStrings(event);
// console.log(comboStrings, event, keySetToUse);
for (const combo of comboStrings) {
if (keySetToUse[combo]) {
const handled = keySetToUse[combo](context.editor, context);
if (handled) {
event.stopPropagation();
event.preventDefault();
}
break;
const combo = keyboardEventToKeyComboString(event);
// console.log(`pressed: ${combo}`);
if (keySetToUse[combo]) {
const handled = keySetToUse[combo](context.editor, context);
if (handled) {
event.stopPropagation();
event.preventDefault();
}
}
};
}
/**
* Takes a shortcut key set and returns a new set with added variations of shortcts where
* they can be sensibly represented as their key code instead of just key, which we can use
* for matching in scenarios where the physical key may be represented of the letter used
* in the shortcut, but produces a different 'key' value.
* Useful for Cyrillic scenarios where the keyboard key would show a latin character
* as an option, and therefore be expected for use for the relevant latin shortcut, but the main
* key output is a Cyrillic character.
*/
function extendKeySetWithKeyCodes(keySet: Record<string, ShortcutAction>): Record<string, ShortcutAction> {
const newKeys: Record<string, ShortcutAction> = {};
const setKeys = Object.keys(keySet);
for (const keyCombo of setKeys) {
const action = keySet[keyCombo];
newKeys[keyCombo] = action;
const comboParts = keyCombo.split('+');
const lastComboPart = comboParts.pop() || '';
if (lastComboPart.match(/^[a-zA-Z]$/)) {
const keyCode = lastComboPart.toUpperCase().charCodeAt(0);
comboParts.push(String(keyCode));
const newCombo = comboParts.join('+');
newKeys[newCombo] = action;
}
}
return newKeys;
}
function keyboardEventToKeyComboStrings(event: KeyboardEvent): string[] {
function keyboardEventToKeyComboString(event: KeyboardEvent): string {
const metaKeyPressed = isMac() ? event.metaKey : event.ctrlKey;
const mainParts = [
const parts = [
metaKeyPressed ? 'meta' : '',
event.shiftKey ? 'shift' : '',
event.key,
];
const toReturn = [
mainParts.filter(Boolean).join('+').toLowerCase(),
];
// If ending with a standard latin character, provide an alternative
// keyCode based option for scenarios of dual-language keyboard use.
const keyCode = event.keyCode || 0;
if (keyCode >= 65 && keyCode <= 90) {
const keyCodeParts = [...mainParts];
keyCodeParts.pop();
keyCodeParts.push(String(keyCode));
toReturn.push(keyCodeParts.filter(Boolean).join('+').toLowerCase());
}
return toReturn;
return parts.filter(Boolean).join('+').toLowerCase();
}
function isMac(): boolean {

View File

@@ -75,7 +75,7 @@ class ImageTest extends TestCase
public function test_image_display_thumbnail_generation_for_animated_avif_images_uses_original_file()
{
if (! function_exists('imageavif')) {
if ((gd_info()['AVIF Support'] ?? false) !== true) {
$this->markTestSkipped('imageavif() is not available');
}