From ae71d8ea2c71e14e89efae87ea7bb7cc0f809c63 Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Wed, 26 Aug 2026 02:38:51 +0200 Subject: [PATCH] fix(test): give Composer an archive extractor Without a zip extension or an unzip/7z binary Composer silently drops to --prefer-source and mirror-clones every dependency, which exceeds its 300 s process timeout on phpunit.git. That took the Arch workspace job from a 2m16s test-unit to a 16m08s failure. Debian never saw it because apt pulls php-zip and unzip in as Composer dependencies; pacman does not. Arch ships no zip extension and no php-zip package, so the extractor has to be the unzip binary rather than the extension. Its mapping already covers all five package managers. Co-Authored-By: Claude Opus 5 (1M context) --- tests/unit/python/utils/install/test_php.py | 6 ++++-- utils/install/php.py | 10 +++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/unit/python/utils/install/test_php.py b/tests/unit/python/utils/install/test_php.py index cb9aea3965..a42f8790a0 100644 --- a/tests/unit/python/utils/install/test_php.py +++ b/tests/unit/python/utils/install/test_php.py @@ -18,7 +18,8 @@ class TestEnsurePhpToolchain(unittest.TestCase): ): php_mod.ensure_php_toolchain() self.assertEqual( - [c.args[0] for c in ensure.call_args_list], ["php", "composer"] + [c.args[0] for c in ensure.call_args_list], + ["php", "composer", "unzip"], ) self.assertEqual( [c.args[0] for c in extension.call_args_list], @@ -43,7 +44,8 @@ class TestEnsurePhpPresent(unittest.TestCase): phpunit.is_file.return_value = True php_mod.ensure_php_present() self.assertEqual( - [c.args[0] for c in ensure.call_args_list], ["php", "composer"] + [c.args[0] for c in ensure.call_args_list], + ["php", "composer", "unzip"], ) run.assert_not_called() diff --git a/utils/install/php.py b/utils/install/php.py index cd1e14017c..3bb2414f29 100644 --- a/utils/install/php.py +++ b/utils/install/php.py @@ -25,11 +25,19 @@ def ensure_php_toolchain() -> None: A distro ships them as packages separate from the interpreter, which is why a present ``php`` binary does not imply they are there. + Composer needs an archive extractor for its dist downloads. Without one it + silently falls back to ``--prefer-source`` and mirror-clones every + dependency, which blows its 300 s process timeout on ``phpunit.git``. Arch + ships no zip extension and no ``php-zip`` package, so the extractor has to + be the ``unzip`` binary rather than the extension. + Raises: - RuntimeError: php, composer or one of the extensions is still absent. + RuntimeError: php, composer, unzip or one of the extensions is still + absent. """ ensure_command_present("php") ensure_command_present("composer") + ensure_command_present("unzip") for extension in _PHPUNIT_EXTENSIONS: ensure_php_extension_present(extension)