Created
April 6, 2026 11:35
-
-
Save DaveLiddament/922dd45cd10b14b6b614e96bee7380af to your computer and use it in GitHub Desktop.
Prompt: Update project to run in all PHP active versions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| I want this project to support PHP 8.3, 8.4, and 8.5 with a CI matrix. Right | |
| now it probably only supports one version. Here's the plan: | |
| ## Goals | |
| - Support PHP 8.3, 8.4, and 8.5 | |
| - Local Docker services for each version | |
| - GitHub Actions matrix that runs CI against all three | |
| - Infection (mutation testing) runs only on 8.5 in a dedicated job | |
| - Single `composer.lock` that works on all three versions (project, not | |
| library — locked dependencies only) | |
| ## Constraints | |
| - This is a project, not a library. Don't use `highest`/`lowest` dependency | |
| matrix strategies. Only run against the locked dependencies. | |
| - Don't change PHP code unless there's a genuine syntax incompatibility. | |
| Most 8.5 features (readonly classes, typed constants, first-class | |
| callables) already work on 8.3. | |
| - Daily development continues on 8.5 — the default `app` docker-compose | |
| service stays as 8.5 with xdebug enabled. | |
| ## Exploration first | |
| Before writing any code: | |
| 1. Find sibling project `test-splitter` (or similar) and copy its | |
| multi-version Docker/CI pattern if it exists | |
| 2. Check the current `composer.json` for the PHP constraint | |
| 3. Check current `Dockerfile`, `docker-compose.yml`, `Makefile`, and | |
| `.github/workflows/` for the existing setup | |
| 4. Scan the codebase for any truly 8.5-only syntax (pipe operator `|>`, | |
| property hooks, asymmetric visibility). Most 8.5 "features" are | |
| actually 8.3+ and don't need changing. | |
| ## Implementation plan | |
| ### composer.json | |
| - Update `"php": "~8.5"` to `"php": "8.3.*|8.4.*|8.5.*"` | |
| - Add `config.platform.php = "8.3.0"` so the lock file is pinned to | |
| dependencies compatible with all target versions | |
| - Split `ci` composer script so infection is NOT in it (infection runs | |
| in its own dedicated job) | |
| ### composer.lock | |
| - Regenerate with `composer update --with-all-dependencies` after the | |
| platform pin. Expect major downgrades (e.g. PHPUnit 13 → 12.5, | |
| symfony 8 → 7.4) because 8.4+-only packages get replaced with | |
| 8.3-compatible versions. | |
| ### vendor-bin/*/composer.json (if using bamarni/composer-bin-plugin) | |
| - Add `config.platform.php = "8.3.0"` to EVERY sub-composer file | |
| - Delete each vendor-bin lock file and regenerate | |
| - Watch out for tools with minimum PHP requirements. For example, | |
| `maglnet/composer-require-checker` 4.21+ requires PHP 8.4 — pin to | |
| `^4.20` if needed. | |
| ### Dockerfile | |
| - Parameterise with `ARG PHP_VERSION=8.5` if not already | |
| - Add `ARG XDEBUG_ENABLED=1` and make xdebug installation conditional: | |
| `RUN if [ "$XDEBUG_ENABLED" = "1" ]; then pecl install xdebug && \ | |
| docker-php-ext-enable xdebug; fi` | |
| ### docker-compose.yml | |
| Add per-version services extending the default `app`. Keep xdebug | |
| enabled on ALL of them because CI needs it for coverage: | |
| ```yaml | |
| services: | |
| app: | |
| build: | |
| context: . | |
| args: | |
| PHP_VERSION: "8.5" | |
| tty: true | |
| stdin_open: true | |
| environment: | |
| XDEBUG_MODE: debug | |
| volumes: | |
| - .:/app | |
| - composer-cache:/root/.composer/cache | |
| app-php83: | |
| extends: | |
| service: app | |
| build: | |
| context: . | |
| args: | |
| PHP_VERSION: "8.3" | |
| app-php84: | |
| extends: | |
| service: app | |
| build: | |
| context: . | |
| args: | |
| PHP_VERSION: "8.4" | |
| app-php85: | |
| extends: | |
| service: app | |
| build: | |
| context: . | |
| args: | |
| PHP_VERSION: "8.5" | |
| volumes: | |
| composer-cache: | |
| Makefile (if present) | |
| Add targets: | |
| app/ci-all: app/ci-83 app/ci-84 app/ci-85 | |
| app/ci-83: | |
| @$(DOCKER_COMP) run --rm app-php83 composer ci-local | |
| app/ci-84: | |
| @$(DOCKER_COMP) run --rm app-php84 composer ci-local | |
| app/ci-85: | |
| @$(DOCKER_COMP) run --rm app-php85 composer ci-local | |
| .github/workflows/ci.yml | |
| Rewrite as a matrix + dedicated infection job: | |
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| jobs: | |
| ci: | |
| name: "PHP ${{ matrix.php-version }}" | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| php-version: ['8.3', '8.4', '8.5'] | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: shivammathur/setup-php@v2 | |
| with: | |
| php-version: ${{ matrix.php-version }} | |
| extensions: bcmath, intl, zip | |
| tools: composer:v2 | |
| coverage: xdebug | |
| - uses: ramsey/composer-install@v3 | |
| with: | |
| dependency-versions: locked | |
| - run: composer ci | |
| infection: | |
| name: "Infection (PHP 8.5)" | |
| runs-on: ubuntu-latest | |
| needs: ci | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: shivammathur/setup-php@v2 | |
| with: | |
| php-version: '8.5' | |
| extensions: bcmath, intl, zip | |
| tools: composer:v2 | |
| coverage: xdebug | |
| - uses: ramsey/composer-install@v3 | |
| with: | |
| dependency-versions: locked | |
| - run: composer infection | |
| infection.json5 (if applicable) | |
| If you use PHPStan as infection's static analysis tool, set | |
| "staticAnalysisToolOptions": "--memory-limit=-1" — infection's internal | |
| PHPStan invocation defaults to 128M which OOMs on non-trivial codebases. | |
| README | |
| Update the install instructions to list all three supported versions. | |
| Verification | |
| After all changes, run in order: | |
| 1. make app/ci in the default 8.5 container — sanity check | |
| 2. Build each versioned container: docker compose build app-php83 && docker compose build app-php84 && docker compose build app-php85 | |
| 3. make app/ci-83, make app/ci-84, make app/ci-85 — each must | |
| pass the full CI suite | |
| 4. composer infection on 8.5 — must pass MSI threshold | |
| Common pitfalls to watch for | |
| - Vendor-bin sub-projects DON'T inherit the main config.platform pin. | |
| You MUST add it to each sub-composer.json individually. | |
| - composer bin all install won't regenerate locks — you need update | |
| or delete the lock files first. | |
| - Xdebug must stay ENABLED on all versioned services because the | |
| coverage step needs it. | |
| - Infection's PHPStan runs with its own memory limit independent of | |
| the project's phpstan.neon — configure it in infection.json5. | |
| - Package minimum PHP versions can bite you. Check the error messages | |
| carefully and find older versions that support PHP 8.3. | |
| Out of scope | |
| - Don't backport to PHP 8.2 or earlier | |
| - Don't replace readonly classes with alternatives | |
| - Keep the default development version at 8.5 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment