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
162 changes: 106 additions & 56 deletions .github/workflows/REUSABLE_backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,37 @@ on:
default: 'curl, dom, gd, json, mbstring, openssl, pdo_mysql, tokenizer, zip'

db_versions:
description: Versions of databases to test with. Should be array of strings encoded as JSON array
description: >-
Versions of databases to test with. Should be array of strings encoded as JSON array.
Each entry runs on `latest_php`; older PHP versions are covered separately against a
single reference database. Images are pinned so a run is reproducible. The default
covers, per driver, the version Flarum declares as its minimum, the version it
recommends, and the newest long-term release — see Flarum\Database\DatabaseRequirements.
type: string
required: false
default: >-
["mysql:5.7", "mysql:8.4", "mysql:9.7",
"mariadb:10.3", "mariadb:11.8", "mariadb:12.3",
"postgres:10", "postgres:15", "postgres:18",
"sqlite:3"]

db_prefix:
description: >-
Table prefix for the prefixed jobs on drivers that allow 64-character identifiers,
at the longest Flarum accepts there (DatabaseRequirements::maxTablePrefixLength).
These jobs cover both identifier length limits and the prefix handling in each
driver's schema code, so there is one per driver, each at that driver's maximum.
type: string
required: false
default: 'flarum_c_'

db_prefix_pgsql:
description: >-
As `db_prefix`, but one byte shorter: PostgreSQL limits identifiers to 63 bytes
rather than 64 characters.
type: string
required: false
default: '["mysql:5.7", "mysql:8.0.30", "mariadb", "sqlite:3", "postgres:10"]'
default: 'flarum_p'

php_ini_values:
description: PHP ini values
Expand Down Expand Up @@ -113,87 +140,95 @@ jobs:
runs-on: ${{ inputs.runner_type }}

strategy:
# One database failing should not hide the state of the others.
fail-fast: false

matrix:
php: ${{ fromJSON(inputs.php_versions) }}
# Every database in `db_versions` runs on the latest PHP. Older PHP versions are
# added below against one reference database: a PHP-version bug is not specific to
# a database engine, so a full cross-product buys coverage that cannot fail alone.
php: ['${{ inputs.latest_php }}']
service: ${{ fromJSON(inputs.db_versions) }}
prefix: ['']
php_ini_values: [inputs.php_ini_values]

# Redis client library to exercise. Defaults to a single empty entry
# (no extra dimension); repos that enable_redis can opt into testing
# both 'phpredis' and 'predis' via the `redis_clients` input.
redis_client: ${{ fromJSON(inputs.redis_clients) }}

# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrixinclude
include:
# Expands the matrix by naming DBs.
# Human-readable names and the driver each image speaks. These match on `service`,
# so they annotate the combinations above rather than adding any.
- service: 'mysql:5.7'
db: MySQL 5.7
driver: mysql
- service: 'mysql:8.0.30'
db: MySQL 8.0
- service: 'mysql:8.4'
db: MySQL 8.4
driver: mysql
- service: 'mysql:9.7'
db: MySQL 9.7
driver: mysql
- service: mariadb
db: MariaDB
- service: 'mariadb:10.3'
db: MariaDB 10.3
driver: mariadb
- service: 'mariadb:11.8'
db: MariaDB 11.8
driver: mariadb
- service: 'mariadb:12.3'
db: MariaDB 12.3
driver: mariadb
- service: 'sqlite:3'
db: SQLite
driver: sqlite
- service: 'postgres:10'
db: PostgreSQL 10
driver: pgsql
- service: 'postgres:15'
db: PostgreSQL 15
driver: pgsql
- service: 'postgres:18'
db: PostgreSQL 18
driver: pgsql
- service: 'sqlite:3'
db: SQLite
driver: sqlite

# PHP coverage, against the recommended MySQL rather than the newest, since that
# is the version most installations are expected to be on.
- php: ${{ fromJSON(inputs.php_versions)[0] }}
service: 'mysql:8.4'
db: MySQL 8.4
driver: mysql
- php: ${{ fromJSON(inputs.php_versions)[1] }}
service: 'mysql:8.4'
db: MySQL 8.4
driver: mysql

# Include Database prefix tests with only one PHP version (latest).
# One prefixed run per driver. Identifier limits differ (64 characters on
# MySQL/MariaDB, 63 bytes on PostgreSQL, which truncates silently), and each
# driver applies the prefix through its own schema code.
- php: ${{ inputs.latest_php }}
service: 'mysql:5.7'
db: MySQL 5.7
service: 'mysql:9.7'
db: MySQL 9.7
driver: mysql
prefix: flarum_
prefix: ${{ inputs.db_prefix }}
prefixStr: (prefix)
- php: ${{ inputs.latest_php }}
service: mariadb
db: MariaDB
service: 'mariadb:12.3'
db: MariaDB 12.3
driver: mariadb
prefix: flarum_
prefix: ${{ inputs.db_prefix }}
prefixStr: (prefix)
- php: ${{ inputs.latest_php }}
service: 'postgres:18'
db: PostgreSQL 18
driver: pgsql
prefix: ${{ inputs.db_prefix_pgsql }}
prefixStr: (prefix)
- php: ${{ inputs.latest_php }}
service: 'sqlite:3'
db: SQLite
driver: sqlite
prefix: flarum_
prefixStr: (prefix)
- php: ${{ inputs.latest_php }}
service: 'postgres:10'
db: PostgreSQL 10
driver: pgsql
prefix: flarum_
prefix: ${{ inputs.db_prefix }}
prefixStr: (prefix)

