From dca9db9283d3da315f27c46d054e21d503ce3fd1 Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Wed, 9 Sep 2026 02:15:56 +0200 Subject: [PATCH] fix(test): resolve the PHP vendor tree against a declared floor ebb835d541 raised phpunit/phpunit from ^11.0 to ^13.3. PHPUnit 13 requires PHP >=8.4.1 and ubuntu-latest ships 8.3.6, so composer install could not resolve and test-unit-php failed on every CI run: - phpunit/phpunit[13.3.0, ..., 13.3.2] require php >=8.4.1 -> your php version (8.3.6) does not satisfy that requirement. Nothing in this repository installs a particular PHP. ensure_php_toolchain takes whatever the distro php package is, so the vendor tree was resolved against an ambient interpreter that no file named. A dependency floor above that interpreter is then only discovered by the resolver, on the machine that happens to have the oldest PHP. Declare the floor and resolve against it. config.platform.php binds composer everywhere, including Dependabot; require states the same for readers; the phpunit constraint follows it. Packagist floors: 11 -> >=8.2, 12 -> >=8.3, 13 -> >=8.4.1. Verified in the dev container: the pinned resolution downgrades phpunit 13.3.2 -> 12.5.34 and the suite passes unchanged, 26 tests, 56 assertions. Co-Authored-By: Claude Opus 5 (1M context) --- composer.json | 8 +++++++- utils/install/php.py | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index aba213db28..86e6d05780 100644 --- a/composer.json +++ b/composer.json @@ -3,10 +3,16 @@ "description": "PHPUnit dependencies for the PHP shipped in roles/*/files/php/.", "type": "project", "license": "MIT", + "require": { + "php": ">=8.3" + }, "require-dev": { - "phpunit/phpunit": "^13.3" + "phpunit/phpunit": "^12.0" }, "config": { + "platform": { + "php": "8.3" + }, "sort-packages": true }, "scripts": { diff --git a/utils/install/php.py b/utils/install/php.py index f46a1df4b2..c7fdd71147 100644 --- a/utils/install/php.py +++ b/utils/install/php.py @@ -19,7 +19,7 @@ _PHPUNIT_EXTENSIONS = ("dom", "mbstring", "xmlwriter") def ensure_php_toolchain() -> None: """Install the PHP interpreter, Composer and the extensions PHPUnit needs. - ``phpunit/phpunit ^13`` declares ``_PHPUNIT_EXTENSIONS`` as platform + ``phpunit/phpunit`` declares ``_PHPUNIT_EXTENSIONS`` as platform requirements and Composer refuses to resolve the vendor tree without them, so they are part of the toolchain rather than of the suite consuming it. A distro ships them as packages separate from the interpreter, which is why