A WordPress plugin that claims to support PHP 8.1–8.4 and WordPress 6.4–7.0 has a 4×4 compatibility matrix — 16 combinations to test. GitHub Actions matrix builds run all 16 in parallel without duplicating workflow YAML, catching the one PHP 8.4 + WordPress 6.4 regression before it reaches users. Reusable workflows take this further: define the test job once in a central repository and call it from every plugin repository, keeping CI configuration consistent across a team’s entire plugin portfolio.
The workflows below set up a PHP/WordPress matrix build using the shivammathur/setup-php action, define a reusable workflow for WordPress plugin testing, and call it from a plugin repository with per-repo overrides.
# .github/workflows/tests.yml — Matrix build for PHP × WordPress versions
name: Plugin Tests
on:
push:
branches: [ main, develop ]
pull_request:
jobs:
test:
name: PHP ${{ matrix.php }} / WP ${{ matrix.wp }}
runs-on: ubuntu-latest
strategy:
fail-fast: false # run all combinations even if one fails
matrix:
php: [ '8.1', '8.2', '8.3', '8.4' ]
wp: [ '6.4', '6.5', '6.6', '7.0' ]
exclude:
# WP 7.0 requires PHP >= 8.1 (already satisfied here, but example syntax)
- php: '8.0'
wp: '7.0'
include:
# Extra: test with MySQL 9.1
- php: '8.3'
wp: '7.0'
mysql: '9.1'
services:
mysql:
image: mysql:${{ matrix.mysql || '8.0' }}
env:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: wordpress_test
ports: [ '3306:3306' ]
options: --health-cmd="mysqladmin ping" --health-interval=10s
steps:
- uses: actions/checkout@v4
- name: Setup PHP ${{ matrix.php }}
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: mysqli, zip, gd
coverage: xdebug
tools: composer, wp-cli
- name: Install WordPress test suite
run: bash bin/install-wp-tests.sh wordpress_test root root 127.0.0.1 ${{ matrix.wp }}
- name: Install Composer dependencies
run: composer install --prefer-dist --no-progress
- name: Run PHPUnit
run: vendor/bin/phpunit --coverage-clover coverage.xml
- name: Upload coverage (main PHP+WP only)
if: matrix.php == '8.3' && matrix.wp == '7.0'
uses: codecov/codecov-action@v4
with:
files: coverage.xml
# org/.github/workflows/wp-plugin-tests.yml — REUSABLE workflow
name: WordPress Plugin Tests (Reusable)
on:
workflow_call:
inputs:
php-versions:
description: 'JSON array of PHP versions'
type: string
default: '["8.2","8.3"]'
wp-versions:
description: 'JSON array of WP versions'
type: string
default: '["6.6","7.0"]'
jobs:
test:
strategy:
matrix:
php: ${{ fromJson( inputs.php-versions ) }}
wp: ${{ fromJson( inputs.wp-versions ) }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
- run: bash bin/install-wp-tests.sh wordpress_test root root 127.0.0.1 ${{ matrix.wp }}
- run: composer install --prefer-dist --no-progress
- run: vendor/bin/phpunit
---
# my-plugin/.github/workflows/ci.yml — CALLER workflow
name: CI
on: [push, pull_request]
jobs:
tests:
uses: my-org/.github/.github/workflows/wp-plugin-tests.yml@main
with:
php-versions: '["8.3","8.4"]'
wp-versions: '["6.6","7.0"]'
NOTE: Matrix builds multiply your CI minute usage — a 4×4 matrix of 5-minute jobs consumes 80 CI minutes per push; on GitHub Free (2000 min/month), a busy plugin with multiple daily pushes will exhaust the free allowance quickly; use fail-fast: false only when you need to see all failures at once, and use path filters (on.push.paths) to skip the matrix for documentation-only changes — these two adjustments typically cut CI usage by 40–60%.