# To reduce number of actions:
# - MySQL 8.0 runs on all PHP versions (primary DB for PHP version coverage)
# - All other DBs run on latest PHP only (DB-specific bugs don't depend on PHP version)
# - MySQL 5.7 also runs on latest PHP only (floor version coverage)
#
# This excludes every non-latest PHP version for those DBs, leaving only
# `latest_php`. The list must cover all `php_versions` entries EXCEPT the
# last one, so keep it in sync when `php_versions` changes size.
exclude:
- php: ${{ fromJSON(inputs.php_versions)[0] }}
service: 'mysql:5.7'
- php: ${{ fromJSON(inputs.php_versions)[1] }}
service: 'mysql:5.7'
- php: ${{ fromJSON(inputs.php_versions)[0] }}
service: mariadb
- php: ${{ fromJSON(inputs.php_versions)[1] }}
service: mariadb
- php: ${{ fromJSON(inputs.php_versions)[0] }}
service: 'sqlite:3'
- php: ${{ fromJSON(inputs.php_versions)[1] }}
service: 'sqlite:3'
- php: ${{ fromJSON(inputs.php_versions)[0] }}
service: 'postgres:10'
- php: ${{ fromJSON(inputs.php_versions)[1] }}
service: 'postgres:10'

services:
mysql:
image: ${{ matrix.driver == 'mysql' && matrix.service || '' }}
Expand All @@ -214,7 +249,7 @@ jobs:
MARIADB_ROOT_PASSWORD: root
ports:
- 3306
options: --health-cmd="healthcheck.sh --connect --innodb_initialized" --health-interval=10s --health-timeout=5s --health-retries=3
options: --health-cmd="healthcheck.sh --connect" --health-interval=10s --health-timeout=5s --health-retries=10
postgres:
image: ${{ matrix.driver == 'pgsql' && matrix.service || '' }}
env:
Expand Down Expand Up @@ -263,7 +298,22 @@ jobs:
# both code paths.
extensions: ${{ inputs.php_extensions }}${{ matrix.redis_client == 'phpredis' && ', redis' || '' }}
tools: phpunit, composer:v2
ini-values: ${{ matrix.php_ini_values }}
ini-values: ${{ inputs.php_ini_values }}

# SQLite is compiled into PHP rather than run as a service, so its version comes from
# the runner image and cannot be pinned like the other drivers. Record it, and fail if
# a runner update ever drops below the version Flarum declares as its minimum.
- name: Report SQLite version
if: matrix.driver == 'sqlite'
run: |
php -r '
$v = SQLite3::version()["versionString"];
echo "SQLite $v\n";
if (version_compare($v, "3.35.0", "<")) {
echo "::error::Runner SQLite $v is below Flarum SQLITE_MINIMUM 3.35.0\n";
exit(1);
}
'

- name: Install Composer dependencies
run: composer install
Expand Down Expand Up @@ -347,7 +397,7 @@ jobs:
coverage: none
extensions: ${{ inputs.php_extensions }}
tools: phpunit, composer:v2
ini-values: ${{ matrix.php_ini_values }}
ini-values: ${{ inputs.php_ini_values }}

- name: Install Composer dependencies
run: composer install
Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ name: Backend Tests

on: [workflow_dispatch, push, pull_request]

# Superseded runs keep occupying slots against the account-wide concurrent job limit, so
# cancel them when a branch is pushed again. Runs on the default branch are left alone,
# since each merge commit's result is worth having on its own.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/2.x' }}

jobs:
run:
uses: ./.github/workflows/REUSABLE_backend.yml
Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/frontend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ name: Frontend Workflow

on: [workflow_dispatch, push, pull_request]

# Superseded runs keep occupying slots against the account-wide concurrent job limit, so
# cancel them when a branch is pushed again. Runs on the default branch are left alone,
# since each merge commit's result is worth having on its own.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/2.x' }}

jobs:
run:
uses: ./.github/workflows/REUSABLE_frontend.yml
Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/phpstan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ name: Static Code Analysis

on: [workflow_dispatch, push, pull_request]

# Superseded runs keep occupying slots against the account-wide concurrent job limit, so
# cancel them when a branch is pushed again. Runs on the default branch are left alone,
# since each merge commit's result is worth having on its own.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/2.x' }}

jobs:
run:
uses: ./.github/workflows/REUSABLE_backend.yml
Expand Down
Loading